我正在从由不同子字符串组成的一行中按;
除以该顺序读取美味食谱:
R1
)1
)Ensalada Mixta
)Lechuga 200;...
)前三个工作就像吊饰一样,您可以看到它们存储在
data
数组中并打印在printf
块中。问题出在阅读其余部分。 reader
迭代器可完美读取该行,但不会在结尾处停止,因此它将垃圾值添加到该对中并引发段错误。这是此MRE的输出::: R1
:: 1
:: Ensalada Mixta
-> Lechuga 200
-> Tomate 50
-> Pepino 50
-> Cebolla 50
-> Aceite Oliva 5
-> Vinagre De Vino 10
-> Sal 1
[1] 85313 segmentation fault (core dumped)
循环应该在
Sal 1
之后停止,那么我该怎么办呢?这是代码:#include <cmath>
#include <list>
#include <string>
#include <utility>
#include <cstdio>
using namespace std;
int main () {
string line = "R1;1;Ensalada Mixta;Lechuga 200;Tomate 50;Pepino 50;Cebolla 50;Aceite Oliva 5;Vinagre De Vino 10;Sal 1";
list<pair<string, unsigned> > ings;
string recipe_data[3];
string::const_iterator reader = line.cbegin();
//Lectura del código, plato y ing_name de la receta
for (int i = 0; i < 3; ++reader) {
if (*reader != ';')
recipe_data[i].push_back(*reader);
else
++i;
}
printf(":: %s\n", recipe_data[0].c_str());
printf(":: %s\n", recipe_data[1].c_str());
printf(":: %s\n", recipe_data[2].c_str());
/*
* This is the problematic loop. The problem is in the while boolean
* expression, which always evaluates to false.
*/
while (reader != line.cend()) {
string ing_name = "";
unsigned ing_quantity = 0;
while (*reader != ';' && reader != line.cend()) {
ing_name += *reader;
++reader;
}
string::reverse_iterator it = ing_name.rbegin();
for (int i = 0; *it != ' '; i++) {
char c[1] = {*it};
ing_quantity += atoi(c) * pow(10, i);
++it;
ing_name.pop_back();
}
ing_name.pop_back();
pair<string, unsigned> ing(ing_name, ing_quantity);
ings.push_back(ing);
printf("-> %s %d\n", ing.first.c_str(), ing.second);
++reader;
}
}
以下是在最后
++reader
行上使用断点的gdb输出:Breakpoint 1, main () at so.cpp:52
52 ++reader;
1: reader = 59 ';'
2: line.cend() = 0 '\000'
3: ing = {first = "Tomate", second = 50}
(gdb)
Continuing.
-> Pepino 50
Breakpoint 1, main () at so.cpp:52
52 ++reader;
1: reader = 59 ';'
2: line.cend() = 0 '\000'
3: ing = {first = "Pepino", second = 50}
(gdb)
Continuing.
-> Cebolla 50
Breakpoint 1, main () at so.cpp:52
52 ++reader;
1: reader = 59 ';'
2: line.cend() = 0 '\000'
3: ing = {first = "Cebolla", second = 50}
(gdb)
Continuing.
-> Aceite Oliva 5
Breakpoint 1, main () at so.cpp:52
52 ++reader;
1: reader = 59 ';'
2: line.cend() = 0 '\000'
3: ing = {first = "Aceite Oliva", second = 5}
(gdb)
Continuing.
-> Vinagre De Vino 10
Breakpoint 1, main () at so.cpp:52
52 ++reader;
1: reader = 59 ';'
2: line.cend() = 0 '\000'
3: ing = {first = "Vinagre De Vino", second = 10}
(gdb)
Continuing.
-> Sal 1
Breakpoint 1, main () at so.cpp:52
52 ++reader;
1: reader = 0 '\000'
2: line.cend() = 0 '\000'
3: ing = {first = "Sal", second = 1}
(gdb) n
47 pair<string, unsigned> ing(ing_name, ing_quantity);
1: reader = 0 '\000'
2: line.cend() = 0 '\000'
3: ing = {first = "Sal", second = 1}
(gdb)
29 string ing_name = "";
1: reader = 0 '\000'
2: line.cend() = 0 '\000'
3: ing = {first = "Sal", second = 1}
(gdb)
28 while (reader != line.cend()) {
1: reader = 0 '\000'
2: line.cend() = 0 '\000'
(gdb)
29 string ing_name = "";
1: reader = 0 '\000'
2: line.cend() = 0 '\000'
3: ing = {first = "Sal", second = 1}
如您所见,由于迭代器和
cend()
相等,因此它不应该重新进入循环,对吗? 最佳答案
内部while会递增,直到找到;
或cend
,然后在两种情况下都继续。仅在下一次迭代时,您才停止,因为reader != line.cend()
是false
,但这已经太迟了。
另外,您必须首先检查您是否在结尾处,然后才取消引用reader
:
while (reader != line.cend() && *reader != ';') {
ing_name += *reader;
++reader;
}
if (reader == line.cend()) break;