在C中从右到左解析字符串

时间:2012-02-22 19:13:23

标签: c parsing delimiter right-to-left

我试图将IPV6地址与C中的端口分开。地址和端口将始终由“'['+ address +']:'+ port'给出,例如:”[2009:7a4d: 80D2:33af:0000:0000]:6667" 。在python中,要做到这一点,我会做类似以下的事情:

>>> thing = "[2009:7a4d:80d2:33af:0000:0000]:6667"
>>> print thing[-4:]
6667
>>> print thing[1:30]
2009:7a4d:80d2:33af:0000:0000

如何在C中执行等效的python的从右到左的解析,即[-4:]?并且,最好不使用正则表达式,我怎么能在C中说我想要'['和']'之间的所有内容?

感谢您提供任何帮助和建议!

6 个答案:

答案 0 :(得分:1)

C语言中没有内置字符串操作,因此您需要使用一些函数。 strrchr()从字符串的末尾搜索给定的字符。以下是如何使用它的示例:

int main()
{
  char* thing = "[2009:7a4d:80d2:33af:0000:0000]:6667";
  char* a=strrchr(thing,']'); /* Find the last ']' */
  char address[128]; /* Make somewhere new to hold the address part */
  strncpy(address, thing+1, a-thing-1); /* copy (a-thing)-1 characters, starting from the second character of thing, into address */
  printf("port: %s\n",a+2); /* a+2 is two characters from the start of a (where we found the ']') */
  printf("address: %s\n",address); 
}

你也可以像在SashaN的答案中一样在字符串中写'\ 0',这有效地将原始字符串分成两部分。这在这里不起作用,因为我使用了一个无法修改的字符串常量。请注意,“地址”必须足够长,以便在所有情况下保留地址。

'a'和'thing'都是指针,因此(a-thing)用于给出事物起点和']'之间的差异(字符)。

答案 1 :(得分:0)

char* thing = "[2009:7a4d:80d2:33af:0000:0000]:6667";
char ipv6[30];
strncpy (ipv6, thing + 1, 29);
ipv6[29] = '\0';

它很粗糙,只适用于您概述的固定字符串约束。

答案 2 :(得分:0)

您可以使用strtok_r

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

int main(int argc, char *argv[])
{
    char *saveptr;

    char *address;
    char *port;

    address = strtok_r(argv[1], "[]", &saveptr);
    port = strtok_r(NULL, ":", &saveptr);

    puts(port);

    return EXIT_SUCCESS;
}

请注意,我实际上并没有向后解析它,但从您提供的信息来看,这似乎没有必要。

答案 3 :(得分:0)

这是一个函数,它将返回字符串中最后一个和最后一个字符之间的子字符串,作为参数提供。 exclusive标志告诉它是否在结果中包含这些字符。

我猜测在尝试strncpy()之前应该进行一些额外的验证,所以要小心。

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

char *substr_betweenchars(char *string, char begin, char end, int exclusive)
{
  char *left = strchr(string, begin);
  char *right = strrchr(string, end);
  char *result = 0;

  int a = left - string;
  int b = right - string;
  int n = b - a + 1 - (!!exclusive << 1);

  if (left && right)
  {
    result = malloc(n * sizeof(char));
    strncpy(result, left + !!exclusive, n);
  }

  return result;
}

int main(void)
{
  char string[] = "[2009:7a4d:80d2:33af:0000:0000]:6667";

  printf("%s\n", substr_betweenchars(string, '[', ']', 1));  
  printf("%s\n", substr_betweenchars(string, '[', ']', 0));
  printf("%s\n", substr_betweenchars(string, '8', '2', 1));  
  printf("%s\n", substr_betweenchars(string, '8', '2', 0));  

  return 0;
}

<强>输出:

$ gcc -Wall -o substr substr.c

$ ./substr
2009:7a4d:80d2:33af:0000:0000
[2009:7a4d:80d2:33af:0000:0000]
0d
80d2

答案 4 :(得分:0)

你会考虑在这里使用sscanf()像正则表达式吗?它具有类似正则表达式的功能,可以很好地从格式化字符串中读取地址:

char str[] = "[2009:7a4d:80d2:33af:0000:00000]:6667";
char addr[30];
sscanf(str, "[%29[^]]]", addr);
addr[29] = '\0';
printf("%s", addr); /* 2009:7a4d:80d2:33af:0000:0000 */

否则,您可以直接扫描字符串,查找开括号和近括号,并在其中一些其他答案显示时复制其中的内容。

答案 5 :(得分:-2)

man string(3C)

portstr = strrchr(ipv6str, ':');
if (portstr != NULL) {
    *portstr = '\0';
    portstr++;
}