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

时间:2015-06-18 02:37:11

标签: c pointers memory-management struct fgets

我正在尝试使用struct创建一个几乎像“bank”的程序,但是当程序应该读取字符串(变量“nome”,这是葡萄牙语中的名称)它完全忽略了“fgets”我用过。这是我谈论的部分:

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

我很确定可能问题在于我的对象数组的动态分配。请帮我解决这个问题,谢谢!

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;
}

3 个答案:

答案 0 :(得分:1)

我看到的问题:

  1. 您在行中分配了错误的内存量:

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

    应该是:

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

    Do I cast the result of malloc?。答案解释了为什么不应该转换malloc的返回值。

  2. 您在fgets之后使用scanfscanf在流上留下换行符和其他空格字符。在此之后立即调用fgets时,fgets只读取空格和换行符。在调用scanf之后和调用fgets之前,您需要添加代码以忽略其余部分。

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

    之后,

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

    应该正确读取数据。

  3. 您在行中使用了错误的值:

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

    cpfint上的数组。如果您只想阅读一个int,可以使用:

    scanf("%d", &vet[cont+1].cpf[0]);
    
  4. 您在行中使用了错误的格式说明符:

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

    应该是:

    scanf("%f", &vet[cont+1].renda_m);
        // ^^ %f not %d
    
  5. 您使用了错误的索引来访问数组vet。您使用vet[cont+1]的任何地方都应该是vet[cont]。通过使用vet[cont+1],您不会使用数组的第一个元素vet[0],并且访问内存超出了您通过访问vet[num]时所分配的内容。

  6. 如果您解决了上述问题,您的程序可能会有效。

答案 1 :(得分:1)

以下代码:

1)纠正我在评论中列出的所有问题。

2)删除了OP发布代码的一些功能,

适当注意使用while(getchar()...循环来清理剩余空白区域的标准输入。

如果用户试图在nome字段中输入任何空格

3)仍然会失败

4)代码总是检查错误

5)代码总是清理(退出前使用'free(vet);'

编译时,始终启用所有警告, (对于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

答案 2 :(得分:0)

还有一个版本,带有循环和功能。

#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