2016-01-29 123 views
1

我正在嘗試將SIP標頭解析成一行。我通過逐行遍歷字符串來完成此操作。每個標題應該用新的一行字符分隔。逐行讀取C字符串

輸入字符串將類似於這樣:

INVITE sip:[email protected] SIP/2.0 
Via: SIP/2.0/UDP pc33.server1.com;branch=z9hG4bK776asdhds Max-Forwards: 70 
To: user2 <sip:[email protected]> 
From: user1 <sip:[email protected]>;tag=1928301774 
Call-ID: [email protected] 
CSeq: 314159 INVITE 
Contact: <sip:[email protected]> 
Content-Type: application/sdp 
Content-Length: 142 

我的代碼:

void readlines(char *str){ 
    int i; 
    int reset; 
    char current_line[500]; 
    char tmp = 0; 
    for(i=0; i<strlen(str); i++){ 
     tmp = str[i]; 
    if (tmp == '\n'){ 
     strncpy(current_line, str+tmp, i); 
     strcat(current_line, '\0'); 
     printf("current line = %s", current_line); 
    } 
    } 
} 

在我的代碼塊,如果你能看到的。在if塊中,我打印出當前行作爲測試我的解決方案的便宜方法,但此打印語句的結果是什麼都沒有。也許我對c如何解釋角色的理解還不完備。

+1

看一看在'strtok'功能 –

+0

感謝您的建議,不幸的是我已經看過這個功能。從我的理解來看,它不是線程安全的,這是我的一個要求。 – btald1331

+1

我發現並沒有意識到的一個問題是,我正在通過將命令行參數傳遞給\ n來測試此函數。但是我通過測試字符串的方式是將字符\ n作爲字面而不是新行字符 – btald1331

回答

1

正如在評論中提到的,strtok_r是理想的功能。它用於根據分隔符分析字符串,併爲狀態提供單獨的指針,以便在多線程程序中安全。

void readlines(char *str){ 
    char *p, *temp; 
    p = strtok_r(str, "\n", &temp); 
    do { 
     printf("current line = %s", p); 
    } while ((p = strtok_r(NULL, "\n", &temp)) != NULL); 
} 

請注意,此函數修改它正在處理的字符串,因此如果需要的話,請複製並處理該字符串。

編輯:

正如評論所說,strtok_r僅在POSIX系統,即不是Windows上使用。對於Windows,等效功能是strtok_s

+0

注意:'strtok_r'只是POSIX。 – user694733

+0

@ user694733謝謝。編輯爲Windows提供替代方案。 – dbush

+0

FWIW:C11附錄K中的'strtok_s()'具有類似的多線程功能。 – chux

0

如果你是在POSIX,利用其getline功能(可能在FILE*這是你的TCP套接字,例如使用fdopen;或者你可以使用fmemopen緩衝區得到FILE*手柄)。如果您沒有getline,則標準C99具有fgets,但您可以將行長限制爲某個固定大小的緩衝區長度,或者需要重新分配它。

如果你在一定的緩衝已經全部報頭數據,則可以使用sscanf(處理其返回計數,還可以使用%n)解析它,或者手工解析它(例如,使用一些strcmp),等等。當然strtok_r的正如其他人所述。

您是否考慮使用一些現有的SIP implementation庫? 值得注意的是GNU oSIP

0

發佈的代碼包含一些問題。

缺少的頭文件:

#include <stdio.h> // printf() 
#include <string.h> // strlen(), strncpy(), strcat() 

strcat()預計這兩個參數是char*不是實際的字符 所以調用的strcat()應該是:

strcat(current_line, "\0"); 

現在,關於執行代碼。

(假設str是指向字符數組不是NUL終止,並且是小於500個字節長)

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void readlines(char *str) 
{ 
    size_t i; 
    char *current_line = NULL; 

    for(i = 0; i< 500 && '\n' != str[i]; i++); 

    if(NULL == (current_line = calloc(i+2, 1))) 
    { // then malloc failed 
     perror("calloc failed"); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, calloc successful 

    memcpy(current_line, str, i); 
    printf("current line = %s", current_line); 
    free(current_line); 
}