简体   繁体   English

逐行读取C字符串

[英]Reading a C string line by line

I am trying to parse SIP headers into a line. 我正在尝试将SIP标头解析为一行。 I do this by iterating over a string line by line. 我通过逐行遍历字符串来做到这一点。 Each header should be separated by a new line character. 每个标题均应以换行符分隔。

The input string will look something similar to this: 输入字符串将类似于以下内容:

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

My code: 我的代码:

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

In my code you can see an if block. 在我的代码中,您可以看到一个if块。 In the if block I print out the current line as a cheap way to test my solution, the result of this print statement is nothing. 在if块中,我以便宜的方式打印出当前行来测试我的解决方案,该打印语句的结果为空。 Maybe my understanding on how c interprets the \\n character is not complete. 也许我对c如何解释\\n字符的理解并不完整。

As mentioned in the comments, strtok_r is the ideal function for this. 如注释中所述, strtok_r是实现此目的的理想功能。 It is used to parse a string based on delimiters, and takes a separate pointer for state so that it's safe in multithreaded programs. 它用于基于定界符解析字符串,并为状态使用一个单独的指针,以便在多线程程序中安全使用。

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

Note that this function modifies the string it is working on, so make a copy and work on that if need be. 请注意,此函数会修改正在处理的字符串,因此请进行复制并在需要时进行处理。

EDIT: 编辑:

As mentioned in the comments, strtok_r is only available on POSIX systems, ie not Windows. 如注释中所述, strtok_r仅在POSIX系统上可用,即Windows上不可用。 For Windows, the equivalent function is strtok_s . 对于Windows,等效功能为strtok_s

If you are on POSIX, use its getline function (probably on a FILE* which is your TCP socket, eg. using fdopen ; or you could get a FILE* handle from a buffer using fmemopen ). 如果在POSIX上,请使用其getline函数(可能在TCP FILE*套接字的FILE*上,例如使用fdopen ;或者可以使用fmemopen从缓冲区获取FILE*句柄)。 If you don't have getline , standard C99 has fgets but you'll either limit the line length to some fixed size buffer length or need to reallocate it. 如果没有getline ,则标准C99具有fgets但您可以将行长度限制为某个固定大小的缓冲区长度,或者需要重新分配它。

If you have already all the header data in some buffer, you can parse it using sscanf (handle its return count, use also %n ), or parse it manually (eg using some strcmp ), etc. And of course strtok_r as mentioned by others. 如果你在一定的缓冲已经全部报头数据,您可以使用解析它sscanf (处理其返回计,使用也%n ),或手动分析它(例如,使用一些strcmp ),等等。当然, strtok_r如提及其他。

Did you consider using some existing SIP implementation library? 您是否考虑过使用某些现有的SIP实现库? Notably GNU oSIP ? 值得注意的是GNU oSIP

the posted code contains a few problems. 发布的代码包含一些问题。

missing the header files: 缺少头文件:

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

the strcat() expects both parameters to be char* not an actual character So the call to strcat() should be: strcat()期望两个参数均为char*而不是实际字符,因此对strcat()的调用应为:

strcat(current_line, "\0");

Now, regarding the execution of the code. 现在,关于代码的执行。

(assume str is a pointer to an array of char that is not NUL terminated and is less than 500 bytes long) (假设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 );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM