scanf, fscanf很相似,都是從流中讀取輸入,然后賦值給變量
int scanf(const char *format, ...)
int fscanf(FILE *stream, const char *format,...)
%c 單一字符
%[] 一個字符集
* 輸入項讀入后跳過,不賦予任何變量
scanf, fscanf 自動跳過tabs和空格,其他字符賦予變量,返回成功賦值的變量數(整數),發生錯誤時返回EOF
%[^\n] 表示讀取一整行,^ 表示 “非”,前面提到 %[] 表示一個字符集,所以 %[^\n] 表示“遇到一個換行符之前的所有字符的集合”,隨后就結束讀入。
char str[80];
fscanf(fp,"%[^\n]",str);
但是這么做以后,那個換行符還沒有讀取。
前面提到了,* 表示輸入項讀入后跳過,所以 %*c 表示跳過一個字符,所以可以寫
fscanf(fp, "%[^\n]%*c", str);
讀取換行符之前的所有內容,賦值給str,然后跳過換行符,指向下一行內容。
如果要跳過整行,可以寫
fscanf(fp, "%*[^\n]%*c");
但有時也會出錯,當緩存中只有一個 \n 時,%*[^\n] 發現 \n 之前沒有任何內容,會直接返回,后面的 %*c 不起作用。所以緩存中只有 \n 時,上面那行代碼不管運行多少遍,都是什么都不做。
為了避免上面的情況,可以修改為
fscanf(fp, "%*c%*[^\n]");
那么如果緩存中只有一個 \n,%*c 會跳過它,%*[^\n] 會跳過下一行換行符之前的內容;如果緩存中不是 \n,則 %*c 跳過第一個字符,%*[^\n] 跳過后面的內容(換行符之前),即跳過一行,緩存中留一個 \n。
緩存中留一個 \n 不影響 %d, %lf 等語句,所以這么寫更安全。