fscanf(fp, "%f,%f,%f", &q, &p, &e) 正常讀取三列。fscanf(fp, "%f", &car[i][j]) 僅第一個數據正確,其餘全為亂碼。| 調用方式 | 格式串 | 掃描行為 | 結果 |
|---|---|---|---|
| 單次多參數 | "%f,%f,%f" | 依次匹配:浮點數 → 字面逗號 → 浮點數 → 字面逗號 → 浮點數 | 逗號被精確消耗,數據正確 |
| 循環單參數 | "%f" | 匹配浮點數,**停留在逗號前**;下一次循環 %f 遇到逗號 (非數字) 匹配失敗,不消耗字符,陷入死循環/亂讀 | 逗號阻塞後續讀取 |
for (i = 0; i < M; i++) {
for (j = 0; j < N+3; j++) {
fscanf(fp, "%f,", &car[i][j]); // 格式串末尾加逗號
}
}
注意:最後一列後可能無逗號 (換行符),需單獨處理或用 %f%*c 吸收任意單字符。
char ch;
for (i = 0; i < M; i++) {
for (j = 0; j < N+3; j++) {
fscanf(fp, "%f%c", &car[i][j], &ch); // %c 讀走逗號或換行
}
}
優點:通用性強,無論分隔符是逗號、分號、空格、換行,%c 都能逐字符吸收。
char line[1024];
for (i = 0; i < M && fgets(line, sizeof(line), fp); i++) {
char *token = strtok(line, ",\n");
for (j = 0; j < N+3 && token; j++) {
car[i][j] = atof(token);
token = strtok(NULL, ",\n");
}
}
優勢:完整讀取一行再解析,天然處理行尾換行、列數不固定、異常行跳過等複雜情況。
fscanf **不自動跳過非空白字符** (逗號、分號、冒號等),格式串必須顯式匹配或吸收它們。%f 等數值格式符**自動跳過空白** (空格、\t、\n),但**不跳過標點符號**。%c **不跳過任何字符**,連空白也讀取,適合作為「通用分隔符吸收器」。fgets 整行讀取 + strtok/sscanf 解析,邏輯清晰、錯誤恢復能力強。循環調用 fscanf(fp, "%f", ...) 讀取 CSV 失敗,核心在於**格式串未消耗逗號分隔符**,導致後續匹配失敗。在格式串添加逗號 (%f,)、引入 %c 吸收分隔符、或改用 fgets+strtok 逐行解析,均能徹底解決。工程實踐中推薦方案 3,健壯性最高。