Struct Strings Read with scanf Giving Wrong

0

Good luck, I'm developing a C code that performs data registration on files. However, I have a problem with the registerCustom function, which you will see below between the codes.

Client struct:

typedef struct
{
        int idCliente;
        char nome[NOME_TAM_MAX];
        char CPF[16];
        char endereco[ENDERECO_TAM_MAX];    
}Cliente;

Macros:

#define NOME_TAM_MAX 51
#define ENDERECO_TAM_MAX 101

Function registerCustomer :

void cadastrarCliente (void)
{
        Cliente *newCliente = (Cliente *) malloc(sizeof(Cliente));
        if (!newCliente)
        {
                printf("ERRO DE MEMORIA!!!\n");
                exit(-1);
        }
        else
        {
                printf("\n--- PRENCHA OS DADOS DE CADASTRO DO CLIENTE ---\n\n");
                printf("Digite o ID do cliente: ");
                scanf(" %d", &newCliente->idCliente);
                printf("Digite o nome do cliente: ");
                scanf(" %s", newCliente->nome);
                printf("Digite o CPF do cliente: ");
                scanf(" %s", newCliente->CPF);
                printf("Digite o endereco do cliente: ");
                scanf(" %s", newCliente->endereco);

                stream = fopen("cliente.txt", "w+b"); // stream é global
                if (!stream)
                {
                        fputs("ERRO AO TENTAR LER ARQUIVO!!!\n", stderr);
                        exit(-1);
                }
                else
                {
                        fwrite(newCliente, sizeof(Cliente), 1, stream);
                        fclose(stream);
                }
        }

        return;
}

The error is as follows, after typing the client name and pressing enter, all other attributes are skipped (showing just the contents of the printf) and the function comes to an end. I have inverted the fields, put the CPF first and then address, after reading the CPF, everything is successful, but the error repeats itself when reading the address as well.

    
asked by anonymous 29.05.2018 / 02:10

3 answers

1

I started by reiterating what I had already said in comment:

  

Note that scanf("%s reads only one word, leaving the remaining words in the input stream. If you want to read a whole line change by scanf("%[^\n]

However this is the generic example. Looking at your particular case, you have a read of an integer before, so there will be a line break to be read after the first number, which will be the one that is picked up shortly after doing scanf("%[^\n] . The solution is simply to consume this break with a small space:

scanf(" %[^\n]",
//     ^--aqui

With this in mind you could rewrite your reading code like this:

printf("Digite o ID do cliente: ");
scanf("%d", &newCliente->idCliente);
printf("Digite o nome do cliente: ");
scanf(" %[^\n]", newCliente->nome); //mais que uma palavra
printf("Digite o CPF do cliente: ");
scanf(" %s", newCliente->CPF); //uma palavra
printf("Digite o endereco do cliente: ");
scanf(" %[^\n]", newCliente->endereco); //mais que uma palavra

See this example working on Ideone

Another alternative would be to read with fgets that would even be safer, but this has its implications . One of them would be that fgets lets the line break read inside the string. In this case, I did not suggest it because when you use fgets , it is generally more appropriate to do all the readings with fgets and do not intersperse with scanf , which may complicate things a little.

Here is another answer I gave that details the reading with fgets : problem-with-gets-e-fgets

    
30.05.2018 / 13:44
0

Try to use scanf ("\ n% s") because otherwise it will read only one string and leave the others behind. And if your name to enter has spaces the scanf does not amarzena, because it ends the reading in the first space or bar \ 0, if this is your problem try using fgets.

    
29.05.2018 / 03:45
0

Good Night Yuri, I tested your code and apparently managed to solve the problem as follows:

printf("\n--- PRENCHA OS DADOS DE CADASTRO DO CLIENTE ---\n\n");
    printf("Digite o ID do cliente: ");
    scanf(" %d", &newCliente->idCliente);

    fflush(stdin);

    printf("Digite o nome do cliente: ");
    fgets(newCliente->nome,51,stdin);

    fflush(stdin);

    printf("Digite o CPF do cliente: ");
    fgets(newCliente->CPF,16,stdin);

    fflush(stdin);

    printf("Digite o endereco do cliente: ");
    fgets(newCliente->endereco,101,stdin);

I used fflush(stdin) to clear the buffer, avoiding skipping the next fields, it was also possible to capture the string from the keyboard using fgets()

    
30.05.2018 / 02:34