简体   繁体   English

为什么我不能使用“fgets”将字符串读取到我的 Struct 元素中?

[英]Why I cannot use "fgets" to read a string to an element of my Struct?

I'm trying to create a program almost like "bank" using struct, but when the program should have read the string (variable "nome" that is name in portuguese) it totally ignore the "fgets" that I used .我正在尝试使用结构创建一个几乎类似于“bank”的程序,但是当程序应该读取字符串(葡萄牙语中的名称变量“nome”)时,它完全忽略了我使用的“fgets” This is the part that I was talking about :这是我正在谈论的部分:

printf("\nNome: \n");
fgets(vet[cont+1].nome, sizeof(vet[cont+1].nome), stdin);

And I'm pretty sure that maybe the problem is with the dynamically allocation of my object array.而且我很确定问题可能出在我的对象数组的动态分配上。 Please, give me a help with this problem, thank you!请帮我解决这个问题,谢谢!

PS: I'm sorry but the code is in portuguese (my native language). PS:对不起,代码是葡萄牙语(我的母语)。

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

/*
Programa realiza uma alocacao dinamica por meio 
de uma funcao que recebe a dimensao e retorna o vetor(ponteiro)
*/

struct CLIENTES
{
    int ano_nasc, cpf[11];
    float renda_m;
    char nome[50];
}; //Lista de Objetos

int main(void) 
{
    //Declaracao de Variaveis
    int cont=0, num, num_2, client, i, j;
    CLIENTES *vet;

    //Leitura de Dados
    printf("Digite o numero de Clientes: ");
    scanf("%d", &num);
    vet = (CLIENTES*)malloc(num*sizeof(int));
    printf("Digite os Dados do Cliente.");

    while (cont != num)
    {  
        printf("\nNome: \n");
        fgets(vet[cont+1].nome, sizeof(vet[cont+1].nome), stdin);
        printf("\nAno de Nascimento: ");
        scanf("%d", &vet[cont+1].ano_nasc);
        printf("\nCPF: ");
        scanf("%d", &vet[cont+1].cpf);
        printf("\nRenda Mensal: ");
        scanf("%d", &vet[cont+1].renda_m);
        cont++;
    }

    printf("\nDigite o numero do cliente que voce deseja conferir: ");
    scanf("%d", &num_2);
    for (i=0;i<num;i++)
    {
        if(num_2 == num)
        {
            printf("\nO que deseja saber sobre ele?\n");
            printf("1-Nome\n2-Ano de Nascimento\n3-CPF\n4-Renda Mensal\n\n\n");
            scanf("%d", &client);
            if (client == 1)
            {
                printf("Nome: %c", vet[num_2].nome );
            }
            else if(client == 2)
            {
                printf("Ano de Nascimento: %d", vet[num_2].ano_nasc );
            }
            else if(client == 3)
            {
                for(j=0;j<11;j++)
                {
                    printf("CPF: %d", vet[num_2].cpf[j]);
                }
            }
            else if(client == 4)
            {
                printf("Renda Mensal: %f", vet[num_2].renda_m );
            } 
        }
    }

    //Finalizando o Programa
    printf("\n\nFim do Programa!");
    getch();
    return 0;
}

Problems that I see: 我看到的问题:

  1. You are allocating the wrong amount of memory in the line: 您在该行中分配了错误的内存量:

     vet = (CLIENTES*)malloc(num*sizeof(int)); 

    That should be: 应该是:

     vet = malloc(num*sizeof(*vet)); 

    See Do I cast the result of malloc? 请参见是否强制转换malloc的结果? . The answers explain why you should not cast the return value of malloc . 答案解释了为什么不应该malloc的返回值。

  2. You are using fgets after a scanf . 您在scanf之后使用fgets scanf leaves the newline and other whitespace characters on the stream. scanf将换行符和其他空白字符留在流中。 When fgets is called right after that, fgets reads just the whitespace and the newline. 此后立即调用fgetsfgets仅读取空白和换行符。 You need to add code to ignore the rest of the line after the call to scanf and before the call to fgets . 您需要添加代码,以忽略对scanf的调用之后和对fgets的调用之前的其余部分。

     // Skip everything up to and including the newline. int c; while ( (c = getc(stdin)) != EOF && c != '\\n'); 

    after that, 之后,

     fgets(vet[cont+1].nome, sizeof(vet[cont+1].nome), stdin); 

    should read the data correctly. 应该正确读取数据。

  3. You are using the wrong value in the line: 您在该行中使用了错误的值:

     scanf("%d", &vet[cont+1].cpf); 

    cpf is an array on int s. cpfint的数组。 If you want to read just one int , you can use: 如果您只想读取一个int ,则可以使用:

     scanf("%d", &vet[cont+1].cpf[0]); 
  4. You are using the wrong format specifier in the line: 您在该行中使用了错误的格式说明符:

     scanf("%d", &vet[cont+1].renda_m); 

    It should be: 它应该是:

     scanf("%f", &vet[cont+1].renda_m); // ^^ %f not %d 
  5. You are using the wrong index to access the array vet . 您使用了错误的索引来访问数组vet Everywhere you use vet[cont+1] , it should be vet[cont] . 您在使用vet[cont+1]地方都应该是vet[cont] By using vet[cont+1] , you are not using the first element of the array, vet[0] , and accessing memory beyond what you allocated for when by accessing vet[num] . 通过使用vet[cont+1] ,您将不使用数组的第一个元素vet[0] ,并且访问的内存超出了通过访问vet[num]分配的内存。

If you fix the above problems, your program might work. 如果解决上述问题,则程序可能会运行。

the following code: 以下代码:

1) corrects all the problems I listed in the comments. 1)纠正我在评论中列出的所有问题。

2) drops some of the functionality of the OPs posted code, 2)删除了OP发布代码的某些功能,

Due notice the usage of a while( getchar() ... loop to clean the stdin of any remaining white space. 请注意,使用while(getchar()...循环)可清理标准输入中的所有剩余空白。

3) will still fail if the user tries to enter any white space in the nome field 3)如果用户尝试在nome字段中输入任何空格,仍然会失败

4) the code always checks for errors 4)代码总是检查错误

5) the code always cleans up (with 'free( vet );' before exiting 5)退出之前,代码始终会清理(使用“ free(vet);”

when compiling, always enable all the warnings, (for gcc, at a minimum, use '-Wall -Wextra -pedantic') 编译时,始终启用所有警告(对于gcc,至少要使用“ -Wall -Wextra -pedantic”)

#include <stdio.h>
//#include <conio.h> // not portable, do not use
#include <stdlib.h>

/*
Programa realiza uma alocacao dinamica por meio
de uma funcao que recebe a dimensao e retorna o vetor(ponteiro)
*/

#define NUM_CPF      (11)
#define MAX_NOME_LEN (50)

struct CLIENTES
{
    int ano_nasc;
    int cpf[NUM_CPF];
    float renda_m;
    char nome[ MAX_NOME_LEN ];
}; //Lista de Objetos


int main(void)
{
    //Declaracao de Variaveis
    int cont=0;
    int num;
    int client;
    int i;
    int j;
    struct CLIENTES *vet = NULL;

    //Leitura de Dados
    printf("Digite o numero de Clientes: ");
    if( 1 != scanf("%d", &num) )
    { // scanf failed
        perror( "scanf for num failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, scanf successful

    // clear stdin
    while( getchar() != '\n' );

    if( NULL == (vet = malloc(num*sizeof(struct CLIENTES)) ) )
    { // then malloc failed
        perror( "malloc for multiple struct CLIENTES failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful

    while (cont != num)
    {
        printf("\nNome: ");
        fflush(stdout);
        if( NULL == fgets(vet[cont].nome, MAX_NOME_LEN, stdin) )
        { // fgets failed
            perror( "fgets failed" );
            free( vet );
            exit( EXIT_FAILURE );
        }

        // implied else, fgets successful

       // clear stdin
       //while( getchar() != '\n' );

        printf("\nAno de Nascimento: ");
        if( 1 != scanf("%d", &vet[cont].ano_nasc) )
        { // scanf failed
            perror( "scanf for ano_nasc failed" );
            free( vet );
            exit( EXIT_FAILURE );
        }

        // implied else, scanf successful

        printf("\nCPF: ");
        if( 1 != scanf("%d", vet[cont].cpf) )
        { // scanf failed
            perror( "scanf for cpf failed" );
            free( vet );
            exit( EXIT_FAILURE );
        }

        // implied else, scanf successful

        printf("\nRenda Mensal: ");
        if( 1 != scanf("%f", &vet[cont].renda_m) )
        { // scanf failed
            perror( "scanf for renda_m failed" );
            free( vet );
            exit( EXIT_FAILURE );
        }

        // implied else, scanf successful

        // clear stdin
        while( getchar() != '\n' );

        cont++;
    } // end while



    for (i=0;i<num;i++)
    {
        printf("\nO que deseja saber sobre ele?\n");
        printf("1-Nome\n2-Ano de Nascimento\n3-CPF\n4-Renda Mensal\n\n\n");
        if( 1 != scanf("%d", &client) )
        { // scanf failed
            perror( "scanf for client failed" );
            free( vet );
            exit( EXIT_FAILURE );
        }

        // implied else, scanf successful

        switch( client )
        {
        case 1:
            printf("Nome: %49s", vet[i].nome );
            break;

        case 2:

            printf("Ano de Nascimento: %d", vet[i].ano_nasc );
            break;

        case 3:
            for(j=0; j< NUM_CPF; j++)
            {
                printf("CPF[%d] =  %d", j, vet[i].cpf[j]);
            }
            printf( "\n" );
            break;

        case 4:
            printf("Renda Mensal: %f", vet[i].renda_m );
            break;

        default:
            printf("ERROR: invalid client value, range 1...4\n");
            break;
        }; // end switch
    } // end for

    //Finalizando o Programa
    printf("\n\nFim do Programa!");
    free( vet );
    system( "pause" );
    return 0;
} // end function: main

One more version, with loops and functional.又一个版本,带有循环和功能。

#include <stdio.h>
//#include <conio.h> // not portable, do not use
#include <stdlib.h>

/*
Programa realiza uma alocacao dinamica por meio
de uma funcao que recebe a dimensao e retorna o vetor(ponteiro)
*/

#define NUM_CPF      (11)
#define MAX_NOME_LEN (50)

struct CLIENTES
{
    int ano_nasc;
    int cpf[NUM_CPF];
    float renda_m;
    char nome[ MAX_NOME_LEN ];
}; //Lista de Objetos

void soErros(char erro[20]){

    perror(erro);
    exit( EXIT_FAILURE );

}

int main(void)
{
    //Declaracao de Variaveis
    int cont=0;
    int num;
    int client, saida;
    int i;
    int j;
    int k;
    struct CLIENTES *vet = NULL;

    //Leitura de Dados
    printf("Digite o numero de Clientes: ");
    if( 1 != scanf("%d", &num) )
    { // scanf failed
        soErros("scanf for num failed" );
    }

    // implied else, scanf successful

    // clear stdin
    while( getchar() != '\n' );

    if( NULL == (vet = malloc(num*sizeof(struct CLIENTES)) ) )
    { // then malloc failed
        soErros("malloc for multiple struct CLIENTES failed");
    }

    // implied else, malloc successful

    while (cont != num)
    {
        printf("\nNome: ");
        fflush(stdout);
        if( NULL == fgets(vet[cont].nome, MAX_NOME_LEN, stdin) )
        { // fgets failed
            soErros("fgets failed");
        }

        // implied else, fgets successful

       // clear stdin
       //while( getchar() != '\n' );

        printf("\nAno de Nascimento: ");
        if( 1 != scanf("%d", &vet[cont].ano_nasc) )
        { // scanf failed
            soErros("scanf for ano_nasc failed");
        }

        // implied else, scanf successful

        printf("\nCPF: ");
        if( 1 != scanf("%d", vet[cont].cpf) )
        { // scanf failed
            soErros("scanf for cpf failed");
        }

        // implied else, scanf successful

        printf("\nRenda Mensal: ");
        if( 1 != scanf("%f", &vet[cont].renda_m) )
        { // scanf failed
            soErros("scanf for renda_m failed");
        }

        // implied else, scanf successful

        // clear stdin
        while( getchar() != '\n' );

        cont++;
    } // end while
    int escolha = 0;
    do{

        int *esc = &escolha;
        printf("\nDeseja saber sobre qual cliente?: ");

        for (i=0;i<num;i++)
        {
            printf("\n%d --- %s",i , vet[i].nome);
        } // end for

        if( 1 != scanf("%d", &esc) )
        { // scanf failed
            soErros("scanf for ano_nasc failed");
        } // end if

        printf("\nVocê escolheu o cliente %s", vet[escolha].nome);

        for(i=0;i<num;i++)
        {
            if(i == escolha){
                printf("\n0-Sair\n1-Nome\n2-Ano de Nascimento\n3-CPF\n4-Renda Mensal\n");
                if( 1 != scanf("%d", &client) )
                { // scanf failed
                    soErros("scanf for client failed");
                }

                // implied else, scanf successful

                switch( client )
                {
                case 0:
                    printf("Saindo do menu");
                    break;
                case 1:
                    printf("Nome: %49s", vet[i].nome );
                    break;

                case 2:

                    printf("Ano de Nascimento: %d", vet[i].ano_nasc );
                    break;

                case 3:
                    printf("CPF = ");
                    for(j=0; j< NUM_CPF; j++)
                    {
                        printf("%d", vet[i].cpf[j]);
                    }
                    printf( "\n" );
                    break;

                case 4:
                    printf("Renda Mensal: %f", vet[i].renda_m );
                    break;

                default:
                    printf("ERROR: invalid client value, range 1...4\n");
                    system("cls || clear");
                    break;
                }; // end switch
                printf( "\n" );
            } // end if
        } //end for
        printf("Continuar[1]\nSair[0]\n: ");
        if( 1 != scanf("%d", &saida) )
        {
            soErros("Erro de continuidade");
        } // end if

        switch( saida )
        {
        case 0:
            break;
        }
    } // end do
    while (saida);

    //Finalizando o Programa
    printf("\nFim do Programa!\n");
    free( vet );
    system( "pause" );
    return 0;
} // end function: main

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM