2016-11-15 70 views
1

有人可以解釋這是如何工作的?我知道它讀取一個字符串(包含空格),但我並不真正理解背後的機制。有人可以一塊一塊地向我解釋 嗎?在C中讀取字符串的詳細信息?

scanf("%[^\n]%*c",string); 
+0

您是否試過閱讀手冊頁?如果你在unix系統上鍵入'man scanf'並通讀它。 – EdgeCaseBerg

+0

特別是,最後的'%* c'指示讀取終止'newline'作爲'char'並放棄結果,以免將'newline'留在輸入緩衝區中。 –

+0

這裏是一個正則表達式的很好的參考:http://stackoverflow.com/questions/22937618/reference-what-does-this-regex-mean –

回答

2

從手冊頁:

所有轉換由%(百分號)推出字符

A轉換是我們如何匹配特定的文本字符串。例如,一個%s匹配一個字符串,而%d匹配一個十進制整數。所以看看你的字符串,我們有一個"%[轉換,它根據手冊頁:

[匹配來自指定的一組接受字符的非空字符序列; ...該集合由開括號[字符和右括號]字符之間的字符定義。

因此,此轉換將定義一個字符列表,它將被匹配並讀入您的字符串。對此重要的是:

如果在開括號後的第一個字符是一個迴音^,那麼這個字符集將排除這些字符。

如果你在你的字符串看起來"%[^\n]%*c"你有%[^\n]這意味着你匹配任何字符,直到你打一個換行符。

接下來,你有一個%*這個明星是一個轉換,其中忽略了之後的匹配。從手冊頁:

禁止分配。隨後的轉換照常進行,但不使用指針;轉換的結果將被丟棄。如果你看看你的最後一場比賽

所以,你已經有了一個c

c匹配的寬度計數字符(默認爲1)的序列;

所以%*c意味着你要匹配1個字符,然後丟棄它(字符相匹配的是新行 - 其中%[^\n]不服用,因爲你的一切相匹配高達新行符的),它不會存儲在您的string變量中。

閱讀手冊頁是你的朋友。我希望這有幫助。

+0

謝謝。這真的幫助了我。我感謝您的幫助。 –

+1

由於未指定最大大小,因此您還應該提示潛在的緩衝區溢出。 – chqrlie

+1

如果第一個字符是''\ n'',''%* c「'不會發生,'\ n''仍然在'stdin'中,'string'是未知的。 – chux

3
scanf("%[^\n]%*c",string); 

這是說「閱讀一切,直到一個換行符,然後讀取一個字符」。 *(位於%*c)是要取消分配。這是它讀取一行並消耗換行符。

scanf()

可選的 '*' 分配抑制字符:scanf()的讀取所指示的轉換規格 輸入,但是丟棄該 輸入。不需要相應的指針參數,並且此規範不包含在由scanf()返回的成功分配數 中。

但是我想,對於讀取行,使用fgets()來代替,然後消耗尾隨的換行符。

char string[256]; 
if (fgets(string, sizeof string, stdin) == NULL) { 
    /* handle failure */ 
} 
string[strcspn(string, "\n")] = 0; /* For removing the newline if present */ 

這就是less error prone和更好理解。

如果您使用的是glibc,則也可以使用getline()

+0

請注意,'scanf()'格式無法讀取空行,並導致在目標數組更長的行上發生緩衝區溢出。 'fgets()'方法更可取,但是在試圖去除'\ n''之前應該測試返回值,因爲如果'fgets()'失敗並且返回'NULL',string的內容是不確定的。 – chqrlie