Ошибка при использовании fgets () для правильного чтения строки из стандартного ввода, когда ввод меньше максимальной длины - PullRequest
2 голосов
/ 05 апреля 2019

Я пишу функцию, которая читает пользовательский ввод и помещает его в строку, которая затем добавляется в связанный список строк, созданный мной, я использую fgetc(), чтобы очистить stdin и позаботиться о новой строке слева в буфере, а также добавьте \0, необходимый в конце каждой строки, прочитанной функцией. Функция работает нормально только в том случае, если длина строки ввода меньше 8 символов. Я не понимаю почему, так как я установил максимальную длину 100

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

Проблема возникает во второй итерации после предыдущего ввода, где строка чтения превышает 7 символов. Затем программа в этот момент вылетает, что бы я ни пытался. Я в полном недоумении.

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

void LeerLista(Lista L) {
    char temp[100];
    int x, i = 1;
    printf("introduzca la cantidad de strings deseados:\n");
    scanf("%d", &x);
    flushstdin(stdin); // flush the stdin function defined below
    while (i <= x) {   
        printf("introduzca la sentencia nro %d (max 100 caracteres):\n",i);
        if (fgets(temp, sizeof(temp), stdin) != NULL) {   
            if (temp[strlen(temp) - 1] == '\n') {   
                temp[strlen(temp) - 1] = '\0';
                addCab(temp, L);    // add at the head node of the linked list
            } else {
                printf("error de entrada limite maximo excedido, intente de nuevo");
                --i;
            }
        } else {
            printf("error en lectura, intente de nuevo");
            --i;
        }
        ++i;
    }
}

Здесь я перечислю все используемые функции и основные функции:

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

typedef struct nodoc {
    char *key;
    struct nodoc *sig;
} Nodoc;

typedef struct cab {
    Nodoc *alpha;
} Cab;

typedef Cab* Lista;

int main(void) {
    Lista L = newLista();
    LeerLista(L);
    printLista(L);
    getchar();
    return 0;
}

Lista newLista() {
    Lista L = malloc(sizeof(Cab));
    L->alpha = NULL;
    return L;
}

Nodoc *newNodoc(char *c, Nodoc *sig) {
    Nodoc *p = malloc(sizeof(Nodoc));
    p->key = malloc(sizeof(c));
    strcpy(p->key, c);
    p->sig = sig;
    return p;
}

void addCab(char *k, Lista L) {
    Nodoc *p = newNodoc(k, L->alpha);
    L->alpha = p;
}

void flushstdin(FILE *where) {
    int ch;
    while (((ch = fgetc(where)) != '\n') && (ch != EOF))
        /* void */;
}

Я ожидаю, что смогу добавить строки в связанный список любого размера, который меньше максимальной длины.

РЕДАКТИРОВАТЬ: здесь вывод, когда я вводить строки длиной менее 8 символов:

introduzca la cantidad de strings deseados:
3
introduzca la sentencia nro 1 (max 100 caracteres):
1234567
introduzca la sentencia nro 2 (max 100 caracteres):
1234567
introduzca la sentencia nro 3 (max 100 caracteres):
1234567

[1234567, 1234567, 1234567]

если я попытаюсь поместить строку большего размера, программа завершит работу после второй итерации: (я поставил тестовый оператор вывода и напечатал связанный список)

introduzca la cantidad de strings deseados:
3
introduzca la sentencia nro 1 (max 100 caracteres):
12345678
this is a test printing linked list:
[12345678]introduzca la sentencia nro 2 (max 100 caracteres):
1234567

1 Ответ

3 голосов
/ 05 апреля 2019

Внутри newNodoc() вы используете malloc(sizeof(c)), который создает пространство только для размера c, который является указателем на char и сам по себе имеет размер (кажется) 8 в вашей среде.Вы, кажется, намереваетесь освободить место для строки, на которую ссылается этот указатель.Этот размер, однако, неизвестен функции, sizeof(*c) будет равен 1 и также не поможет.

В случае, если вы уже знаете, сколько нужно хранить вне функции, в любом случае вы можете предоставить эти знанияк функции, например, путем добавления другого параметра для предоставления информации о размере.
Для случая строк с нулем в конце, однако вы можете использовать strlen(), даже внутри функции, без дополнительного параметра.(Спасибо Джонатану Леффлеру.)

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