输入文件读取错误值及EOF控制循环无法终止的技术问询
哇,这个问题我之前踩过好几次坑!混合使用getline和>>读取文件,再加上while(!infile.eof())的经典陷阱,简直是新手读文件的两大噩梦。咱们一步步拆解问题,然后搞定它。
为什么会出现垃圾值和循环不终止?
1. while(!infile.eof())的致命陷阱
这个循环条件的逻辑是:只有当文件指针已经到末尾时才停止。但问题在于,程序会在读取失败之后才检测到EOF——也就是说,当最后一行数据读完后,循环还会强行执行一次。这时候所有读取操作都会失败,数组里的productName[i]、productQty[i]等变量就会被填充垃圾值,i还会多自增一次,后续读取自然为空,循环也没法正常终止。
2. getline和>>混合使用的缓冲区残留
当你用infile >> productQty[i]或infile >> productPrice[i]读取数字时,这些操作会停在数字后面的换行符/空格处,不会把它们从输入缓冲区里清除。接下来调用getline(infile, productLocation[i])时,getline会直接读取这个残留的换行符,导致productLocation[i]变成空字符串,后续读取顺序全乱,这就是第四行开始异常的核心原因。
解决方案:两种修复思路
方案一:修复缓冲区+正确的循环条件
在每次用>>读取数字后,手动跳过缓冲区里的换行符和空白字符,同时把循环条件改成检查读取是否成功:
#include <limits> // 需要包含这个头文件来使用numeric_limits int ReadData(string productName[], string productLocation[], int productQty[], double productPrice[]) { ifstream infile; int i = 0; infile.open("prog1.txt"); // 以成功读取productName作为循环启动条件,避免EOF陷阱 while (getline(infile, productName[i])) { // 读取数量,失败则终止循环 if (!(infile >> productQty[i])) break; // 跳过数量后面的所有空白(包括换行符) infile.ignore(numeric_limits<streamsize>::max(), '\n'); // 读取位置,失败则终止循环 if (!(getline(infile, productLocation[i]))) break; // 读取价格,失败则终止循环 if (!(infile >> productPrice[i])) break; // 跳过价格后面的所有空白 infile.ignore(numeric_limits<streamsize>::max(), '\n'); i++; } infile.close(); return i; }
方案二:统一用getline读取整行,再分割字段(更可靠)
因为你的数据是按行存储的,且部分字段(比如Zip Drive、Warehouse C)包含空格,直接用>>会拆分这些字段。可以先读取整行,再用字符串流分割成各个部分:
#include <sstream> // 需要包含这个头文件来使用istringstream int ReadData(string productName[], string productLocation[], int productQty[], double productPrice[]) { ifstream infile; int i = 0; string line; infile.open("prog1.txt"); // 每次读取整一行,直到文件结束 while (getline(infile, line)) { istringstream iss(line); string part; // 读取带空格的productName:直到遇到数字(productQty) productName[i].clear(); while (iss >> part) { // 简单判断当前部分是否为数字(或负号开头) if (isdigit(part[0]) || part[0] == '-') { // 把数字部分放回流中,供后续读取productQty iss.seekg(-(int)part.size(), ios::cur); break; } if (!productName[i].empty()) productName[i] += " "; productName[i] += part; } // 读取数量,失败则终止 if (!(iss >> productQty[i])) break; // 读取带空格的productLocation:直到遇到数字/小数点(productPrice) productLocation[i].clear(); while (iss >> part) { if (isdigit(part[0]) || part[0] == '-' || part[0] == '.') { iss.seekg(-(int)part.size(), ios::cur); break; } if (!productLocation[i].empty()) productLocation[i] += " "; productLocation[i] += part; } // 读取价格,失败则终止 if (!(iss >> productPrice[i])) break; i++; } infile.close(); return i; }
内容的提问来源于stack exchange,提问作者Derek
相关产品推荐
相关产品推荐

