Назначьте строковый указатель в структуре - PullRequest
0 голосов
/ 16 июня 2020

Я узнал о C и у меня проблемы с этим. Компилируется, но результат неожиданный. В моем коде есть структура:

typedef struct {
    char *title[50];
    float price;
} Book;

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

void Display(Book* lib, int n);

int main() {
    int n;
    printf("Enter the number of books:\n" );
    scanf("%d", &n);
    if(n <= 0) {
        printf("Invalid number of book.");
        return 1;
    }

    Book *lib = (Book *) malloc(n * sizeof(Book));
    if(lib == NULL) {
        printf("The memory is full");
        return 1;
    }

    for(int i = 0; i < n; ++i) {
        char title[50];
        float price;
        printf("Book no.%d\n", i);
        printf("Book Title: ");
        scanf("%s", title);
        printf("Book Price: ");
        scanf("%f", &price);
        printf("\n");
        *(lib+i)->title = title;
        (lib+i)->price = price;
    }

    Display(lib, n);

    return 0;
}

Код успешно компилируется, но результат такой:

Enter the number of books:
2
Book no.0
Book Title: AAAA
Book Price: 1.0

Book no.1
Book Title: BBBB
Book Price: 9.9


----Displaying----
Book no.0
Book Title: BBBB
Book Price: $1.000000

Book no.1
Book Title: BBBB
Book Price: $9.900000

Название первой книги неверно, и это название второй книги. Почему так происходит? И как мне это исправить? Спасибо

Изменить : Одно из требований в моем задании - заголовок Book должен иметь тип char*

Изменить 2 : Я осознал свою ошибку, имея 50 указателей типа char. Как исправить?

Ответы [ 3 ]

3 голосов
/ 16 июня 2020

В определении вашей структуры:

typedef struct {
    char *title[50];
    float price;
} Book;

У вас нет массива char (который может содержать строку), а массива указателей на char, каждый из которых может указывать на строка.

Кроме того, это не соответствует вашим ожиданиям из-за определения члена price:

*(lib+i)->title = title;

Измените определение на:

typedef struct {
    char title[50];
    float price;
} Book;

И читать непосредственно в полях структуры вместо временных переменных, чтобы избежать копирования:

    printf("Book Title: ");
    scanf("%s", lib[i].title);
    printf("Book Price: ");
    scanf("%f", &lib[i].price);

В качестве альтернативы вы можете определить title как char *:

typedef struct {
    char *title;
    float price;
} Book;

В этом случае вам нужно выделить место для указателя, чтобы он указывал на:

    lib[i].title = malloc(50);
    printf("Book Title: ");
    scanf("%s", lib[i].title);

Обратите внимание, что вы не можете указать, чтобы он указывал на локальный, как вы делали раньше, потому что этот локальный объект выходит за пределы области действия в конце l oop, что делает указатель недействительным.

2 голосов
/ 16 июня 2020

Если вам нужно использовать указатель, вам нужно будет использовать динамическое c распределение.

Член структуры должен быть объявлен как указатель, а не как массив указателей:

typedef struct {
    char *title;
    float price;
} Book;

Затем l oop должен выделить память для копии заголовка и скопировать в него заголовок.

    for(int i = 0; i < n; ++i) {
        char title[50];
        float price;
        printf("Book no.%d\n", i);
        printf("Book Title: ");
        scanf("%s", title);
        printf("Book Price: ");
        scanf("%f", &price);
        printf("\n");
        (lib+i)->title = malloc(strlen(title)+1); // +1 for the trailing null
        strcpy((lib+i)->title, title);
        (lib+i)->price = price;
    }
0 голосов
/ 16 июня 2020

Перед обновлением поста объявление элемента данных title структуры

typedef struct {
    char *title[50];
    float price;
} Book;

неверно (в контексте программы не имеет смысла). Структура должна выглядеть так:

typedef struct {
    char title[50];
    float price;
} Book;

То есть каждая книга имеет одно название, а не 50 указателей на названия.

И вместо этого оператора

*(lib+i)->title = title;

у вас есть написать, по крайней мере, как

#include <string.h>

//...

strcpy( ( lib+i )->title, title );

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

    char *title[50];

каждого элемента динамически выделяемый массив.

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

free( lib );

Изменить: одно из требований в моем задании - название книги должно иметь тип char *

После обновления сообщения в В этом случае определение структуры должно выглядеть так:

typedef struct {
    char *title;
    float price;
} Book;

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

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

( lib + i )->title = malloc( strlen( title ) + 1 );
strcpy( ( lib + i )->title, title );

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

for ( int i = 0; i < n; i++ )
{
    free( ( lib + i )->title );
}

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