在下面的 C++ 代码中,我意识到 gcount() 返回的数字比我想要的要大,因为 getline() 消耗最后的换行符,但不将其发送到输入流。

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

#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;
}
有帮助吗?

解决方案

我还复制了这个结果,Windows Vista,Visual Studio 2005 SP2。

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

编辑: :好的,我们开始吧。问题(以及人们得到的不同结果)来自 。发生的事情是你打电话 input.getline 并将结果放入 vecBuffer 中。getline 函数去掉 ,但保留 。

然后,您将 vecBuffer 传输到字符串变量,但使用输入中的 gcount 函数,这意味着您将获得过多的一个字符,因为输入变量仍然包含 ,而 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

然后打印“Test”,然后是回车符(将光标放回行首)、空字符(覆盖 T),最后是 ,它正确地将光标放在新行上。

因此,您要么必须去掉 ,要么编写一个直接从 vecBuffer 获取字符串长度的函数,检查是否有空字符。

其他提示

我复制一个Windows XP专业版的Service Pack 2系统,使用Visual Studio 2005 SP2编译的代码上汤米的问题,建成一个控制台项目(实际上,它“版本8.0.50727.879”说的)。

如果我的test.txt文件只包含“测试”和CR,程序吐出“EST”(注意前导空格)时运行。

如果我不得不采取胡乱猜测,我会说,这个版本的实现具有在那里治疗的Windows换行符像它应该在Unix中被视为一个bug(作为“去的前同一行”的字符),然后将其擦除出的第一个字符,以保持下一个提示或东西的一部分。


<强>更新 用它打了一下后,我肯定是发生了什么事。如果您在调试器看strResult,你会看到它在年底复制十进制13值。这是CR,它在Windows的土地是“\ n”,和其他地方的“回到行的开始”。如果我不是改变你的构造函数如下:

的字符串strResult(vecBuffer.begin(),vecBuffer.begin()+ input.gcount() - 1);

...(这样CR是不可复制的),那么它打印出“测试”像你期望的那样。

我敢肯定的是,T为实际获取写入,然后覆盖。在的rxvt窗口(Cygwin的)运行同一程序产生预期的输出。你可以做两件事情。如果您摆脱的ios ::在您打开二进制它会自动转换\ r \ n转换为\ n和事情会像你期望的那样。

您可以在二进制编辑器中通过单击打开文件对话框的打开按钮的小向下箭头并选择具有...->二进制编辑器中打开也打开你的文本文件。这将让你看看你的文件,并确认它确实有\ r \ n和不只是的\ n

修改 我重定向输出到文件中,它是写出:

Test\r\0\r\n

原因你所得到的\ 0是,gcount的返回6(6个字符被从物流中除去),但最终的分隔符不会被复制到缓冲器中,“\ 0”是代替。当你正在建设的字符串,你实际上是告诉它包括“\ 0”。的std :: string有嵌入的0没有问题,将其作为问道。一些炮弹显然输出空白字符并覆盖T,而其他人没有做任何事情,输出看起来不错,但仍可能是错误的,因为它已经嵌入的“\ 0”

cout << strResult.c_str() << "\n";

最后一行更改为这将停止对\ 0,并且还获得输出预期。

我使用Windows XP专业版SP3(32位)的Visual Studio 2005 SP2测试你的代码,一切工作正常。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top