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

Поэтому я распечатал структуру, и она показывает Location, direction и name как NULL, так как это их значение по умолчанию, а длина равна 0.

Ship *newShip = (Ship*)malloc(sizeof(Ship));
sscanf(line, "%s %s %d %[^\n]", newShip->location, newShip->direction,
       &newShip->length, newShip->name);    
printf("\nShip %d: \n\tLocation: %s \n\tDirection: %s \n\tLength: %d \n\tName: %s\n",
       shipNum, newShip->location, newShip->direction, newShip->length, newShip->name);
shipNum++;

Редактировать Используемая структура выглядит следующим образом:

typedef struct {
    char *location;                          
    char *direction;                        
    int length;                             
    char *name;                             
} Ship;

Редактировать: пример форматируемой строки.

"D4 E 3 NullByte Sub"

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

Любая помощь будет большой благодарностью.

1
Argon 11 Апр 2020 в 07:48

2 ответа

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

Выделите память для членов структуры location,direction,name.

Например:

Ship* newShip = malloc(sizeof(Ship));
newShip->location=malloc(size);
newShip->direction=malloc(size);
newShip->name=malloc(size);

Размер обозначает размер памяти для каждого члена структуры.

0
Karthick 11 Апр 2020 в 08:11

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

Если ваша библиотека C поддерживает общее расширение, модификатор выделения m, вы можете написать так:

typedef struct {
    char *location;
    char *direction;
    int length;
    char *name;
} Ship;

Ship *create_ship(const char *line) {
    Ship *newShip = calloc(sizeof(Ship), 1);
    if (newShip) {
        if (sscanf(line, "%ms %ms %d %m[^\n]", &newShip->location,
                   &newShip->direction, &newShip->length, &newShip->name) == 4)) {
            printf("\nShip %d:\n\tLocation: %s\n\tDirection: %s\n"
                   "\tLength: %d\n\tName: %s\n", shipNum, newShip->location, 
                   newShip->direction, newShip->length, newShip->name);
        } else {
            /* format error */
            free(newShip->location);
            free(newShip->direction);
            free(newShip);
            newShip = NULL;
        }
    }
    return newShip;
}

Для более простого и переносимого подхода вы можете определить строковые поля в Ship как массивы char и использовать:

typedef struct {
    char location[20];
    char direction[4];
    int length;
    char name[50];
} Ship;

Ship *create_ship(const char *line) {
    Ship *newShip = calloc(sizeof(Ship), 1);
    if (newShip) {
        if (sscanf(line, "%19s %3s %d %49[^\n]", newShip->location,
                   newShip->direction, &newShip->length, newShip->name) == 4)) {
            printf("\nShip %d:\n\tLocation: %s\n\tDirection: %s\n"
                   "\tLength: %d\n\tName: %s\n", shipNum, newShip->location, 
                   newShip->direction, newShip->length, newShip->name);
        } else {
            /* format error */
            free(newShip);
            newShip = NULL;
        }
    }
    return newShip;
}
0
chqrlie 11 Апр 2020 в 13:58