Fw: [心得] 用sscanf取代strtok

看板THUMath95作者 (Yilin)時間8年前 (2016/01/25 20:13), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/1
※ [本文轉錄自 C_and_CPP 看板 #1AFwhK53 ] 作者: FRAXIS (喔喔) 看板: C_and_CPP 標題: [心得] 用sscanf取代strtok 時間: Tue Jun 23 00:01:23 2009 一些技巧是我在解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

06/23 00:06, , 1F
GOOOOOD!!!!
06/23 00:06, 1F

06/23 00:06, , 2F
好文推
06/23 00:06, 2F

06/23 00:07, , 3F
這篇要M阿
06/23 00:07, 3F

06/23 00:14, , 4F
推:)
06/23 00:14, 4F

06/23 00:27, , 5F
水喔 推一個
06/23 00:27, 5F

06/23 01:21, , 6F
超棒,原來scanf 這麼威
06/23 01:21, 6F

06/23 01:49, , 7F
文章由上往下 心情: 無聊->還好吧->不會吧->會不會太扯了
06/23 01:49, 7F

06/23 03:02, , 8F
好文!!推!!
06/23 03:02, 8F

06/23 04:17, , 9F
收藏。有了中括號的功能就比較接近regular expression了
06/23 04:17, 9F

06/23 16:39, , 10F
推~又學了一招好招
06/23 16:39, 10F

06/23 19:36, , 11F
06/23 19:36, 11F

06/23 21:25, , 12F
借轉XD
06/23 21:25, 12F

02/19 23:25, , 13F
天阿真的是太強了!!QQ感恩!
02/19 23:25, 13F
※ 發信站: 批踢踢實業坊(ptt.cc) ※ 轉錄者: azter (61.222.81.253), 01/25/2016 20:13:37
文章代碼(AID): #1MfX5oTY (THUMath95)