gpt4 book ai didi

c - 读取c中的输入后如何清除缓冲区?

转载 作者:行者123 更新时间:2023-11-30 16:37:55 25 4
gpt4 key购买 nike

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

void generarDimension(int, void **, int);
void reallocarDimensiones(int, void **, int);
void preguntarValor(int *);
char *generarCadena(char *);

typedef struct listaAlu{//this is a list of students
char cedula[7];//this means id
char *nombreApellido;//this means name and lastname
short curso;//this means the year of the student in college/school
unsigned short anho;//and this means year-E.g: 2017
};

int main(void){
struct listaAlu *alu = NULL;
int salir=1;
char c;
unsigned int cont = 0;
unsigned int i;
size_t size = 0;
struct listaAlu *temp = NULL;
while(salir!=0){//Condition until user press exit option
printf("Agregar Alumno?Ingrese 1 para Agregar, y 0 para salir\n");//This means "Add student?Press 1 to add, and 0 to exit
preguntarValor(&salir);//this verifies user input
if(salir==1){//if user adds then it asks info of the student
cont++;
if ( NULL == ( temp = realloc ( alu, size + 2))) {//realloc for each character input and '\0'
fprintf ( stderr, "realloc problem\n");
}//this is for increasing the number of students
alu = temp;
printf("Ingrese Cedula:\n");//This means "Enter id"
scanf("%s", &(alu+(size))->cedula);
printf("Ingrese Nombre y Apellido:\n");//This means "Enter name and lastname"
(alu+(size))->nombreApellido = generarCadena((alu+(size))->nombreApellido);
printf("Ingrese Curso:\n");//This means enter college/school year
scanf("%hd", &(alu+(size))->curso);
printf("Ingrese Anho:\n");//and this means "Enter year"
scanf("%hd", &(alu+(size))->anho);
size++;
}
}
for(i=0;i<cont;i++){
printf("\tAlumno %d\n", i+1);
printf("Nombre:\t%s\n", (alu+i)->nombreApellido);
printf("Cedula:\t%s\n", (alu+i)->cedula);
printf("Curso:\t%d\n", (alu+i)->curso);
printf("Anho:\t%d\n", (alu+i)->anho);
}//This prints Everything the user entered
free(alu);
return 0;
}//Sorry for writing my program entirely on the main >.<

void generarDimension(int bloques, void **ptr, int tamanho){
void **ptrAux;
*ptrAux = malloc(bloques * tamanho);
if(*ptrAux==NULL){
printf("No se pudo almacenar memoria\n");
}else{
*ptr = *ptrAux;
free(ptrAux);
}
}//this I didn't use, but it is for generating an array through a pointer
void reallocarDimensiones(int bloques, void **ptr, int tamanho){
void **ptrAux;
*ptrAux = realloc(*ptr,bloques * tamanho);
if(*ptrAux==NULL){
printf("No se pudo almacenar memoria\n");
}else{
*ptr = *ptrAux;
free(ptrAux);
}
}//This I didn't either, but it is for reallocating any given pointer

void preguntarValor(int *n){
long entero, lector;
*n=-2;
do{
printf("\nSi ingresa otro numero o caracter, vuelva a ingresar opcion\n");
while(!scanf("%d", &entero)){
while((lector=getchar()) !='\n' && lector !=EOF );
}
*n=entero;
}while(*n>1 || *n<0);//You can change this parameters according to the numbers you want
}//This subrutine scans only integers between 1 and 0

char *generarCadena(char *scaneado){
char *temp = NULL;
int in = 0;
size_t size = 0;

while ( '\n' != ( in = getchar ( ))) {//loop until newline
if ( NULL == ( temp = realloc ( scaneado, size + 2))) {//realloc for each character input and '\0'
fprintf ( stderr, "realloc problem\n");
return scaneado;
}
scaneado = temp;
scaneado[size] = in;//set input
scaneado[size + 1] = '\0';//terminate
size++;
}
return scaneado;
}//This subrutine is for geting an input of chars of any given length

这是一个存储大学/学校学生列表的程序,我想知道如何改进此代码,但是在我要求用户输入字符串的部分中,在第二个部分中我无法输入任何内容。如果我尝试输入超过 2 名学生,我的代码不会打印我输入的学生的所有信息

最佳答案

struct listaAlu *temp = NULL;
temp = realloc ( alu, size + 2);//<- wrong size

realloc(alu, size + 2) 将在第一次运行中仅分配 2 个字节。但你需要的远不止这些。所需的总大小是数组中元素的数量乘以结构的大小。即 sizeof(struct listaAlu) ,大约 15 个字节。

realloc( alu, sizeof(struct listaAlu) * (size + 1) );

您不需要将大小增加 2

确保检查正确位置的输入。当 scanf 失败时清除输入。

要获取名字和姓氏,您可以使用 fgetsstrdup

generarDimensionesreallocarDimensiones 存在重大问题。您可能想将它们排除在外。

struct listaAlu{
char cedula[7];//this means id
char *nombreApellido;//this means name and lastname
short curso;//this means the year of the student in college/school
unsigned short anho;//and this means year-E.g: 2017
};

void clear()
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}

int main(void)
{
struct listaAlu *alu = NULL;
size_t size = 0;
while(1)
{
alu = realloc( alu, sizeof(struct listaAlu) * (size + 1) );
if (!alu)
{
fprintf(stderr, "realloc problem\n");
break;
}

char buf[256] = { 0 };

printf("Enter id:\n");
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\r\n")] = 0;
buf[sizeof(alu[size].cedula) - 1] = 0;
strcpy(alu[size].cedula, buf);

printf("Enter name and lastname:\n");
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\r\n")] = 0;
alu[size].nombreApellido = _strdup(buf);

for(;;)
{
printf("Enter college/school year:\n");
if (scanf("%hd", &alu[size].curso) == 1)
break;

printf("input error\n");
clear();
}

for(;;)
{
printf("Enter year:\n");
if (scanf("%hd", &alu[size].anho) == 1)
break;

printf("input error\n");
clear();
}

size++;

printf("Press 1 to continue\n");
char input;
scanf(" %c", &input);
if(input != '1')
break;
clear();
}

for(size_t i = 0; i < size; i++)
{
printf("Alumno %d\n", i);
printf("Nombre:\t%s\n", alu[i].nombreApellido);
printf("Cedula:\t%s\n", alu[i].cedula);
printf("Curso:\t%hd\n", alu[i].curso);
printf("Anho:\t%hd\n", alu[i].anho);
}

for(size_t i = 0; i < size; i++)
free(alu[i].nombreApellido);
free(alu);
return 0;
}

<小时/> 编辑

realloc 不需要包装在不同的函数中。但出于有趣的目的,您可以执行以下操作:

void* my_realloc1(void *ptr, int size)
{
ptr = realloc(ptr, size);
if (!ptr) printf("error\n");
return ptr;
}

//usage:
alu = my_realloc1(alu, sizeof(struct listaAlu) * (size + 1));
if (!alu) printf("error\n");

my_realloc1 在这里可以工作,但是没有任何收获。这只是额外的代码行。直接使用realloc并进行必要的错误处理会更简单、更清晰。

另一种方法是传递引用:

void my_realloc2(void **ptr, int size)
{
*ptr = realloc(*ptr, size);
}

//usage: (*** Note the address `&` operator ***)
my_realloc2(&alu, sizeof(struct listaAlu) * (size + 1));
if (!alu) printf("error\n");

这同样可以工作,但它只是添加了更多代码。

函数generCadena看起来没问题。您可以简化如下:

char *my_getline()
{
char *buf = NULL;
int in = 0;
size_t size = 0;
while('\n' != (in = getchar()))
{
size++;
buf = realloc(buf, size);
buf[size - 1] = (char)in;
}

size++;
buf = realloc(buf, size);
buf[size - 1] = 0;

return buf;
}

//usage:
printf("Enter name and lastname:\n");
alu[size].nombreApellido = my_getline();

并使用scanf读取6个字符(因为cedula的大小为7)

printf("Enter 6 characters:\n");
scanf("%6s", alu[size].cedula);
alu[size].cedula[6] = '\0';
clear();

为了安全起见,请确保输入以 null 终止,并清除缓冲区。

或者您可以使用我在示例中使用的fgets。这将读取最多 256 个字符:

char buf[256];
fgets(buf, sizeof(buf), stdin);

fgets 有时更容易,因为您不需要清除缓冲区。但是 buf 包含行结束符 \n,在这种情况下您必须删除 \n

关于c - 读取c中的输入后如何清除缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47701166/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com