數據格式
大學英語B 4.0 2.67
高等數學下 6.0 3.67
離散數學上 2.5 3.67
金工實習 1.0 3.33
思修 3.0 3.33
普通物理實驗上 1.5 4.00
普通物理上 4.0 3.67
程序設計實訓 1.0 3.33
目標結構體
struct Course {
char name[20];
float credit;
float mark;
} courses[N];
讀取策略
- 使用
ifstream 逐行讀取。
- 每行用
stringstream 或 sscanf 解析:課程名可能含空格,故先讀整行,再從末尾向前提取兩個 float,剩余為名稱。
- 或約定課程名無空格,直接
in >> name >> credit >> mark。
完整代碼示例
#include <fstream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;
struct Course {
string name; // 用 string 避免緩衝區溢出
float credit;
float mark;
};
int main() {
vector<Course> courses;
ifstream fin("grades.txt");
if (!fin) { cerr << "無法打開文件\n"; return 1; }
string line;
while (getline(fin, line)) {
if (line.empty()) continue;
stringstream ss(line);
Course c;
// 從末尾讀取兩個 float
vector<string> tokens;
string tok;
while (ss >> tok) tokens.push_back(tok);
if (tokens.size() < 3) continue;
c.mark = stof(tokens.back()); tokens.pop_back();
c.credit = stof(tokens.back()); tokens.pop_back();
// 剩余合併為課程名
c.name = "";
for (size_t i = 0; i < tokens.size(); ++i) {
if (i) c.name += " ";
c.name += tokens[i];
}
courses.push_back(c);
}
// 輸出驗證
for (auto &c : courses) {
cout << left << setw(20) << c.name
<< setw(8) << c.credit
<< c.mark << '\n';
}
return 0;
}
關鍵點
- 優先使用
std::string 和 std::vector 替代定長數組,安全且靈活。
- 利用
stringstream 分割字符串,配合反向提取數值,完美處理含空格的課程名。
- 檢查文件打開狀態與解析有效性,增強健壯性。