为什么我的弦的开头消失了?

Tom*_*ert 6 c++ string cout vector

在下面的C++代码中,我意识到gcount()返回的数字比我想要的更多,因为它getline()消耗了最终的换行符,但是没有将它发送到输入流.

但我仍然不明白的是程序的输出.对于输入"Test \n",为什么我得到"est \n"?为什么我的错误会影响字符串的第一个字符,而不是在末尾添加不需要的垃圾?为什么程序的输出与字符串在调试器中的显示方式不一致("Test \n",正如我所期望的那样)?

#include <fstream>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

int main()
{
    const int bufferSize = 1024;
    ifstream input( "test.txt", ios::in | ios::binary );

    vector<char> vecBuffer( bufferSize );
    input.getline( &vecBuffer[0], bufferSize );
    string strResult( vecBuffer.begin(), vecBuffer.begin() + input.gcount() );
    cout << strResult << "\n";

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ais*_*ina 12

我也复制了这个结果,Windows Vista,Visual Studio 2005 SP2.

当我弄清楚到底发生了什么时,我会更新这篇文章.

编辑:好的,我们去吧.问题(以及人们得到的不同结果)来自\ r \n.如果您调用input.getline并将结果放入vecBuffer,会发生什么.getline函数剥离\n,但将\ r留在原位.

然后将vecBuffer转换为字符串变量,但是使用输入中的gcount函数,这意味着你将得到一个char太多,因为输入变量仍包含\n,而vecBuffer不包含.

由此产生的strResult是:

-       strResult   "Test"
        [0] 84 'T'  char
        [1] 101 'e' char
        [2] 115 's' char
        [3] 116 't' char
        [4] 13 '?'  char
        [5] 0   char
Run Code Online (Sandbox Code Playgroud)

那么然后打印"Test",然后是回车(将光标放回到行的开头),空字符(覆盖T),最后是\n,它正确地将光标放在新行上.

所以你要么必须删除\ r,要么写一个直接从vecBuffer获取字符串长度的函数,检查空字符.


T.E*_*.D. 6

我在Windows XP Pro Service Pack 2系统上复制了Tommy的问题,使用Visual Studio 2005 SP2编译的代码(实际上,它说"版本8.0.50727.879"),作为控制台项目构建.

如果我的test.txt文件只包含"Test"和CR,则程序在运行时会吐出"est"(注意前导空格).

如果我不得不采取疯狂的猜测,我会说这个版本的实现有一个错误,它正在处理Windows换行符,就像它应该在Unix中处理(作为"走到同一行的前面"然后它会清除第一个字符以保存下一个提示的一部分或其他内容.


更新: 玩了一下后,我很肯定这是正在发生的事情.如果你在调试器中查看strResult,你会看到它在末尾复制了十进制13的值.那是CR,在Windows-land中是'\n',其他地方都是"回到行的开头".如果我改为你的构造函数来读取:

string strResult(vecBuffer.begin(),vecBuffer.begin()+ input.gcount() - 1);

...(这样CR不会被复制)然后打印出"测试",就像你期望的那样.