我正在尝试将SIP标头解析为一行。我通过逐行迭代字符串来做到这一点。每个标题应该用换行符分隔。
输入字符串看起来与此类似:
INVITE sip:user2@server2.com SIP/2.0
Via: SIP/2.0/UDP pc33.server1.com;branch=z9hG4bK776asdhds Max-Forwards: 70
To: user2 <sip:user2@server2.com>
From: user1 <sip:user1@server1.com>;tag=1928301774
Call-ID: a84b4c76e66710@pc33.server1.com
CSeq: 314159 INVITE
Contact: <sip:user1@pc33.server1.com>
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块。在if块中,我打印出当前行作为测试我的解决方案的廉价方法,这个print语句的结果是什么。也许我对c如何解释\n
字符的理解并不完整。
答案 0 :(得分: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
。
答案 1 :(得分:0)
如果您使用的是POSIX,请使用其getline函数(可能在您的TCP套接字FILE*
上,例如使用fdopen
;或者您可以获得FILE*
使用fmemopen
从缓冲区处理。如果您没有getline
,则标准C99具有fgets
,但您可以将行长度限制为某个固定大小的缓冲区长度,或者需要重新分配它。
如果您已经在某个缓冲区中拥有了所有标头数据,则可以使用sscanf
解析它(处理其返回计数,同时使用%n
),或手动解析它(例如使用一些{{ 1}})等等,当然还有其他人提到的strcmp
。
您是否考虑使用现有的SIP implementation库? 特别是GNU oSIP?
答案 2 :(得分:0)
发布的代码包含一些问题。
缺少标题文件:
#include <stdio.h> // printf()
#include <string.h> // strlen(), strncpy(), strcat()
strcat()
要求两个参数都是char*
而不是实际字符
所以对strcat()的调用应该是:
strcat(current_line, "\0");
现在,关于代码的执行。
(假设str
是指向未终止NUL并且长度小于500字节的char数组的指针)
#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 );
}