我有一个问题我无法理解它是如何存在的。
我有一堆按时间排序并包含一堆对象的文件。结果应该是每个对象的目录中每次排序一个文件。
它工作得很好但是在我将Outputstring
转换为char[]
以使用fstream.open()
时,数组的字符数比字符串多3个字符。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int main()
{
string strOutput;
char *OutputFile;
short z;
strOutput = "/home/.../2046001_2013-02-25T0959.txt";
cout << strOutput << endl;
OutputFile = new char[strOutput.length()];
z = 0;
while (z < strOutput.length())
{
OutputFile[z] = strOutput[z];
z++;
}
cout << OutputFile << endl;
return 0;
}
第一个输出始终是正确的,但第二个输出有时结束.txt60A
,.txt5.a
或.txt9.A
。
当它发生时,它始终是相同的对象和时间,每次尝试都会发生。但并非每个对象都这样做。
由于显而易见的原因,我无法在这个最小的代码片段中重现此错误,但我也不想发布整个390行代码。
你有什么建议吗?
答案 0 :(得分:4)
您缺少在C字符串末尾终止null。修复:
OutputFile = new char[strOutput.length() + 1]; // notice +1
z = 0;
while (z < strOutput.length())
{
OutputFile[z] = strOutput[z];
z++;
}
OutputFile[z] = 0; // add terminating 0 byte
当然有更好的方法来完成整个事情......你根本不需要复制,只需要摆脱OutputFile
和整个循环,并使用{{{}内的char数组1}}:
std::string
我认为真正的代码需要一个C字符串。 cout << strOutput.c_str() << endl;
可以直接打印std::cout
,当然:
std::string
如果您确实想要创建副本,最好只复制cout << strOutput << endl;
并存储它,并在需要时使用c_str-method获取C缓冲区:
std::string
如果你知道你真的做需要从堆分配的原始字符数组,你应该使用string OutputFile = strOutput;
(或者可能是其他一些C ++智能指针类)来包装指针,所以你不需要手动删除并避免内存泄漏,也可以使用标准库函数进行复制:
std::unique_ptr
...
#include <memory>
#include <cstring>
答案 1 :(得分:1)
Char数组需要额外的空字符或\0
附加到结尾,否则读取字符串的代码将运行到数组的末尾,直到找到它为止。
OutputFile = new char[strOutput.length() + 1];
z = 0;
while (z < strOutput.length())
{
OutputFile[z] = strOutput[z];
z++;
}
OutputFile[z] = '\0';
如果数组后面的下一个字节恰好为空,它似乎可以工作,但这只是巧合。我确信这就是你的代码在第一次通过时的原因。
答案 2 :(得分:0)
我将Outputstring转换为char []以使用fstream.open()
你不必这样做。做这样的事情:
outfile.open(Outputstring.c_str(), std::fstream::out)
当然,如果你有一个符合C ++ 11的编译器,你可以这样做:
outfile.open(Outputstring, std::fstream::out)