Разбор строки справа налево в C - PullRequest
1 голос
/ 22 февраля 2012

Я пытаюсь отделить адрес 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

Как мне сделать эквивалент синтаксического анализа Python справа налево, то есть [-4:], в C? И, желательно без использования регулярных выражений, как я могу сказать в C, что я хотел бы, чтобы все между '[' и ']'?

Спасибо за любую помощь и совет!

Ответы [ 6 ]

1 голос
/ 22 февраля 2012

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

Вы также можете написать '\ 0' в строку, как в ответе SashaN, что эффективно делит исходную строку на две части. Это не сработает, так как я использовал строковую константу, которую нельзя изменить. Обратите внимание, что «адрес» должен быть достаточно длинным, чтобы вместить адрес во всех случаях.

'a' и 'вещь' являются указателями, поэтому (a-вещь) используется для определения разницы (в символах) между началом вещи и ']'.

0 голосов
/ 23 февраля 2012

Не могли бы вы использовать 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 */

В противном случае вы можете просто просмотреть строку в поисках открытых и закрытых скобок и скопировать содержимое между ними, как показали некоторые другие ответы.

0 голосов
/ 23 февраля 2012

Вот функция, которая будет возвращать подстроку между первым и последним символами в строке, предоставленную в качестве параметра.Флаг 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
0 голосов
/ 23 февраля 2012

Вы можете использовать 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;
}

Обратите внимание, что я на самом деле не анализировал его в обратном направлении, но это не кажется необходимым из предоставленной вами информации.

0 голосов
/ 22 февраля 2012
char* thing = "[2009:7a4d:80d2:33af:0000:0000]:6667";
char ipv6[30];
strncpy (ipv6, thing + 1, 29);
ipv6[29] = '\0';

Это грубо, и работает только с ограничениями фиксированной строки, которые вы обрисовали.

0 голосов
/ 22 февраля 2012

мужская струна (3C)

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