簡體   English   中英

如何使用fscanf()格式字符串

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM