为何sscanf在文件读取作用域内解析失败,移出后正常?
为什么将sscanf放在文件读取的if块内会解析失败?
我遇到一个奇怪的问题:下面的代码中,第一种写法把sscanf放在文件读取的if代码块外时,op和lc能正确获取整数值,解析正常;但第二种写法把sscanf放在if块内时,解析总是失败,op和lc始终为0。之前把文件输入数据传入sscanf的解析函数时工作正常,请问哪里出问题了?
代码示例
写法一(看似正常)
#include <stdio.h> #include <windows.h> #include <string> void readFromFile() { char buff[100]; int op = 0; int lc = 0; char st[25]; FILE *cmdBuffer; std::string CMDFILE = "C:\testFile.txt"; // 示例测试文件内容:50 0005 SomeString //----- 此写法正常,op和lc能正确获取整数值 cmdBuffer = fopen(CMDFILE.data(), "r"); if (cmdBuffer != NULL) { fgets(buff, sizeof(buff), cmdBuffer); fclose(cmdBuffer); } sscanf(buff, "%d %d %s", &op, &lc, st); printf(" %d %d %s\n", op, lc, st); }
写法二(解析失败)
#include <stdio.h> #include <windows.h> #include <string> void readFromFile() { char buff[100]; int op = 0; int lc = 0; char st[25]; FILE *cmdBuffer; std::string CMDFILE = "C:\testFile.txt"; // 示例测试文件内容:50 0005 SomeString //----- 此写法始终失败 ---- cmdBuffer = fopen(CMDFILE.data(), "r"); if (cmdBuffer != NULL) { fgets(buff, sizeof(buff), cmdBuffer); sscanf(buff, "%d %d %s", &op, &lc, st); fclose(cmdBuffer); } printf("%d %d %s\n", op, lc, st); // sscanf失败后op和lc始终为0 }
问题根源
- 文件路径转义错误:代码中
std::string CMDFILE = "C:\testFile.txt";里的\t是C/C++的转义字符,代表制表符,实际生成的路径是C: estFile.txt,这个文件并不存在,导致fopen始终失败。 - 写法一的“虚假成功”:当
fopen失败时,if块内的fgets不会执行,buff是未初始化的栈内存,里面的随机字节刚好被sscanf解析成了看起来正确的数值——这是未定义行为,完全是巧合,不是真的成功。 - 写法二的真实结果:因为
fopen失败,if块内的代码全部跳过,op和lc保持初始值0,输出0是正确反映了文件打开失败的状态。
解决方案
1. 修复路径转义
将路径中的单个反斜杠改成双反斜杠(转义后代表实际的反斜杠),或者使用C++11支持的原始字符串:
// 方式1:双反斜杠转义 std::string CMDFILE = "C:\\testFile.txt"; // 方式2:原始字符串(无需转义) std::string CMDFILE = R"(C:\testFile.txt)";
2. 增加错误检查
为所有IO操作添加返回值检查,避免依赖未定义行为:
#include <stdio.h> #include <windows.h> #include <string> void readFromFile() { char buff[100] = {0}; // 初始化缓冲区,避免未定义行为 int op = 0; int lc = 0; char st[25] = {0}; FILE *cmdBuffer; std::string CMDFILE = "C:\\testFile.txt"; cmdBuffer = fopen(CMDFILE.data(), "r"); if (cmdBuffer != NULL) { // 检查fgets是否成功读取到内容 if (fgets(buff, sizeof(buff), cmdBuffer) != NULL) { // 检查sscanf是否成功解析全部3个字段 int parse_count = sscanf(buff, "%d %d %s", &op, &lc, st); if (parse_count != 3) { printf("解析失败:仅成功读取%d个字段\n", parse_count); } } else { printf("读取文件内容失败\n"); } fclose(cmdBuffer); } else { printf("无法打开文件,请检查路径是否正确\n"); } printf("%d %d %s\n", op, lc, st); }
内容的提问来源于stack exchange,提问作者MacLCM
相关产品推荐
相关产品推荐

