逐行读取C字符串

时间:2016-01-29 13:25:14

标签: c

我正在尝试将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字符的理解并不完整。

3 个答案:

答案 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 );
}