[爆卦]Sscanf是什麼?優點缺點精華區懶人包

為什麼這篇Sscanf鄉民發文收入到精華區:因為在Sscanf這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者FRAXIS (喔喔)看板C_and_CPP標題[心得] 用sscanf取代strtok時間Tu...


一些技巧是我在解ACM題目的時候湊出來,跟大家分享一下,雖然不是什麼高深的技術。

這些技巧在解題的時候是有用,但是要實用的code可能比較不適合。

如果有更好的方法也歡迎討論。


在parse輸入的時候,用C可以用strtok,只是那函數不太方便使用,我覺得有兩個缺點。

1. strtok會破壞原始的字元陣列,所以常常需要多做一份複製來使用strtok。
2. strtok一次只能針對一個字串用,如果有同時用strtok的需求,用起來比較麻煩。

用sscanf的缺點是如果分隔符號是動態輸入的,那就變成要自己手動產

生sscanf的format string,會比較麻煩。

下面就從簡單的輸入到複雜的輸入來介紹


最簡單的輸入,就是那種一個數字的輸入,或是一行字串的輸入

可以用 while ( scanf( "%d", &n ) == 1 && n != 0 )

和 while ( gets( buf ) != NULL )

來讀取,其中 n != 0 的判斷是因為有些題目會特別指定某些特殊

數字來代表輸入結束。


再來稍微麻煩一點的是題目輸入的個數是動態的,會先有一筆資料

來告知總共有幾筆輸入,大多數都可以用下面的程式來讀取

while ( scanf( "%d", &n ) == 1 && n != 0 ) {
for ( i = 0; i < n; ++i )
scanf( "%d", &input[ i ] );
}


有些問題是一行一行的輸入,但是演算法必須要知道該行長度,每

次輸入之後還要用strlen來算長度很麻煩,可以用下面的寫法

while ( scanf( "%s%n ", &input, &length ) == 1 ) {
}

其中%n的符號代表這次scanf中讀取了幾個字元,就可以讀進資料又知道長度了。

而且%n後的空白是重要的,因為這樣才可以把換行符號吃掉,長度計算才會對。


如果輸入筆數不固定,而且題目的輸入中也不告訴你,都要

靠自己來parse的。像是輸入為一行以某些特殊符號為分隔符號的輸入

例如

1019 1002 1005 1004 1009 1020 1017 9009 1017 1003 1006

我都是用下面這種方法
gets( buf );
for ( p = buf; sscanf( p, " %d %n", &n, &length ) == 1; p += length ) {
}

其中%n表示這次總共讀了多少個字元,所以可以一直把p調整到還沒處理到的部分。


如果輸入分隔符號不是空白,而是多種分隔符號的

舉例來說

aaa-bbb:ccc-ddd-eee:fff-ggg:hhh-iii:jjj:kkk

這就必須要搭配sscanf的 []功能

for ( p = buf, gets( buf ); ; p += length ) {
if ( sscanf( p, "%3[^:-]%1[:-]%n", &input, &delimiter, &length ) != 2 )
break;
}

其中的3和1表示欄位的長度,如果長度是固定的就可以寫上去,確保正確。

這種方法同時還可以知道分隔符號是什麼,如果想要忽略分隔符號的話可以用%*。


如果輸入中存有一些垃圾輸入,就是完全不需要處理的輸入

像是

AAaaaa-BBBbb:Ccccccc-DDDddd

其中的大寫字母代表是無用的字串,這時候可以用 %*s 來處理

for ( p = buf, gets( buf ); ; p += length ) {
if ( sscanf( p, "%*[A-Z]%[^:-]%*[:-]%n", &input, &length ) != 1 )
break;
}

自動就會把大寫字母忽略,也不用浪費變數去儲存他了,我同時也把delimiter忽略了。

雖然sscanf還沒有辦法像regular expression功能那麼強大,不過還是

有一些不錯的功能。

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.119.162.51
smallworld:GOOOOOD!!!! 06/23 00:06
ianfang:好文推 06/23 00:06
smallworld:這篇要M阿 06/23 00:07
VictorTom:推:) 06/23 00:14
elfkiller:水喔 推一個 06/23 00:27
freelancer:超棒,原來scanf 這麼威 06/23 01:21
wowtiger:文章由上往下 心情: 無聊->還好吧->不會吧->會不會太扯了 06/23 01:49
tiyun:好文!!推!! 06/23 03:02
zlw:收藏。有了中括號的功能就比較接近regular expression了 06/23 04:17
imce:推~又學了一招好招 06/23 16:39
ibmibmibm:#1A02ZkC7 06/23 19:36
seedpk5079:借轉XD 06/23 21:25
OTSS:天阿真的是太強了!!QQ感恩! 02/19 23:25
azter:轉錄至看板 THUMath95 01/25 20:13
azter: 借轉 01/25 20:14

你可能也想看看

搜尋相關網站