2013-05-29 17 views
7

如何使用scanf寬度說明符0?
1)無限制寬度(與cywin gcc版本4.5.3一致)
2)UB
3)其他?如何使用0的scanf寬度說明符?

我的應用程序(未示出)動態地形成寬度說明作爲scanf的一個更大的格式字符串的一部分()。很少會在格式字符串的中間創建一個"%0s"。在這種情況下,%0s的目標字符串只有1個字節的空間用於存儲\0scanf(),其中上述行爲#1導致問題。

注意:以下測試用例使用常量格式。

#include <memory.h> 
#include <stdio.h> 

void scanf_test(const char *Src, const char *Format) { 
    char Dest[10]; 
    int NumFields; 
    memset(Dest, '\0', sizeof(Dest)-1); 
    NumFields = sscanf(Src, Format, Dest); 
    printf("scanf:%d Src:'%s' Format:'%s' Dest:'%s'\n", NumFields, Src, Format, Dest); 
} 

int main(int argc, char *argv[]) { 
    scanf_test("1234" , "%s"); 
    scanf_test("1234" , "%2s"); 
    scanf_test("1234" , "%1s"); 
    scanf_test("1234" , "%0s"); 
    return 0; 
} 

輸出:

scanf:1 Src:'1234' Format:'%s' Dest:'1234' 
scanf:1 Src:'1234' Format:'%2s' Dest:'12' 
scanf:1 Src:'1234' Format:'%1s' Dest:'1' 
scanf:1 Src:'1234' Format:'%0s' Dest:'1234' 

我的問題是,最後一行。看起來0寬度不會導致寬度限制而不是0寬度。如果這是正確的行爲或UB,我將不得不以另一種方式接近零寬度情況,或者有其他scanf()格式要考慮嗎?

+0

它看起來'%0s'被評估爲'%s'。 0被忽略。但我無法證實這一點。我不知道是否有標準提及這種行爲 – MOHAMED

+0

@chux什麼是UB? –

+0

有一個'*'格式規範來禁止分配。這會有幫助嗎? – Arkadiy

回答

10

最大字段寬度說明符必須爲非零。 C99,7.19.6.2:

格式應該是一個多字節字符序列,其開頭和結尾的初始位置爲 。格式是由零個或多個指令:一個或更多個空白字符 ,一個普通的多字節字符(均未%也不是空白字符),或 轉換規範。每個轉換規範都由字符%引入。 的%後,下面的順序出現:
- 一個可選的分配抑制字符*
- 可選的非零十進制整數,指定最大場寬度( 字符)。
- 一個可選長度修改,指定接收對象的大小。
- A 轉換說明符指定要應用的轉換類型的字符。

所以,如果您使用0,行爲是未定義的。

4

這來自n1570.pdf的7.21.6.2(C11標準草案):

的%後,下列順序出現:

- 一個可選的賦值抑制符*。

- 一個可選的十進制整數大於零,指定 最大場寬度(字符)。

...

這是不確定的行爲,因爲C標準的規定,您最大字段寬度必須大於零。

輸入項

你想實現什麼是它通過讀取寬度的字段定義爲不超過任何指定的字段寬度和輸入字符 最長序列... 0並將其分配爲一個字符串(空字符串)到Dest?你試圖解決哪個實際問題?似乎更清楚地指定爲*Dest = '\0';

+0

*未定義的行爲此應用程序中'scanf()'的格式是根據目標字符串的可用空間以及其他字段動態生成的。程序事先並不知道寬度需要爲0.因此使用'* Dest ='\ 0';'在一般情況下不起作用,但可用於處理特殊寬度= 0的情況。 – chux

+0

@chux嗯,我的程序分類了一副牌......但是它的用途是什麼?爲什麼需要?你試圖解決哪個實際問題?我不是要求你描述你的解決方案;我要求你描述這個問題。 – Sebivor

+0

應用程序使用的文本文件來控制測試各種產品和產品功能的生產程序的操作。在解析配置文件時,它們可以存在其他配置,這些配置指定了某些字段預期的最大文本長度。正是這些其他配置文件允許指定0的寬度,並將0傳遞給一般分析器。當通過0寬度時,僅分配0 + 1字節來接收數據。如上所述,保存了太多的字節。最後,配置爲0的寬度現在是過時的。 – chux

相關問題