Возможный дубликат:
Разделение строки в C ++
Я пытаюсь создать функцию, которая имитирует поведение getline()
функция, с возможностью использовать разделитель для разделения строки на токены.
Функция принимает 2 строки (вторая передается по ссылке) и char
тип для разделителя. Он проходит по каждому символу первой строки, копирует его во вторую строку и останавливает цикл, когда достигает разделителя. Возвращается true
если первая строка содержит больше символов после разделителя и false
иначе. Позиция последнего символа сохраняется в статической переменной.
по какой-то причине программа входит в бесконечный цикл и ничего не выполняет:
const int LINE_SIZE = 160;
bool strSplit(string sFirst, string & sLast, char cDelim) {
static int iCount = 0;
for(int i = iCount; i < LINE_SIZE; i++) {
if(sFirst[i] != cDelim)
sLast[i-iCount] = sFirst[i];
else {
iCount = i+1;
return true;
}
}
return false;
}
Функция используется следующим образом:
while(strSplit(sLine, sToken, '|')) {
cout << sToken << endl;
}
Почему это входит в бесконечный цикл, и почему это не работает?
Я должен добавить, что я заинтересован в решении без использования istringstream
, если это возможно.
Это не совсем то, что вы просили, но рассматривали ли вы std::istringstream
а также std::getline
?
// UNTESTED
std::istringstream iss(sLine);
while(std::getline(iss, sToken, '|')) {
std::cout << sToken << "\n";
}
РЕДАКТИРОВАТЬ:
Почему это входит в бесконечный цикл, и почему это не работает?
Мы не можем знать, вы не предоставили достаточно информации. Попробуйте создать SSCCE и опубликуйте это.
я Можно скажу вам, что следующая строка очень подозрительна:
sLast[i-iCount] = sFirst[i];
Эта строка приведет к неопределенному поведению (включая, возможно, то, что вы видели) в любом из следующих условий:
i >= sFirst.size()
i-iCount >= sLast.size()
i-iCount < 0
Мне кажется вероятным, что все эти условия выполняются. Если переданная строка, например, короче 160 строк, или если iCount
когда он станет больше, чем смещение первого разделителя, вы получите неопределенное поведение.
LINE_SIZE
вероятно, больше, чем количество символов в string
объект, поэтому код запускается из конца хранилища строки, и почти все может произойти.
Вместо того, чтобы кататься самостоятельно, string::find
делает то, что вам нужно
std::string::size_type pos = 0;
std::string::size_type new_pos = sFirst.find('|', pos);
Призыв к find
находит первое вхождение ‘|’ это в или после позиции «pos». Если это успешно, он возвращает индекс ‘|’ что он нашел. Если это не удается, он возвращает std::string::npos
, Используйте его в цикле, и после каждого совпадения копируйте текст из [pos, new_pos) в целевую строку и обновляйте pos
в new_pos + 1
,
Вы уверены, что это strSplit()
функция, которая не возвращает или это ваш вызывающий while
цикл это бесконечно?
Не должен ли ваш цикл вызова быть чем-то вроде:
while(strSplit(sLine, sToken, '|')) {
cout << sToken << endl;
cin >> sLine >> endl;
}
— редактировать —
если значение sLine
таков, что делает strSplit()
чтобы вернуть истину, то while
цикл становится бесконечным .. поэтому сделайте что-нибудь, чтобы изменить значение sLine
для каждой итерации цикла, например положить в cin
..
Проверь это
std::vector<std::string> spliString(const std::string &str,
const std::string &separator)
{
vector<string> ret;
string::size_type strLen = str.length();
char *buff;
char *pch;
buff = new char[strLen + 1];
buff[strLen] = '\0';
std::copy(str.begin(), str.end(), buff);
pch = strtok(buff, separator.c_str());
while(pch != NULL)
{
ret.push_back(string(pch));
pch = strtok(NULL, separator.c_str());
}
delete[] buff;
return ret;
}