Какой самый простой способ разобрать строку в C? - PullRequest
2 голосов
/ 13 мая 2010

Я должен разобрать эту строку в C:

XFR 3 NS 207.46.106.118:1863 0 207.46.104.20:1863\r\n

И сможете получить часть 207.46.106.118 и часть 1863 (первый IP-адрес).

Я знаю, что мог бы переходить от символа к символу и в конечном итоге найти свой путь, но как проще всего получить эту информацию, учитывая, что IP-адрес в строке может измениться на другой формат (с меньшим количеством цифр)?

Ответы [ 7 ]

11 голосов
/ 13 мая 2010

Вы можете использовать sscanf() из стандартной библиотеки Си. Вот пример того, как получить ip и порт в виде строк, предполагая, что часть перед адресом постоянна:

#include <stdio.h>

int main(void)
{
    const char *input = "XFR 3 NS 207.46.106.118:1863 0 207.46.104.20:1863\r\n";

    const char *format = "XFR 3 NS %15[0-9.]:%5[0-9]";
    char ip[16] = { 0 };  // ip4 addresses have max len 15
    char port[6] = { 0 }; // port numbers are 16bit, ie 5 digits max

    if(sscanf(input, format, ip, port) != 2)
        puts("parsing failed");
    else printf("ip = %s\nport = %s\n", ip, port);

    return 0;
}

Важными частями строк форматирования являются шаблоны сканирования %15[0-9.] и %5[0-9], которые будут соответствовать строке длиной не более 15 символов, состоящей из цифр или точек (т. Е. IP-адреса не будут проверяться на корректность ) и строка длиной не более 5 цифр соответственно (что означает, что будут проходить недопустимые номера портов выше 2 ^ 16 - 1).

2 голосов
/ 13 мая 2010

Перебирайте, пока не получите первое «.», И возвращайтесь, пока не найдете «». Цикл вперед, пока вы не найдете ':', собирая подстроки каждый раз, когда встречаетесь '.' или же ':'. Вы можете проверить количество подстрок и их длину как простую проверку ошибок. Затем выполните цикл, пока не найдете '', и у вас будет деталь 1863 года.

Это было бы надежно, если начало строки не сильно отличается. И тоже очень просто. Вы могли бы сделать это еще проще, если бы строка всегда начиналась с "XFR 3 NS".

2 голосов
/ 13 мая 2010

Вы можете использовать strtok для токенизации разбиения в пространстве, или вы можете использовать одно из семейства scanf для извлечения данных.

Однако во всем этом есть большое предостережение: эти функции печально известны своей безопасностью и неправильным обращением с вводом. YMMV.

2 голосов
/ 13 мая 2010

Зависит от того, что определяет формат документа. В этом случае это может быть просто токенизация строки и поиск токенов, что вы хотите. Просто используйте strtok и разделите пробелы, чтобы получить 207.46.106.118:1863, а затем вы можете токенизировать это снова (или просто отсканировать на : вручную), чтобы получить нужные компоненты.

1 голос
/ 13 мая 2010

В этом случае strok () имеет тривиальное применение и будет моим выбором. В целях безопасности, вы можете посчитать «:» в вашей строке и продолжить, если есть ровно один:

0 голосов
/ 13 мая 2010

Это может быть излишним, так как вы сказали, что не хотите использовать библиотеку регулярных выражений, но программа re2c даст вам синтаксический анализ регулярных выражений без библиотеки: она генерирует DFSM для регулярного выражения в виде кода C. Регулярные выражения указываются в комментариях, встроенных в код языка Си.

И то, что кажется излишним сейчас, может стать утешением для вас позже, если вам придется анализировать остальную часть строки; Гораздо проще изменить несколько регулярных выражений, чтобы скорректировать или добавить новый синтаксис, чем модифицировать кучу специального кода токенизации. И это делает структуру того, что вы анализируете, намного понятнее в вашем коде.

0 голосов
/ 13 мая 2010

Если анализируемые строки хорошо отформатированы, я бы согласился с предложением Даниэля и Укко использовать strtok ().

Слово предупреждения, хотя: strtok () изменяет строку, которую он анализирует. Не всегда то, что вы хотите.

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