int n = sscanf("string", "%s %[^, ]%*[, ]%s", word1, word2, word3);
n
中的返回值告訴您成功完成了多少分配。 %[^, ]
是一個否定的字符類匹配,可以找到一個不包含逗號或空格的單詞(如果你喜歡,可以添加標籤)。 %*[, ]
是找到逗號或空格但禁止分配的匹配項。
我不確定我會在實踐中使用它,但它應該可以工作。但是,它沒有經過測試。
也許更緊密的說明書是:
int n = sscanf("string", "%s %[^, ]%*[,]%s", word1, word2, word3);
不同的是,該非分配字符類只接受一個逗號。 sscanf()
在word2
後停止在任何空間(或EOS,字符串末尾),並在分配給word3
之前跳過空格。前一版允許第二個和第三個單詞之間的空格代替逗號,這個問題並不嚴格允許。
由於pmg建議在評論中,分配轉換規範應給予一個長度,以防止緩衝區溢出。請注意,長度不包含空終止符,因此格式字符串中的值必須小於數組大小(以字節爲單位)。還請注意,printf()
允許您使用*
,sscanf()
等使用*
來動態指定大小來抑制分配。這意味着你手頭專門創建的字符串任務:
char word1[20], word2[32], word3[64];
int n = sscanf("string", "%19s %31[^, ]%*[,]%63s", word1, word2, word3);
(Kernighan的&派克建議他們(優秀)的書'The Practice of Programming'動態格式格式字符串)
剛發現一個問題:給出"word1 word2 ,word3"
,它不會讀取word3
。有治癒嗎?
是的,這有一種治療方法,它實際上也是微不足道的。在非賦值逗號匹配轉換規範之前,在格式字符串中添加一個空格。因此:
#include <stdio.h>
static void tester(const char *data)
{
char word1[20], word2[32], word3[64];
int n = sscanf(data, "%19s %31[^, ] %*[,]%63s", word1, word2, word3);
printf("Test data: <<%s>>\n", data);
printf("n = %d; w1 = <<%s>>, w2 = <<%s>>, w3 = <<%s>>\n", n, word1, word2, word3);
}
int main(void)
{
const char *data[] =
{
"word1 word2 , word3",
"word1 word2 ,word3",
"word1 word2, word3",
"word1 word2,word3",
"word1 word2 , word3",
};
enum { DATA_SIZE = sizeof(data)/sizeof(data[0]) };
size_t i;
for (i = 0; i < DATA_SIZE; i++)
tester(data[i]);
return(0);
}
輸出示例:
Test data: <<word1 word2 , word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2 ,word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2, word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2,word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2 , word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
一旦「非分配字符類」只接受一個逗號,可以縮寫,爲在格式字符串文字逗號:
int n = sscanf(data, "%19s %31[^, ] , %63s", word1, word2, word3);
將其插入測試設備中會產生與以前相同的結果。請注意,所有代碼均可從審閱中受益它可以經常(基本上總是)在其工作之後得到改進。
輸入行是單個字符串嗎?所以你必須從字符串中提取令牌(分隔符是空格和逗號),對不對? – vulkanino 2012-03-02 16:50:33
3個字符串,第一個分隔符是空格第二個分隔符逗號 – Nahum 2012-03-02 16:53:22
使用'sscanf'(以及所有'scanf'-family函數)的最正確方法就是不要使用它們..當然,也有例外,scanf的奇怪'恰好符合你的需求,但通常你最終不得不寫一些黑客來解決它的行爲,在這種情況下,你最好先編寫自己的清理解析器。 – 2012-03-02 16:59:56