2013-11-28 28 views
1

我有以下字符串:另一個語法分析器內的C字符串解析器

GET /index.html HTTP/1.0;;User-Agent: Wget/1.11.4;;Accept: */*;;Host: www.google.com;;Connection 

我使用下面的代碼來解析每個元素:

while (parser != NULL){ 
     printf ("%s\n",parser);   
     parser = strtok (NULL, ";;"); 
    } 

此輸出:

GET /index.html HTTP/1.0 
User-Agent: Wget/1.11.4 
Accept: */* 
Host: www.google.com 
Connection 

現在我只需要獲得主機網址,在這種情況下,該網址是www.google.com。所以首先我想將它與其他東西分開。

要做到這一點,我把另一個語法分析器我以前的一個內像這樣:

while (parser != NULL){ 
     char * pars = strtok (string,":"); 
     while (pars != NULL) { 
      printf("%s\n", pars); 
      pars = strtok (NULL, ":"); 
     } 
     parser = strtok (NULL, ";;"); 
    } 

的這個輸出是一些亂七八糟的東西。我不明白爲什麼......任何人都可以看到錯誤?謝謝

回答

4

你的代碼不起作用的原因是strtok是不可重入的。因爲函數使用靜態變量來保存狀態(這就是你可以用作爲第一個參數調用),所以你不能在嵌套循環中設置strtok的調用:一旦你告訴strtok":"分隔符解析,它會「忘記」與分隔符";"解析的狀態。

切換到可重入版本strtok - strtok_r將解決此問題。該功能要求您提供一個額外的參數savePtr。重要提示:您需要在內部和外部循環中爲savePtrstrtok_r提供兩個不同的變量,否則代碼將顯示相同的行爲。

注:strtok_r不是C標準的一部分。但是,最流行的C庫使它可用。如果您的圖書館沒有strtok_r,請找到它的源代碼,並將其添加到您自己的代碼庫中。

+0

我知道'strtok'有這個問題,我不知道有一個可重入版本。很酷。 – Floris

+0

請注意'strtok_r'不是C標準的(但POSIX)。 – Kninnug

+0

@Kninnug這是真的。我添加了一個提示說明。謝謝! – dasblinkenlight

0

您的方法存在一個大問題 - 除strtok問題不可重入外。這就是strtok尋找「與任何令牌匹配」 - 因此strtok(NULL, ";;")將停止在第一個;,而不是在第一個;;

我會採用不同的方式 - 你正在尋找一個特定的字符串("\nHost: ") - 搜索那個,然後找到下面的位。這似乎是一個更強大的解決方案。

還要注意的是strtok修改其參數 - 基本上就會增加'\0'在那裏發現的道理,所以你將不能夠再使用的字符串它是由strtok操縱之後。如果您想在以後使用該字符串,則需要先製作一個副本。

所有這些都表明您想要重新考慮您的解析策略。

char * inputString =「GET /index.html HTTP/1.0 ;; User-Agent:Wget/1.11.4 ;; Accept:/ ;; Host:www.google。com ;;連接「; char * temp,* hostString,* endHost; temp = strstr(inputString,」;; Host:「)+ 7; //指向」主機:「後 endHost = strstr(temp, 「;;」); 的nChar =(int)的(endHost - 溫度)+ 1; hostString = malloc的(的nChar); strcpy的 (hostString,溫度,NCHAR);

這只是爲了找到/提取主機字符串