为什么我不能使用 "fgets" 将字符串读入我的结构元素?
Why I cannot use "fgets" to read a string to an element of my 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;
}
我看到的问题:
您在行中分配了错误的内存量:
vet = (CLIENTES*)malloc(num*sizeof(int));
应该是:
vet = malloc(num*sizeof(*vet));
参见 Do I cast the result of malloc?。答案解释了为什么你不应该转换 malloc
的 return 值。
您在 scanf
之后使用 fgets
。 scanf
将换行符和其他空白字符留在流中。之后立即调用 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);
应该能正确读取数据。
您在行中使用了错误的值:
scanf("%d", &vet[cont+1].cpf);
cpf
是 int
上的数组。如果你只想读一个int
,你可以使用:
scanf("%d", &vet[cont+1].cpf[0]);
您在行中使用了错误的格式说明符:
scanf("%d", &vet[cont+1].renda_m);
应该是:
scanf("%f", &vet[cont+1].renda_m);
// ^^ %f not %d
您使用错误的索引访问数组 vet
。凡是用vet[cont+1]
的地方,都应该是vet[cont]
。通过使用 vet[cont+1]
,您没有使用数组的第一个元素 vet[0]
,并且通过访问 vet[num]
.
[=68 访问超出分配的内存=]
如果您解决了上述问题,您的程序可能会运行。
以下代码:
1) 更正了我在评论中列出的所有问题。
2) 删除了 OP 发布代码的一些功能,
请注意使用 while(getchar() ... 循环来清除任何剩余白色的标准输入 space。
3) 如果用户尝试在 nome 字段中输入任何白色 space
,仍然会失败
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
另一个版本,有循环和功能。
#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
我正在尝试使用结构创建一个几乎类似于 "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;
}
我看到的问题:
您在行中分配了错误的内存量:
vet = (CLIENTES*)malloc(num*sizeof(int));
应该是:
vet = malloc(num*sizeof(*vet));
参见 Do I cast the result of malloc?。答案解释了为什么你不应该转换
malloc
的 return 值。您在
之前忽略该行的其余部分scanf
之后使用fgets
。scanf
将换行符和其他空白字符留在流中。之后立即调用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);
应该能正确读取数据。
您在行中使用了错误的值:
scanf("%d", &vet[cont+1].cpf);
cpf
是int
上的数组。如果你只想读一个int
,你可以使用:scanf("%d", &vet[cont+1].cpf[0]);
您在行中使用了错误的格式说明符:
scanf("%d", &vet[cont+1].renda_m);
应该是:
scanf("%f", &vet[cont+1].renda_m); // ^^ %f not %d
您使用错误的索引访问数组
[=68 访问超出分配的内存=]vet
。凡是用vet[cont+1]
的地方,都应该是vet[cont]
。通过使用vet[cont+1]
,您没有使用数组的第一个元素vet[0]
,并且通过访问vet[num]
.
如果您解决了上述问题,您的程序可能会运行。
以下代码:
1) 更正了我在评论中列出的所有问题。
2) 删除了 OP 发布代码的一些功能,
请注意使用 while(getchar() ... 循环来清除任何剩余白色的标准输入 space。
3) 如果用户尝试在 nome 字段中输入任何白色 space
,仍然会失败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
另一个版本,有循环和功能。
#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