【问题标题】:Parse string from right-to-left in C在C中从右到左解析字符串
【发布时间】:2012-02-22 19:13:23
【问题描述】:

我正在尝试将 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 中说我想要 '[' 和 ']' 之间的所有内容?

感谢您的帮助和建议!

【问题讨论】:

  • 所以基本上你正在寻找的是 C 中的 substr 实现?
  • 我对 PHP 不太熟悉,但是是的,我相信这正是我要找的。​​span>

标签: c parsing delimiter right-to-left


【解决方案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) 用于给出事物开头和 ']' 之间的区别(以字符为单位)。

【讨论】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

            人字串(3C)

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

            【讨论】:

              猜你喜欢
              • 2022-01-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-05-24
              • 1970-01-01
              • 2017-07-26
              • 1970-01-01
              • 2015-10-17
              相关资源
              最近更新 更多