cpp 文件中的部分行最终出现在输出文件中 - 闹鬼的代码
Partial line from cpp file ending up in output file - haunted code?
很抱歉,要制作一个完全可重现的错误版本是非常困难的---所以请裸露我的原理图代码。
该程序从网页检索信息,对其进行处理,并将输出保存到 ASCII 文件中。 我还有一个"日志"文件(FILE *theLog
---包含在Manager
对象中)用于报告错误等。
一些后台方法:
// Prints string to log file
void Manager::logEntry(const string lstr) {
if( theLog != NULL ) { fprintf(theLog, "%s", lstr.c_str()); }
}
// Checks if file with given name already exists
bool fileExists(const string fname) {
FILE *temp;
if( temp = fopen(fname.c_str(), "r") ) {
fclose(temp);
return true;
} else { return false; }
}
// Initialize file for writing (some components omitted)...
bool initFile(FILE *&oFile, const string fname) {
if(oFile = fopen(fname.c_str(), "w") ) { return true; }
else { return false; }
}
造成麻烦的东西:
// Gets data from URL, saves to file 'dataFileName', input control flag 'foreCon'
// stu is some object that has string which i want
bool saveData(Manager *man, Stuff *stu, string dataFileName, const int foreCon) {
char logStr[CHARLIMIT_LARGE]; // CHARLIMIT_LARGE = 2048
sprintf(logStr, "Saving Data...n");
man->logEntry( string(logStr) ); // This appears fine in 'theLog' correctly
string data = stu->getDataPrefixStr() + getDataFromURL() + "n"; // fills 'data' with stuff
data += stu->getDataSuffixStr();
if( fileExists(dataFileName) ) {
sprintf(logStr, "save file '%s' already exists.", dataFileName.c_str() );
man->logEntry( string(logStr) );
if( foreCon == -1 ) {
sprintf(logStr, "foreCon = %d, ... exiting.", foreCon); // LINE 'A' : THIS LINE ENDS UP IN OUTPUT FILE
tCase->logEntry( string(logStr) );
return false;
} else {
sprintf(logStr, "foreCon = %d, overwriting file.", foreCon); // LINE 'B' : THIS LINE ENDS UP IN LOG FILE
tCase->logEntry( string(logStr) );
}
}
// Initialize output file
FILE *outFile;
if( !initFile(outFile, dataFileName) ) {
sprintf(logStr, "couldn't initFile '%s'", dataFileName.c_str());
tCase->logEntry( string(logStr) );
return false;
}
fprintf(outFile, "%s", data.c_str()); // print data to output file
if( fclose(outFile) != EOF) {
sprintf(logStr, "saved to '%s'", dataFileName.c_str());
tCase->logEntry( string(logStr) );
return true;
}
return false;
}
如果文件已经存在,并且 ' int foreCon
= -1' 则代码应将行 'A' 打印到日志文件中。 如果文件存在且foreCon
!= -1,则旧文件将被 data
覆盖。 如果文件不存在,则会创建该文件,并将数据写入其中。
但是,结果是数据文件中出现了行"A"的分解版本,而日志文件中打印了行"B"!!!
数据文件的外观:
.. exiting.20130127 161456
20130127 000000,55,17,11,0.00
20130127 010000,54,17,11,0.00
... ...
第二行及以后看起来是正确的,但还有一行包含行"A"的一部分。
现在,非常奇怪的部分。 如果我注释掉if( foreCon == -1) { ... }
块中的所有内容,则数据文件如下所示:
%d, ... exiting.20130127 161456
20130127 000000,55,17,11,0.00
20130127 010000,54,17,11,0.00
... ...
仍然有一行额外的行,但它是复制到数据文件中的文字代码。
我认为我的代码中有一个恶作剧者。 我不明白这些怎么会发生。
编辑:我尝试打印以控制台data
字符串,它给出了相同的混乱值:即 %d, ... exiting.20130127 161456
- 所以它一定是关于string
而不是FILE *
根据您的最新评论回答:
getDataPrefixStr() 最终返回一个以 类似于字符串 retStr = COMCHAR + " 在...上创建的文件";这样 const char COMCHAR = '#';.COMCHAR会是问题吗?
你不能像那样添加字符和字符串文字(它们是 char
的数组,而不是 string
s)。
您要将 35("#"的 ASCII)添加到" 在 ...",即getDataPrefixStr()是从该字符串的开头开始的35个字符。由于所有文本字符串都一起存储在同一个数据区域中,因此您将在输出中从程序中获取字符串。
相反,你冷淡地做
const string COMCHAR = "*";
string retStr = COMCHAR + " file created on ...";
logStr
太短,导致数据在其他缓冲区中被覆盖(您是否仔细检查CHARLIMIT_LARGE
?您可以通过将所有写入注释到logStr
(sprintf
)来诊断此问题,并查看data
是否仍然损坏。通常,如果用户可以将 dataFileName
(设置为很长的字符串),则您的代码容易受到此影响;请改用snprintf
或ostringstream
。
否则,我会猜测stu->getDataPrefixStr()
或getDataFromURL()
返回损坏的结果或返回类型 char*
而不是 string
.尝试将这些值直接打印到控制台,以查看它们是否已损坏。如果它们返回一个char*
,则data = stu->getDataPrefixStr() + getDataFromURL()
将具有未定义的行为。
if( temp = fopen(fname.c_str(), 'r') ) {
应该是
if( temp = fopen(fname.c_str(), "r") ) {
- 如何在 的开头<x>和结尾<y>之间更改带有文件输出的字符串的值
- C++对象数组的文件输出
- bcdedit 文件输出不起作用,但其他命令可以
- 如何从文本文件输出数据?(学生成绩单计划)
- 使用 C++文件 I/O 输出 pdf 文件
- C 文件输出垃圾
- 从堆栈中读取字符后,如何修复不正确的文件输出
- C++:具有随机名称的文件输出
- 在命令提示符下看到换行符,但在文件输出中可以看到 相同的字符串
- 生成文件不会生成预期的文件输出
- C++11 fgetc 在"r+b"模式下使用时向我的文件输出 0
- 使用函数从文件输出
- GCC.obj文件输出不具有确定性(.debug_info,PROGPITS部分)
- C cstdiofile :: Writestring给出了不正确的文件输出
- C 输出:STD :: COUT和文件输出没有相同的内容
- GCC和MSVC之间的文件输出不一致
- C++文件输出奇怪的数字,并且部分代码没有运行
- 如何将特定字符从TXT文件输出到特定点
- C 调用从TXT文件输出信息的函数
- 将交易从文本文件输出到屏幕