2013-03-11 43 views
3

我想弄清楚scanf的工作原理。如果我的代碼是這樣的:瞭解Scanf - 處理格式化輸入

scanf("%s %d %f", name, &age, &wage); 

進入這個作爲標準輸入:

james 20 34000.25 

,然後分別打印出的姓名,年齡,工資,我得到一個會想到什麼,同樣的事情因爲我將其納入標準輸入。不過,如果我進入這樣的事情:

scanf("%s/%d/%f", name, &age, &wage); 

,我進入這個作爲標準輸入:

james/20/34000.25 

我得到的字符串值,0和0.00000字符串james/20/34000.25分別針對整數和浮點值。我認爲scanf會將斜線視爲與第一個版本中的空格相同。我如何得到它,所以如果用戶輸入斜線分隔值,我可以適當地分配值的變量?

+1

在我看到關於scanf的每一個答案中都有一些*關鍵的*缺失。你如何判斷'%s','%d','%f','%[^ /]'或'%[^ /]格式規格是否成功匹配?如果用戶只是在Windows中按CTRL + Z,或者在Linux中按CTRL + d以關閉stdin,會發生什麼? scanf *返回*,您的程序很樂意使用垃圾值?什麼scanf *返回*? * Scanf應該這樣做!它爲什麼這樣做,而不是?*因爲[手冊](http://pubs.opengroup.org/onlinepubs/009695399/functions/scanf.html)這樣說。 *您*閱讀手冊? – Sebivor 2013-03-11 03:03:03

+0

......並且在某些情況下,返回值不被忽略;它與-1進行比較以檢查文件錯誤,但不是針對任何*正數*來檢查轉換錯誤! - 爲什麼在嘗試閱讀手冊之前提出問題?本手冊在問題出現之前回答您的問題;你花費一個小時診斷的每一個問題都有一本你可能已經閱讀過的手冊來解決其他五十個問題(除此之外)。更不要說拖拽其他人工時間......爲什麼手冊書面,如果不是被那些瞭解相關功能的人閱讀? – Sebivor 2013-03-11 03:06:13

+0

當你沒有面對實際問題時,從手冊中學習是非常困難的。我閱讀的內容比大多數程序員都要多,但我仍然很少覺得我知道一些東西,直到我必須調試它並親自與它搏鬥。另外,C手冊並不完全是清晰的典範,它有助於讓真實的人指出我的代碼有什麼特別的錯誤。儘管如此,感謝您的信息! – user1427661 2013-03-11 03:10:26

回答

4

%s匹配非空白字符(這是一個貪婪的比賽:它不會走回頭路,看一些其他的比賽是可能的)爲配合非正斜槓字符,請使用%[^/]

(另請注意,在scanf的字符串中空格字符(匹配零個或多個空白字符)具有從非空間非百分比字符一個非常不同的行爲,如'/'(嚴絲合縫'/'

2

要匹配兩個空間分隔和斜線分隔的輸入,您需要一個適度複雜的格式字符串:

if (scanf("%[^ /]%*1[ /]%d%*1[ /]%f", name, &age, &wage) == 3) 
    ...data was read properly... 
else 
    ...something went wrong... 

第一個轉換規範是一個掃描集,它接受一系列非空格,非斜槓(因此它會停在第一個空格或斜線處)。最好指定接受多少個字符的上限,以避免stack overflow;例如,如果char name[32];,然後%31[^ /](注意一個接一個)。第二個轉換規範%*1[ /]接受空白或斜槓[ /]的單個字符(1),並且不將其分配給任何變量(*)。第三個轉換規範是標準數字輸入,跳過前導空格,允許輸入負數等。第四個轉換規範與第二個轉換規範相同,第五個是float的標準格式(這意味着34000.25 7位有效數字位於可表示值範圍的外端)。

請注意,「出錯了」部分難以一致地向用戶報告錯誤。這就是爲什麼包括我自己在內的許多人建議不要使用scanf()fscanf(),而更願意使用fgets()或POSIX getline來讀取用戶的一行文字,然後使用sscanf()來分析它。您可以更輕鬆地報告問題。另請注意,scanf()的返回值是成功分配的數量;它不包括包含*的轉換規格。