C中从右到左解析字符串

发布于 2025-01-08 07:48:38 字数 424 浏览 1 评论 0原文

我试图将 IPV6 地址与 C 中的端口分开。地址和端口始终由“'[' + 地址 + ']:' + 端口”给出,例如:“[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 中说我想要 '[' 和 ']' 之间的所有内容?

感谢您的任何帮助和建议!

I am trying to separate an IPV6 address from a port in C. The address and port will always be given by "'[' + address + ']:' + port", for example: "[2009:7a4d:80d2:33af:0000:0000]:6667". In python, to do this, I would do something similar to the following:

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

How do I do the equivalent of python's right-to-left parsing, i.e. [-4:], in C? And, preferably without using regex, how can I say in C that I would like everything between '[' and ']'?

Thanks for any help and advice!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

云胡 2025-01-15 07:48:38

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) 用于给出 thing 的开头和 ']' 之间的差异(以字符为单位)。

C does not have string manipulation built into the language, so you need to use a few functions. strrchr() searches for a given character from the end of the string. Here's an example of how to use it:

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

You can also write a '\0' into the string as in SashaN's answer, which effectively divides the original string in two. This won't work here as I used a string constant which can't be modified. Note that 'address' must be long enough to hold the address under all cases.

'a' and 'thing' are both pointers, so (a-thing) is used to give the difference (in characters) between the start of thing and the ']'.

淡忘如思 2025-01-15 07:48:38
char* thing = "[2009:7a4d:80d2:33af:0000:0000]:6667";
char ipv6[30];
strncpy (ipv6, thing + 1, 29);
ipv6[29] = '\0';

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

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

It's crude, and only works with the fixed-string constraints you outlined.

妄想挽回 2025-01-15 07:48:38

您可以使用 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;
}

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

You can use strtok_r for this:

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

Note that I haven't actually parsed it backwards, but that doesn't seem necessary from the information you provided.

水中月 2025-01-15 07:48:38

这是一个函数,它将返回字符串中第一个和最后一个字符之间的子字符串(作为参数提供)。 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

Here is a function that will return the substring between the firstmost and lastmost characters in a string, provided as parameter. The exclusive flag tells it whether or not to include those characters in the result.

I'm guessing some additional validation should be done before attempting strncpy(), so be careful.

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

Output:

$ gcc -Wall -o substr substr.c

$ ./substr
2009:7a4d:80d2:33af:0000:0000
[2009:7a4d:80d2:33af:0000:0000]
0d
80d2
原来分手还会想你 2025-01-15 07:48:38

您会考虑在这里像正则表达式一样使用 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 */

否则,您可以扫描字符串,查找左括号和右括号,然后复制其中的内容,如其他一些答案所示。

Would you consider using sscanf() here like a regex? It has a regex-like feature that could read the address from the formatted string quite nicely:

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 */

Otherwise you could just scan through the string looking for the open and close brackets and copy the contents in between as some of the other answers have shown.

国粹 2025-01-15 07:48:38

男绳(3C)

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

man string(3C)

portstr = strrchr(ipv6str, ':');
if (portstr != NULL) {
    *portstr = '\0';
    portstr++;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文