[英]How to use fscanf() format string
我正在使用fscanf()從文件中讀取輸入(我知道我應該使用fgets(),但不允許這樣做),而且我不知道如何正確使用格式字符串。
輸入格式為:M 03f8ab8,1
我需要將字母,地址和數字分別保存到一個變量中。 這是到目前為止我得到的:
while(fscanf(file, " %s %s, %d", operation, address, &size) != -1)
如所寫,它將字母放入正確的var(operation)中,但在地址末尾添加,number,然后將未定義的內容分配給size變量。
它應該將每個變量放到各自的變量中(並忽略逗號)
如何設置fscanf()才能正確獲取此信息?
這里的問題是"%s"
格式讀取以空格分隔的字符串,並且由於03f8ab8,1
沒有空格,因此它將全部作為單個字符串讀取。
您可以使用"%["
格式解決此問題,該格式允許您進行一些非常簡單的模式匹配。 例如,您可以使用它告訴fscanf
讀取所有內容,直到(但不包括)逗號為止。 喜歡
fscanf(file, "%s %[^,], %d", operation, address, &size)
有關更多詳細信息,請參見例如scanf
(和系列)參考 。
另外,您不應該將fscanf
的結果與-1
,而是通過將return與3
進行比較來檢查它是否解析了正確的序列數:
while (fscanf(file, "%s %[^,], %d", operation, address, &size) == 3) ...
請注意,以上格式不會對其讀取的字符串施加任何限制。 這可能會導致字符串溢出。 如果您的字符串是固定大小的(即,它們是數組),則使用格式最大字段寬度來限制fscanf
將讀取並放入數組的字符數。
例如(完全不了解您的實際字符串/數組):
while (fscanf(file, "%1s %8[^,], %d", operation, address, &size) == 3) ...
使用上述方法,第一個字符串不能超過一個字符,第二個字符串不能超過八個字符。 請注意,這些數字不包括字符串null終止符(您在數組中需要的空間超出了上面給出的大小)。
fscanf(input_fp, "%30[^ ,\n\t]%30[^ ,\n\t]%30[^ ,\n\t]", ...
不會在文本文件中使用','或'\\ n'。 隨后的fscanf()嘗試也會失敗,並返回值0(不是EOF)會導致無限循環。
對於fgets()/sscanf()
fscanf()
解決方案可以更好地處理潛在的IO和解析錯誤:
main()
{
FILE *input_fp;
FILE *output_fp;
char buf[100];
while (fgets(buf, sizeof buf, input_fp) != NULL)
{
char name[30]; // Insure this size is 1 more than the width in scanf format.
char age_array[30];
char occupation[30];
#define VFMT " %29[^ ,\n\t]"
int n; // Use to check for trailing junk
if (3 == sscanf(buf, VFMT "," VFMT "," VFMT " %n",
name, age_array, occupation, &n) && buf[n] == '\0')
{
// Suspect OP really wants this width to be 1 more
if (fprintf(output_fp, "%-30s%-30s%-30s\n", name, age_array, occupation) < 0)
break;
} else
break; // format error
}
fclose(input_fp);
fclose(output_fp);
}
而不是調用ferror(),而是檢查fgets(),fprintf()的返回值。
可疑OP的未聲明字段緩沖區為[30],並相應地調整了scanf()。
有關if (3 == sscanf(buf, VFMT "," ...
if (3 == sscanf(...) && buf[n] == '\\0') {
在以下情況下為真:
1)精確地使用3個"%29[^ ,\\n\\t]"
格式說明符,每個scanf至少使用1個字符。
2)buf [n]是字符串的結尾。 n通過“%n”說明符設置。 “%n”中的前一個''導致最后一個"%29[^ ,\\n\\t]"
之后的任何后續空格被消耗。 scanf()看到“%n”,它指示它設置從掃描開始的當前偏移量,以將其分配給&n所指向的int。
編譯器將"VFMT "," VFMT "," VFMT " %n"
連接到
" %29[^ ,\n\t], %29[^ ,\n\t], %29[^ ,\n\t] %n".
我發現前者比后者更易於維護。
" %29[^ ,\\n\\t]"
的第一個空格指示sscanf()掃描(消耗並不保存)0個或多個空格('','\\ t','\\ n'等)。 其余的命令sscanf()消耗並保存除“,”,“ \\ n”,“ \\ t”之外的任何1到29個字符,然后附加一個“ \\ 0”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.