C++中使用getline()处理跨行拆分的BLS文本数据问题
处理BLS文本数据中的跨行城市条目问题
问题场景与代码
读取BLS文本格式数据时,部分都会区名称过长导致对应城市的数据被拆分为两行,示例文件片段:
999 26380 Houma-Thibodaux, LA 42 42 0 0 0 0 94 288 26420 Houston-The Woodlands-Sugar Land, TX 4424 3046 4 0 1374 34 100 170 26580 Huntington-Ashland, WV-KY-OH 7 1 0 6 0 0 85
需要提取州信息后的7个整数,存入total, one, two, three, five, struc, per变量中。单行数据处理正常,但跨行的Houston数据无法正确读取——原本期望读取下一行的州和数字,实际getline(sin, line)持续读取空行。
当前使用的代码:
#include <fstream> #include <string> #include <vector> #include <sstream> using namespace std; int main() { ifstream BLS; vector <string> cities = {"Houston-The Woodlands-Sugar Land"}; string city, state, total, one, two, three, five, struc, per, temp; BLS.open("trial.txt"); if (BLS.is_open()) { string line; while(getline(BLS, line)) { istringstream sin(line); getline(sin, temp, ' '); getline(sin, temp, ' '); getline(sin, city, ','); for (int i = 0; i < (int) cities.size(); i++) { if (city == cities[i]) { if (getline(sin, line) ) { istringstream in(line); in >> state >> total >> one >> two >> three >> five >> struc >> per; } else { sin.ignore(); getline(sin, line); istringstream in(line); in >> state >> total >> one >> two >> three >> five >> struc >> per; } cout << " " << city << " " << state << " " << total << " " << five << endl; } } } } }
问题分析
核心错误是混淆了**文件流BLS和字符串流sin**的作用:
sin是基于当前读取的单行内容创建的,只能处理该行剩余数据,无法读取文件的下一行。- 针对Houston的行,
getline(sin, city, ',')已经读到行尾的逗号,sin内剩余内容为空,此时调用getline(sin, line)必然失败,后续操作自然无法获取下一行的州和数字。
修复方案
当检测到目标城市的当前行没有州信息时,直接从**文件流BLS**读取下一行,再解析州和数字。修正后的代码:
#include <fstream> #include <string> #include <vector> #include <sstream> using namespace std; int main() { ifstream BLS; vector<string> cities = {"Houston-The Woodlands-Sugar Land"}; string city, state, total, one, two, three, five, struc, per, temp; BLS.open("trial.txt"); if (BLS.is_open()) { string line; while (getline(BLS, line)) { istringstream sin(line); // 跳过前两个数字字段 getline(sin, temp, ' '); getline(sin, temp, ' '); // 读取城市名称到逗号处 getline(sin, city, ','); // 判断是否为目标城市 bool is_target = false; for (const string& target_city : cities) { if (city == target_city) { is_target = true; break; } } if (!is_target) continue; // 跳过逗号后的空白字符,尝试读取州信息 sin >> ws; if (!(sin >> state)) { // 当前行无州信息,读取文件下一行 if (!getline(BLS, line)) break; istringstream next_line(line); next_line >> state >> total >> one >> two >> three >> five >> struc >> per; } else { // 当前行有州信息,直接读取后续数字 sin >> total >> one >> two >> three >> five >> struc >> per; } cout << " " << city << " " << state << " " << total << " " << five << endl; } } return 0; }
关键改进
- 区分流的作用:读取下一行时直接操作文件流
BLS,而非字符串流sin。 - 空白处理:用
sin >> ws跳过逗号后的所有空白,避免读取空内容。 - 简化逻辑:提前判断是否为目标城市,减少嵌套层级,代码更清晰。
- 异常防护:读取下一行时检查是否成功,避免文件提前结束引发错误。
内容的提问来源于stack exchange,提问作者matheconcs
相关产品推荐
相关产品推荐

