как я могу разобрать такую ??строку (6,8)

Я хочу проанализировать строку в формате как int main () { char a [ 80 ] = "(6,8)" ; синтаксический анализ ( a ); return 0 ; } int parsing ( char * a ) { char * word ; char temp [ 80 ] ; stpcpy ( temp , a ); char * new ; char ** newendptr = NULL ; char ** newnewendptr = NULL ; int u , v ; word = strtok ( temp , "(" ); word = strtok ( NULL , "," ); u = strtoumax ( secword , newendptr , 0 ); printf ( "% d n" , u ); new = strtok ( NULL , ")" ); printf ( "% s n" , новый ); v = strtoumax ( new , newnewendptr , 0 ); printf ( "% d% d" , u , v ); return 1 ; } 6strtok () 8 #include <stdio.h> #include <string.h> #include <inttypes.h> static int parsing ( char * a ) { char temp [ 80 ]; strcpy ( temp , a ); printf ( "temp 0 =% p [[% s]] n" , ( void *) temp , temp ); char * word1 = strtok ( temp , "(,)" ); printf ( "word 1 =% p [[% s]] n" , ( void *) word1 , word1 == 0 ? "<ничего>" : word1 ); char * word2 = strtok ( NULL , "(,)" ); printf ( "word 2 =% p [[% s]] n" , ( void *) word2 , word2 == 0 ? "<ничего>" : word2 ); int u = strtoumax ( word1 , 0 , 0 ); int v = strtoumax ( слово2 , 0 , 0 ); printf ( "% d% d n" , u , v ); return 1 ; } int main ( void ) { char a [ 80 ] = "(6,8)" ; синтаксический анализ ( a ); return 0 ; } , и я хочу хранить 6 и 8 в разных переменных. Я пытаюсь использовать «strtok». Однако это дает мне segfault

вот мой код

temp 0 = 0x7fff54844440 [[( 6 , 8 )]] 
слово 1 = 0x7fff54844441 [[ 6 ]] 
слово 2 = 0x7fff54844443 [[ 8 ]] 6 8 prettyprstrtok () ed ">         
 "("

c,parsing,segmentation-fault,

2

Ответов: 2


2 принят

Платит (внимательно прочитать спецификацию .

Этот код работает:

,

Выходной сигнал на моей машине:

)

Проблема заключается в том, что вызов strtoumax()в оригинале с 0разделителем проскакивает через отверстие (, но затем не находит другого, чтобы отметить конец токена, так что остальная часть строки потребляется. Второй вызов strtoumax()поэтому не имеет ничего для обработки и возвращает NULL.

Фиксированный код избегает этой проблемы. Первоначальный разделитель должен включать, (чтобы пропустить это и должен включать, ,чтобы остановить его. Второй разделитель должен включать ); другие символы строго не нужны.

Поскольку вы не проверяете выходной указатель, который является вторым аргументом int, он также может быть NULL (aka 0) каждый раз. Использование strtoX()и присвоение результата inta немного немного. С данными, это нормально, но в целом он рискует потерять важную информацию. Эти errnoфункции являются весьма мощными , но и удивительно тонкими , как они сообщают из значений границ, и т.д. Это использование отбрасывает всю эту информацию (и вам нужно установить uintmax_tна 0 перед вызовом, и вы должны сохранить значение в переменных, чтобы получить и сохранить информацию точно).char c; if (sscanf(a, " (%d ,%d %c", &u, &v, &c) != 3 || c != ')') a€¦oops a€” malformatted dataa€¦

В этом контексте более сжатый (но не обязательно более простой) способ анализа входной строки будет:

sscanf()

Убедитесь, что вы знаете, почему существуют пробелы и почему они находятся там, где они есть. Это может потребовать тщательного изучения спецификации POSIX . Вы можете обойтись без пробелов; вам нужно знать, каковы последствия этого. Если вы хотите убедиться, что вся строка была проанализирована, используйте:char c; int n; if (sscanf(a, " (%d ,%d %c%n", &u, &v, &c, &n) != 3 || c != ')' || temp[n] != '') a€¦Oopsa€¦

%n

Обратите внимание, что parsing()спецификации преобразования не учитываются, поэтому 3 не изменяется.


1

Ответ, данный @Jonathan Leffler, кажется, охватывает то, что не работает в вашем исходном коде. Я просто подумал, что добавлю решение, которое будет анализировать строки, содержащие n-кортежей неизвестной длины. Здесь intфункция принимает в качестве аргументов адрес указателя int, в котором будет храниться имитированный массив чисел, и входную строку, которая должна быть отформатирована как "(int1, int2, ...)". Я не делаю никаких обещаний о поведении этой функции с неправильным вводом. Функция выделяет пространство, сохраняет числа в моделированном массиве и возвращает количество найденных чисел.

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

Вот код:

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

size_t parsing(int **nums, char *a);
void * xrealloc(void *ptr, size_t size);
void shownums(int *nums, size_t n);

int main(void)
{
    int *nums = NULL;
    size_t n;
    char a[80] = "(6, 8)";
    char b[80] = "(2, 3, 5)";
    char c[80] = "(7)";
    char d[80] = "(11,)";
    char e[80] = "(2, 7, 1, 8, 2, 8, 1, 8, 2, 8, 5)";

    n = parsing(&nums, a);
    shownums(nums, n);

    n = parsing(&nums, b);
    shownums(nums, n);

    n = parsing(&nums, c);
    shownums(nums, n);

    n = parsing(&nums, d);
    shownums(nums, n);

    n = parsing(&nums, e);
    shownums(nums, n);

    /* Free allocated memory */
    free(nums);

    return 0;
}

size_t parsing(int **nums, char *a)
{
    size_t nums_sz = 0;
    char *res;

    while ((res = strtok(a, "(,)"))) {
        nums_sz++;
        *nums = realloc(*nums, sizeof(int) * nums_sz);
        (*nums)[nums_sz - 1] = atoi(res);
        a = NULL;
    }

    return nums_sz;
}

void * xrealloc(void *ptr, size_t size)
{
    void *ret = realloc(ptr, size);
    if (ret == NULL) {
        fprintf(stderr, "Unable to allocate memory
");
        exit(EXIT_FAILURE);
    }

    return ret;
}

void shownums(int *nums, size_t n)
{
    for (size_t i = 0; i < n; i++)
        printf("%d ", nums[i]);
    putchar('
');
}

И вот вывод:

6 8 
2 3 5 
7 
11 
2 7 1 8 2 8 1 8 2 8 5 
с, разбор, сегментация вины,
Похожие вопросы