Динамическая память в C вводить цепь текста

Я пытаюсь сделать так, чтобы следующая программа хранила меня посредством динамической памяти и потом показывала мне различные элементы, введенные клавиатурой. Проблема состоит в том, что посредством %s оно не функционирует и посредством %c только он показывает первый символ цепи текста.

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

typedef struct cliente{
    char dni;
    char nombre;
    char apellido;
}cliente_t;

cliente_t* crear_cliente(){

    cliente_t* nuevo_cliente = malloc(sizeof(cliente_t));
    if(!nuevo_cliente)printf("Error");

    //asignamos los valores
    fflush(stdin);
    printf("Introduce el dni:\t");
    scanf("%s", &nuevo_cliente->dni);

    fflush(stdin);
    printf("Introduce el nombre:\t");
    scanf("%s", &nuevo_cliente->nombre);

    fflush(stdin);
    printf("Introduce el apellido:\t");
    scanf("%s", &nuevo_cliente->apellido);

    return nuevo_cliente;

}


void imprimir_cliente(cliente_t* cliente_impreso){
    printf("DNI: %s\n Nombre: %s\n Apellido: %s\n", cliente_impreso->dni, cliente_impreso->nombre, cliente_impreso->apellido);


}

int main()
{
    cliente_t* cliente1 = crear_cliente();
    imprimir_cliente(cliente1);
    return 0;
}
0
задан 17.04.2018, 13:43
2 ответа

TendrГЎs, что объявлять dni поля, имя и такую фамилию как вектора char с tamaГ±o mГЎximo, который ты захотел позволить:

#define TAM_MAX 80
typedef struct cliente{
    char dni[TAM_MAX];
    char nombre[TAM_MAX];
    char apellido[TAM_MAX];
} cliente_t;

И потом, когда ты сделаешь scanf:

scanf("%79s", &nuevo_cliente->dni);
2
ответ дан 23.11.2019, 23:53

Ты объявил dni поля, имя и фамилию как тип char, а следовательно только есть место для характера.

у Тебя Есть два выбора:

  • , Которые были бы типа array символов, как он тебе предлагается в другом ответе. Проблема состоит в том, что ты не знаешь quГ© tamaГ±o, - соответствующий, и в самом деле, если ты помещаешь что-то как char nombre[20], estarГЎs размещая 20 байт для каждого имени. Если он занимает меньше, ты проматываешь память, если он занимает mГЎs, он не помещается.

  • , Которые были бы указателем в char, и которые размещала бы память для nГєmero необходимых букв, segГєn длина имени.

Восток второй случай кажется лучше, но aГєn не estГЎ просвет cГіmo funcionarГ - в. Если мы не знаем заранее quГ© имя, будет вводить пользователь ВїcГіmo podrГ-хозяева уметь cuГЎnta память размещать?

Прием в этом случае serГ, - чтобы иметь array достаточной длины (мы это можем делать очень большими на всякий случай, например 200) и использовать этот буфер как almacГ©n ненастье, чтобы читать ответ пользователя. Этот ответ ocuparГЎ менее 200 байт, давайте говорить, что он занимает 8. Остальные на данный момент estГЎn проматывая, но не важно слишком много, потому что, что мы заставим в continuaciГіn serГЎ использовать strdup(), чтобы доставать дубликат ответа. Этот дубликат usarГЎ уже sГіlo память mГ-nima необходимая (8), так как copiarГЎ sГіlo символы буфера до того, чтобы находить завершающего цепи, вместо того, чтобы копировать 200.

strdup() возвращает тебе указатель в копию. Ты можешь распределять этот указатель в одно из полей твоей структуры, и повторять ход (повторно используя тот же буфер), чтобы читать каждое поле.

Другая вещь, вместо scanf("%s") может быть интересно тебе использовать fgets(), так как %s sГіlo leerГЎ буквы до первого места (которое ты causarГЎ проблемы в составных именах, так как sГіlo leerГЎ первый), в то время как fgets() читает до возврата каретки (включая). AdemГЎs ты можешь показывать один fgets() mГЎximo символов, которые нужно читать, и убеждаться asГ - в том, что ты не вытекаешь из места, размещенного в твоем буфере.

Следующий cГіdigo осуществляет эту идею:

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


typedef struct cliente{
    char *dni;
    char *nombre;
    char *apellido;
}cliente_t;

cliente_t* crear_cliente(){

    char buffer[200];

    cliente_t* nuevo_cliente = malloc(sizeof(cliente_t));
    if(!nuevo_cliente)printf("Error");

    //asignamos los valores
    fflush(stdin);
    printf("Introduce el dni:\t");
    fgets(buffer, 199, stdin);
    nuevo_cliente->dni = strdup(buffer);

    fflush(stdin);
    printf("Introduce el nombre:\t");
    fgets(buffer, 199, stdin);
    nuevo_cliente->nombre = strdup(buffer);

    fflush(stdin);
    printf("Introduce el apellido:\t");
    fgets(buffer, 199, stdin);
    nuevo_cliente->apellido = strdup(buffer);

    return nuevo_cliente;

}


void imprimir_cliente(cliente_t* cliente_impreso){
    printf("DNI: %s\n Nombre: %s\n Apellido: %s\n", cliente_impreso->dni, cliente_impreso->nombre, cliente_impreso->apellido);


}

int main()
{
    cliente_t* cliente1 = crear_cliente();
    imprimir_cliente(cliente1);
    return 0;
}

Деталей (что deberГ-схвати исправлять):

  • Память никогда не освобождена. Указатели, возвращенные strdup() должны быть освобожденными free(), когда уже они не будут необходимы.
  • Ответы пользователя, будучи прочитаны fgets(), содержат в конце концов возврат каретки, который ты вероятно не хотел бы. Ты это можешь удалять sobreescribiГ©ndolo с одним байт стоимости 0 перед тем, как называть strdup(). Так как 0 - завершающий цепи, это evitarГ, - в который strdup() это скопировал.
3
ответ дан 23.11.2019, 23:53
  • 1
    Смотрит этот fflush(stdin) papá '! Jajaja, очень хороший ответ :D –  NaCl 17.04.2018, 19:12
  • 2
    @NaCl Sí. Этот fflush(stdin) уже был в вопросе и я pasó señ alar, что bá sicamente не служит для совсем не . Не está определенный qué он должен делать один fflush() на буфере ввода, и меньше на вводе está ndar. –  abulafia 17.04.2018, 19:22