2013-10-08 86 views
0

我有一个问题,我不知道如何解决它。 的问题是:C++垃圾在文件末尾

char * ary = new Char[]; 

ifstream fle; 
fle.open(1.txt, ios_base::binary); 
fle.seekg(fle.end); 
long count = fle.tellg(); 
fle.seek(fle.beg); 

现在的问题是: 文件1.txt的包含:你好世界!

当我执行:

ary = new char(count); 
fle.read(ary, count); 

充满这样的进制:世界,你好! @T#^ @ $ @ FF(垃圾)

该文件在ookay里面没有任何东西,只有上面的内容。

平台:Win 7,VS 2012

不知道如何来解决这个问题。 (已解决)

(问题2) 现在我面临另一个问题,fle.read有时阅读比我给的尺寸更多。例如,如果我通过像fle.read(缓冲,1000),它在某些情况下结束(strlen的(缓冲)= 1500。我怎样才能解决这个问题?

问候,

+0

它不是在文件中,这是您的分配内存的一部分。在做任何事之前尝试将数组置空。即'ary = new char(count); memset(ary,0,count); fle.read(ary,count);',对于memset,如果你还没有它,你还需要'#include '。 – bizzehdee

+2

为什么你打开二进制文件? – crashmstr

+0

并且count中有一个“o”。 – crashmstr

回答

3

我认为你的问题不是你的数组包含垃圾,而是你忘记把null结束符放在最后,而你的print语句不知道什么时候停止。您也写了new char(count)而不是new char[count]。在第一种情况下,您只能实例化一个char,其值为count,而在第二种情况下,您将创建一个count字符的缓冲区。

试试这个:

ary = new char[count+1]; 
fle.read(ary, count); 
ary[count] = '\0'; 
+0

谢谢你做了我想要的,对于我而不是增加缓冲区,我只是做了[count -1] ='\ 0',否则我将不得不改变接收缓冲区大小,如果没有错的话。 – nothing

+0

如果你做'ary [count-1] ='\ 0'',你将失去最后一个字节。 –

+0

是的,但我改变了阅读大小为-1,所以我可以保持该字节为空。 现在我面临着另一个问题,fle.read有时阅读比我给的尺寸更多。例如,如果我像fle.read(目的地,1000)那样通过,它在某些情况下结束1500.我该如何解决这个问题? – nothing

1

我们必须在这里估计了一下,但最有可能这个归结为你调试的问题。缓冲区填写正确,但错误地检查其内容。

现在,ary被声明为char*,我怀疑,当你试图检查的内容ary你使用了一些打印方法,该方法需要一个以null结束的数组,但是你并没有终止该数组,所以你有一个缓冲区溢出

如果您只打印了count个字符,那么您就不会超支。如果你有空终止数组,也不会忘记为空终止符分配一个额外的字符。

而不是使用原始数组和new,将缓冲区读入std::string会更有意义。您应尽量避免使用以空字符结尾的字符串。在与非C++库互操作时使用这些。

5

char [] - C中的字符串通常以null结尾。它们比所需的长一个字节,最后一个字节设置为0x00。这是必要的,因为C无法告诉数组的长度。

当您从文件中读取二进制数据时,不会在字符串中读入终止空字符。这意味着像printf这样的函数对未知长度的char数组进行操作将输出该数组以及在内存中发生的任何数据,直到它遇到空字符。

解决方案:分配char [] - 缓冲区比数据长度长一个字节,并手动将最后一个字节设置为0

更好的解决方案:不要使用C风格的字符数组。做到面向对象的方式,并使用类std::string来表示字符串。

0

试试这个

ary = new char[count + 1]; 
fle.read(ary,count); 
ary[count] = '\0'; 

终止空字符不见了 - 它不是在文件中,你必须将它添加之后

0

你正在阅读count字符为一个文件,你必须分配一个额外的字符来提供字符串终止符(\0)。

ary = new char[count + 1]; 
ary[count] = '\0'; 
+0

这仍然只分配一个'char'。 (当然,他真正需要的是'std :: vector ary(count + 1);'。) –

+0

对。纠正。 –

2

大多数其他的答案错过一个非常重要的一点: 当你做你ary = new char(count);分配与ASCII码count一个符号初始化一个字符。 你应该这样写:ary = new char[count + 1];

+0

两个尼特(因为你不像所有其他人都有正确的答案):这里没有涉及ASCII。 'char'只是另一种小整数,并且用'count'的整数值初始化它(当然转换为'char')。而他应该写的更多的是'std :: vector ary(count +1);'。 –

+0

@詹姆斯为什么没有涉及ASCII?当你写'char(32)'时,你会在里面得到一个空间,因为32是空间的ASCII码,不是吗? –

+0

输出结果取决于输出设备。你如何解读它取决于你;如果你把它解释为一个字符,并且32是你正在使用的编码中空间的代码点(这可能是这种情况,即使ASCII本身已经死了,并且没有在任何地方使用),那么你会解释它作为一个空间。但最后,'char'是一个整数数据类型,它保存了整数值。在像'new char(count)'这样的表达式中,没有什么可以说'count'应该被解释为一个代码点,而不是一个普通的整数值。 –

2

好了,最明显的问题是,你正在使用 new char(count),它分配一个char分配,与count初始化 。你可能试图做的是new char[count]。你真正需要的是:

std::vector<char> arr(count); 
fle.read(&arr[0], count); 
在分配

或许count + 1,如果你想在缓冲区尾 '\0'

编辑:

既然你仍然有问题:fle.read永远不会读 超过要求。在 阅读之后fle.gcount()返回什么?

如果你这样做:

std::vector<char> arr(count); 
fle.read(&arr[0], count); 
arr.resize(fle.gcount()); 

你应该有与char是 您已经阅读完全数的向量。如果您希望将它们作为字符串,则可以从arr.begin(), arr.end()构造一个 ,或者甚至可以使用std::string 而不是std::vector<char>开始。

如果你需要一个'\0'结尾的字符串(与 旧版软件界面),那么您只需建立矢量大小为 count + 1,而不是count,并&arr[0]将是你 '\0'字符串。

不是尝试在这里使用new char[count]。 要做到这一点非常困难。 (例如,它将需要一个尝试块 和一个捕获。)