簡體   English   中英

C編程:如何將sscanf與':'分隔符一起使用?

[英]C programming: How to use sscanf with a ':' delimiter?

我一直在嘗試使用sscanf從輸入文本中提取小時,秒和分鍾。 執行sscanf函數后,只有保留秒數的s變量具有正確的值。 帶有小時和分鍾的hm僅保留零。 請在下面建議對我的代碼進行更改。

     char text[20];
     if (fgets(text, sizeof text, stdin)!= NULL){
         char* newline = strchr(text, '\n');
         if (newline != NULL){
             *newline = '\0';
         }
     }
     uint8_t s = 0;
     uint8_t m = 0;
     uint8_t h = 0;
     sscanf(text, "%02i:%02i:%02i",&h,&m,&s);

注意在調試器中,文本具有正確的值。

該程序:

#include <stdio.h>

int main(void)
{
    const char hhmmss[] = "10:32:54";
    int hh, mm, ss;
    if (sscanf(hhmmss, "%i:%i:%i", &hh, &mm, &ss) != 3)
        printf("Failed to scan 3 values from '%s'\n", hhmmss);
    else
        printf("From <<%s>> hh = %d, mm = %d, ss = %d\n", hhmmss, hh, mm, ss);
    return 0;
}

給出以下輸出:

From <<10:32:54>> hh = 10, mm = 32, ss = 54

%02i轉換也應該起作用,但是數字有點多余。


修改后的問題表明,變量的類型為uint8_t ,在這種情況下,必須使用<inttypes.h>的正確轉換說明符:

#include <stdio.h>
#include <inttypes.h>

int main(void)
{
    const char hhmmss[] = "10:32:54";
    uint8_t s;
    uint8_t m;
    uint8_t h;

    if (sscanf(hhmmss, "%02" SCNi8 ":%02" SCNi8 ":%02" SCNi8, &h, &m, &s) != 3)
        printf("Failed to scan 3 values from '%s'\n", hhmmss);
    else
        printf("From <<%s>> h = %d, m = %d, s = %d\n", hhmmss, h, m, s);
    return 0;
}

這將產生與以前相同的輸出。 對於任何scanf()函數家族,至關重要的是,格式轉換說明符必須與要傳遞給函數的指針的類型相匹配。 由於默認的整數提升(特別是),您scanf() printf()的很多不匹配printf()當然是比較),但是scanf()寬容度要低得多。

@Jonathan Leffler的回答是完全正確的,但是...

除非可能在已知的拋出明天代碼中使用,否則永遠不要使用scanffscanfsscanf來分析來自文件句柄或字符串的輸入。 它們太容易出錯並且很難控制。 對於scanf的各種問題的詳盡總結,我推薦本系列文章 一些要點:

  • 如果需要讀取單個字符,請使用getchar
  • 如果要讀取一個字符串, scanf會遇到gets所有緩沖區溢出問題。
  • 如果您想讀取數字,則scanf的解析容易出錯並且難以使用。 請改用strtoulstrtod
  • 如果您有更復雜的輸入,那么一切都會變得更糟。

該怎么辦?

  • 使用比gets更好的方法讀取自己的輸入,即沒有緩沖區溢出問題。 不要試圖將輸入字節與解釋字節結合起來。
  • 使用strcspnstrspnstroulstrtod組合以及一些自定義代碼來掃描輸入。

有時候這也很麻煩,但是到那時,您通常需要構建某種輸入語言,但無論如何都需要更多的通用技術。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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