如何从行长度可变的文本文件正确填充二维char数组?
解决二维char数组读取文本文件名字的乱码问题
我来帮你搞定这个问题!你的代码里确实有几个关键坑导致了乱码和不正确的读取,咱们一步步拆解并修正:
先说说你代码里的核心问题
while(!inFile.eof())的经典误区:这个判断逻辑会让程序多读一次。因为eof()只有在尝试读取失败后才会被置为true,所以当文件最后一行读完后,循环还会再执行一次,这次读取会失败,导致数组里被写入无效数据。- 逐字符读取的不合理性:你用嵌套循环强制读满7个字符,但每行名字长度不一样,而且每行末尾的换行符也会被读进数组,同时未被填充的数组位置因为没初始化,会留下随机的垃圾值(就是你看到的
?)。 - 数组未初始化:局部的二维char数组不会自动初始化为空字符,未被赋值的位置都是内存里的随机值,输出时就会显示乱码。
方案一:修正原有的二维char数组实现
如果一定要用固定大小的二维char数组,我们可以这样改,保证读取正确且无乱码:
#include <iostream> #include <fstream> #include <cstring> using namespace std; int main(){ // 初始化数组为全'\0',避免未赋值位置的垃圾值 char names[4][7] = {0}; string fileName = "names.txt"; ifstream inFile(fileName); // 先检查文件是否成功打开,避免异常情况 if (!inFile.is_open()) { cerr << "Failed to open the file!" << endl; return 1; } for(int i=0; i<4; i++){ // 读取一行到数组,最多读6个字符(留1位给字符串结束符'\0') inFile.getline(names[i], 7); // 如果行尾还有未读取的换行符,跳过它 if (inFile.peek() == '\n') { inFile.ignore(); } } // 直接输出每个C风格字符串(遇到'\0'自动停止) for(int i=0; i<4; i++){ cout << names[i] << " "; } cout << endl; inFile.close(); return 0; }
关键改进点:
- 初始化数组为全
'\0':保证未被填充的位置都是空字符,输出时不会显示乱码。 - 使用
getline读取整行:自动在每个名字末尾添加'\0',输出时直接打印字符串即可,不用逐字符遍历。 - 增加文件打开检查:避免文件不存在或权限问题导致的崩溃。
方案二:用C++的string和vector更灵活(推荐)
如果不需要固定大小的数组,用C++标准库的string和vector会更安全简洁,完全不用操心长度问题:
#include <iostream> #include <fstream> #include <vector> #include <string> using namespace std; int main(){ vector<string> names; string fileName = "names.txt"; ifstream inFile(fileName); if (!inFile.is_open()) { cerr << "Failed to open the file!" << endl; return 1; } string name; // 正确的逐行读取方式:读取失败时自动终止循环 while (getline(inFile, name)) { names.push_back(name); } // 遍历输出所有名字 for(const auto& n : names){ cout << n << " "; } cout << endl; inFile.close(); return 0; }
优势:
- 不需要预先知道名字的数量和长度,
vector会自动扩容。 - 彻底避免数组越界、未初始化等问题,代码更易维护。
while(getline(inFile, name))是C++读取文件的标准正确写法,不会出现多读一次的问题。
内容的提问来源于stack exchange,提问作者TheStrangeQuark
相关产品推荐
相关产品推荐

