for循环中字符串的输出根据是否满足某个条件而变化

Output of string in for loop changes depending on whether a certain condition is met

我一直在尝试用 C++ 标记字符串。 我有一个 for 循环,我用它来遍历字符串,如下所示:

for(unsigned int i=0; i < data_str.length(); i++)
{
    tok += data_str[i];
    if(tok[i] == '\n')
    {
        //cout << "NEWLINE" << endl;
        tok = "";
    }
    if(tok == "output:")
    {
        cout << "OUTPUT FOUND" << endl;
        tokens.push_back("output:");
        tok = "";
    }
    cout << tok << endl;
}

如您所见,当找到某个标记 ("output:") 时,我正在重置 tok 变量。然后我将一个字符串添加到我用来存储我的标记的向量中,称为 tokens。为了查看我的标记向量是否具有适当数量的字符串,我将其打印出来。我期望有两个字符串,每个字符串都表示 "output:"。但是,打印矢量时,它只有一个字符串。我做了一些调试,发现每当我在找到标记 "output:" 后尝试重置 tok 变量时,循环只会找到一次字符串 "output:"。然后我决定打印 tok 变量,并得到以下输出:

o
ou
out
outp
outpu
output
OUTPUT FOUND

"
"H
"He
"Hel
"Hell
"Hello
"Hello
"Hello W
"Hello Wo
"Hello Wor
"Hello Worl
"Hello World
"Hello World"
"Hello World"

"Hello World"
o
"Hello World"
ou
"Hello World"
out
"Hello World"
outp
"Hello World"
outpu
"Hello World"
output
"Hello World"
output:
"Hello World"
output:"
"Hello World"
output:"G
"Hello World"
output:"Go
"Hello World"
output:"Goo
"Hello World"
output:"Good
"Hello World"
output:"Goody
"Hello World"
output:"Goodye
"Hello World"
output:"Goodye
"Hello World"
output:"Goodye W
"Hello World"
output:"Goodye Wo
"Hello World"
output:"Goodye Wor
"Hello World"
output:"Goodye Worl
"Hello World"
output:"Goodye World
"Hello World"
output:"Goodye World"
output:string

当我注释掉重置 tok 变量的行时,我得到:

o
ou
out
outp
outpu
output
OUTPUT FOUND
output:
output:"
output:"H
output:"He
output:"Hel
output:"Hell
output:"Hello
output:"Hello
output:"Hello W
output:"Hello Wo
output:"Hello Wor
output:"Hello Worl
output:"Hello World
output:"Hello World"

o
ou
out
outp
outpu
output
OUTPUT FOUND
output:
output:"
output:"G
output:"Go
output:"Goo
output:"Good
output:"Goody
output:"Goodye
output:"Goodye
output:"Goodye W
output:"Goodye Wo
output:"Goodye Wor
output:"Goodye Worl
output:"Goodye World
output:"Goodye World"
output:string
output:string

为什么我的循环只有在我不尝试重置 tok 变量时才能正常工作?我必须重置变量,否则程序的其他部分将无法运行。是否有重置我的 tok 变量的替代解决方案?

很明显tok是一个std::string,所以:

for(unsigned int i=0; i < data_str.length(); i++)
    {
        tok += data_str[i];
        if(tok[i] == '\n')
        {
            //cout << "NEWLINE" << endl;
            tok = "";
        }

让我们用纸和笔,按照解析算法的这一部分进行操作。假设 data_str 由以下文本组成:

"hello\nworld"

data_str[5] 附加到 tok 之后,tok 现在包含 "hello\n",因为 tok[5]'\n',tok 得到清除为空字符串。

在下一次迭代中,data_str[6] 被附加到一个空的 tok,因此 tok 现在只包含一个 "w"(因为它在上一次迭代中被清除了循环)。

 if(tok[i] == '\n')

i 现在是 6。这会检查 tok[6]。当然,tok只有一个字符。这会导致未定义的行为和无意义的结果。

从现在开始,rails 的事情就大不一样了。

如果此处的目的是在每个换行符后清除 tok 缓冲区,请检查 tok 的最后一个字符,即 tok[tok.size()-1],而不是 tok[i] ,因为 itok 的大小完全没有任何关系。