You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用stringstream读取文本行赋值Student时stoi异常的解决方法

文本行解析与哈希表插入异常修复

问题背景

需要读取文本文件中以单个空格分隔的行,每行包含id(整数)、firstname、lastname、department、gpa字段,示例行:

9528951 Adney Smith CS 4.2 //id    fname lname dept gpa

现有代码运行时抛出异常:

terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi

调试发现Student变量无值,推测是stringstream使用不当导致解析失败,且id转int时因空值触发异常。

错误原因

  1. stringstream未正确绑定每行数据:代码中stringstream ss(line)初始化时绑定的是空字符串,后续循环读取新的line后,未将ss重新绑定到当前line,导致始终读取空数据,所有字段变量为空。
  2. 未处理行内注释:示例行包含//开头的注释,直接解析会把注释内容混入字段,导致解析异常。
  3. 空id触发stoi异常:空字符串调用stoi()会直接抛出invalid_argument异常。

修复后的代码

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>

// 假设Student和HashTable的定义已正确实现
template <typename T>
class Student {
private:
    std::string firstName;
    std::string lastName;
    std::string gpa;
    std::string department;
public:
    void setFirstName(const std::string& fn) { firstName = fn; }
    void setLastName(const std::string& ln) { lastName = ln; }
    void setGPA(const std::string& g) { gpa = g; }
    void setDepartment(const std::string& d) { department = d; }
};

template <typename T>
class HashTable {
public:
    void insert(int id, const Student<T>& student) {
        // 假设这里实现了正确的插入逻辑,包含stoi转换id的操作
    }
    void displayHash() {
        // 假设这里实现了显示逻辑
    }
};

int main()
{
    std::string line;
    std::ifstream myfile("enroll_test.txt");
    HashTable<std::string> ht;
    std::string id_str, fname, lname, dept, gpa;

    if (!myfile.is_open())
    {
        std::cout << "File failed to open" << std::endl;
        return 0;
    }

    while (std::getline(myfile, line))
    {
        // 去除行内的注释部分
        size_t comment_pos = line.find("//");
        if (comment_pos != std::string::npos) {
            line = line.substr(0, comment_pos);
        }

        // 重置stringstream,绑定当前行
        std::stringstream ss(line);
        // 解析字段
        if (ss >> id_str >> fname >> lname >> dept >> gpa) {
            Student<std::string> student;
            student.setFirstName(fname);
            student.setLastName(lname);
            student.setGPA(gpa);
            student.setDepartment(dept);
            
            // 安全转换id为int
            try {
                int id = std::stoi(id_str);
                ht.insert(id, student);
            } catch (const std::invalid_argument& e) {
                std::cerr << "Invalid id format: " << id_str << std::endl;
                continue;
            } catch (const std::out_of_range& e) {
                std::cerr << "Id out of range: " << id_str << std::endl;
                continue;
            }
        } else {
            std::cerr << "Invalid line format: " << line << std::endl;
            continue;
        }
    }
    myfile.close();

    ht.displayHash();
    
    return 0;
}

关键修复点

  • 每次循环重新初始化stringstream:在循环内创建std::stringstream ss(line),确保每次绑定当前读取的有效行数据。
  • 处理行内注释:通过line.find("//")定位注释起始位置,截取注释前的有效内容。
  • 安全转换id:用try-catch包裹stoi()调用,捕获无效格式或超出范围的异常,避免程序崩溃。
  • 增加解析校验:判断ss >> ...的返回值,确保字段解析成功后再创建Student对象,避免无效数据插入哈希表。

内容的提问来源于stack exchange,提问作者stackunderflow3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 00:35:19