Для чего это стоит, вот моя реализация. Он имеет дело с вводом wstring, но может быть легко скорректирован. Он не обрабатывает новую строку в полях (так как мое приложение тоже не работает, но добавление его поддержки не слишком сложно), и оно не соответствует концу строки «\r\n» в соответствии с RFC (если вы используете std :: getline), но он корректно обрабатывает пробелы и двойные кавычки (надеюсь).
using namespace std;
// trim whitespaces around field or double-quotes, remove double-quotes and replace escaped double-quotes (double double-quotes)
wstring trimquote(const wstring& str, const wstring& whitespace, const wchar_t quotChar)
{
wstring ws;
wstring::size_type strBegin = str.find_first_not_of(whitespace);
if (strBegin == wstring::npos)
return L"";
wstring::size_type strEnd = str.find_last_not_of(whitespace);
wstring::size_type strRange = strEnd - strBegin + 1;
if((str[strBegin] == quotChar) && (str[strEnd] == quotChar))
{
ws = str.substr(strBegin+1, strRange-2);
strBegin = 0;
while((strEnd = ws.find(quotChar, strBegin)) != wstring::npos)
{
ws.erase(strEnd, 1);
strBegin = strEnd+1;
}
}
else
ws = str.substr(strBegin, strRange);
return ws;
}
pair<unsigned, unsigned> nextCSVQuotePair(const wstring& line, const wchar_t quotChar, unsigned ofs = 0)
{
pair<unsigned, unsigned> r;
r.first = line.find(quotChar, ofs);
r.second = wstring::npos;
if(r.first != wstring::npos)
{
r.second = r.first;
while(((r.second = line.find(quotChar, r.second+1)) != wstring::npos)
&& (line[r.second+1] == quotChar)) // WARNING: assumes null-terminated string such that line[r.second+1] always exist
r.second++;
}
return r;
}
unsigned parseLine(vector<wstring>& fields, const wstring& line)
{
unsigned ofs, ofs0, np;
const wchar_t delim = L',';
const wstring whitespace = L" \t\xa0\x3000\x2000\x2001\x2002\x2003\x2004\x2005\x2006\x2007\x2008\x2009\x200a\x202f\x205f";
const wchar_t quotChar = L'\"';
pair<unsigned, unsigned> quot;
fields.clear();
ofs = ofs0 = 0;
quot = nextCSVQuotePair(line, quotChar);
while((np = line.find(delim, ofs)) != wstring::npos)
{
if((np > quot.first) && (np < quot.second))
{ // skip delimiter inside quoted field
ofs = quot.second+1;
quot = nextCSVQuotePair(line, quotChar, ofs);
continue;
}
fields.push_back( trimquote(line.substr(ofs0, np-ofs0), whitespace, quotChar) );
ofs = ofs0 = np+1;
}
fields.push_back( trimquote(line.substr(ofs0), whitespace, quotChar) );
return fields.size();
}
Я бы просто использовал одну переменную для управления приращением цикла for:
for (i=0; menu_statetop[i].state; i++)
В ответ на Weather Vane вы можете обработать смещение индекса массива в теле цикла for. Это намного яснее и надежнее.
Я также был бы осторожен с переменной, которую вы используете в качестве условия для цикла for. в вашем коде вы используете переменную menu_statetop [i] .state, которая выглядит как целое число / enum. Если бы не было "перерыва"; в цикле цикл for будет выполняться до тех пор, пока значение, содержащееся в menu_statetop [i] .state, не равно 0.
Вместо грязного int a
и т. Д. Вы можете сделать
menu_statetop[(i + 1) % 5].pText;
menu_statetop[(i + 2) % 5].pText;
menu_statetop[(i + 3) % 5].pText;
и т. Д.
РЕДАКТИРОВАТЬ: Это также заботится о переполнении меню, гарантируя, что оно «оборачивается» обратно к началу. Помимо доступа к следующему пункту (пунктам) меню с помощью i + 1
и т. Д. Для этого используется оператор модуля (или остатка) %
.