txt檔案:
44.56 john doe
100.21 jane doe
如何計算數字的總和?這個函式給 0
double get_sum(FILE *out)
{
double sum = 0;
double value;
char name;
char surname;
while(fscanf(out, "%lf %s %s", &value, name, surname) != EOF)
{
sum = value;
}
return sum;
}
uj5u.com熱心網友回復:
在行
while(fscanf(out, "%lf %s %s", &value, name, surname) != EOF)
fscanf將函式的回傳值與.進行比較是不好的EOF。例如,如果函式只能匹配一個引數,那么它將回傳1,但您的程式仍會表現得好像所有3引數都已匹配,并且您的程式將嘗試處理不存在的資料。因此,您應該改寫以下內容:
while( fscanf(out, "%lf %s %s", &value, name, surname) == 3 )
但是,這可能不是您遇到的直接問題的原因。該問題可能是由于%s轉換格式說明符需要一個指標來寫入。但是,您傳遞的是(而不是指向)單個char.
假設您啟用了警告,您的編譯器應該已經警告您這一點。有關詳細資訊,請參閱此問題:為什么我應該始終啟用編譯器警告?
為了解決這個問題,你應該改變行
char name;
char surname;
到:
char name[50];
char surname[50];
此外,您可能應該限制寫入這些字串的字符數,以防止緩沖區溢位,如下所示:
while( fscanf(out, "%lf Is Is", &value, name, surname) == 3 )
對于基于行的輸入,我通常建議您使用函式一次讀取一行fgets。然后,您可以sscanf在每一行上使用該函式來決議它。
如果您fscanf像現在一樣使用,并且如果它與一行中的 3 個欄位不完全匹配,那么決議器將與行不同步,并且它無法在新的開始時重新同步行,這可能意味著您的程式將在檔案的其余部分出現例外,而不是僅在一行中出現例外。
這是一個使用fgetsand的程式sscanf:
#include <stdio.h>
double get_sum( FILE *fp )
{
char line[200];
double sum = 0;
while ( fgets( line, sizeof line, fp ) != NULL )
{
double value;
char name[50];
char surname[50];
if ( sscanf( line, "%lf Is Is", &value, name, surname ) == 3 )
{
sum = value;
}
else
{
printf( "WARNING: skipping line due to parse failure!\n" );
}
}
return sum;
}
int main( void )
{
//calling this function would also work for an opened file, but
//for simplicity, I am only passing it "stdin"
double sum = get_sum( stdin );
printf( "The sum is: %lf\n", sum );
}
隨著輸入
44.56 john doe
100.21 jane doe
從這個問題來看,這個程式有以下輸出:
The sum is: 144.770000
如果您現在改為向程式提供包含一行無效輸入的輸入
44.56 john doe
invalid_input_line
100.21 jane doe
它只會在決議該無效行時失敗,但仍會正確處理其他行:
WARNING: skipping line due to parse failure!
The sum is: 144.770000
如前所述,您的程式能夠從此錯誤中恢復,因為它使用 一次讀取一行fgets,并且使用sscanf而不是fscanf. 否則,從這樣的錯誤中恢復會更加復雜。
uj5u.com熱心網友回復:
只需告訴像這樣fscanf忽略nameandsurname插槽:
double get_sum(FILE *out) {
double sum = 0;
double value;
while (fscanf(out, "%lf%*s%*s", &value) != EOF) {
sum = value;
}
return sum;
}
問題是你在哪里傳遞指標而不是指向可以保存內容char的 char陣列的指標。因為你沒有它溢位并導致未定義的行為。
但是,如果您真的想閱讀名稱,請嘗試:
double get_sum(FILE *out) {
double sum = 0;
double value;
char name[5];
char surname[4];
while (fscanf(out, "%lf%s%s", &value, name, surname) != EOF) {
sum = value;
}
return sum;
}
這里的緩沖區足夠長以容納示例文本檔案資料。在現實生活中(如果需要),您將擁有足夠大的名稱來處理最長的名字。與原始代碼的重要區別在于name和surname是fscanf函式期望的指標。
但是考慮到名稱的長度有時是不可預測的,在讀取行上的值之后,只需將剩余的行讀入緩沖區并忽略它即可。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
double get_sum(FILE *in) {
double sum = 0;
double value;
char *remainingLine = NULL;
size_t bufLen = 0;
while (fscanf(in, "%lf", &value) == 1) {
sum = value;
// ignore remaining character in line
getline(&remainingLine, &bufLen, in);
}
free(remainingLine);
return sum;
}
int main(void) {
FILE *f = fopen("text.txt", "r");
assert(f);
double s = get_sum(f);
fclose(f);
printf("Sum is %f", s);
}
text.txt檔案包含
1.03 First Surname
2.2Here is another long "name" (sum should be 10.63)
3.4 first middle last (next line is lonely and last)
4
運行最后一個程式應該會產生類似的東西
Sum is 10.630000
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/418549.html
標籤:
