Tại sao không nhập được tên sinh viên?

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

struct sinhvien
{
	char hoten[30];
	char msv[5];
	float toan, tin, anh, dtb;

};
void Nhap(struct sinhvien a[], int n)
{
	int i;
	printf("THONG TIN SINH VIEN: \n");
	for (i = 0; i < n; i++)
	{
		fflush(stdin);
		printf("\n Ho ten sinh vien %d: ", i);
		
		gets(a[i].hoten);
		fflush(stdin);
		printf("\n ma sinh vien: ");
		gets(a[i].msv);
		fflush(stdin);
		printf("\n toan, tin, anh: ");
		scanf_s("%f%f%f", &a[i].toan, &a[i].tin, a[i].anh);
		a[i].dtb = (a[i].toan + a[i].tin + a[i].anh) / 3;
	}
}
void Xuat(struct sinhvien a[], int n)
{
	int i;
	printf("\n\tthong tin sinh vien lop cntt\n");
	printf("\n%-30s %-10s %-7s %-7s %-7s %-7s\n", "hoten", "masv", "toan", "tin", "anh", "dtb\n");
	for (i = 0; i < n; i++)
	{
		printf("%-30s %-10s %-7.1f %-7.1f %-7.1f %-7.1f", a[i].hoten, a[i].msv, a[i].toan, a[i].tin, a[i].anh, a[i].dtb);
	}
}

int main()
{
	int i, n;
	struct sinhvien sv[100];
	printf("nhap n:");
	//fflush(stdin);
	scanf_s("%d", &n);
	fflush(stdin);
	Nhap(sv, n);
	Xuat(sv, n);
	_getch();
	return 0;
}

Lỗi của bạn gặp phải như thế nào nhỉ

2 Likes

Câu này không xài được luôn rồi (chứ không còn là “không nên” nữa).

1 Like

“sinhvien” là kiểu dữ liệu, “struct sinhvien” là để khai báo thôi. Dùng đúng chỗ đi bạn.

Code C phải ghi đủ struct sinhvien, typedef xong mới được ghi tắt.

1 Like

đây là mình code lại = vs 2017như trong video hd chỉ thay cái scanf=scanf_s và getch() = _getch() do vs báo lỗi nhưng lại bị bỏ qua câu lệnh nhập tên sv ạ, chương trình là C rồi ạ (source.c)

Lỗi này là do dùng hàm fflsuh(stdin) chưa xóa được bộ đệm nên khi nhập mã sinh viên bị bỏ qua.

Bạn thử thế này xem sao:

void Nhap(struct sinhvien a[], int n)
{
	int i;
	printf("THONG TIN SINH VIEN: \n");
	for (i = 0; i < n; i++)
	{
		printf("\n Ho ten sinh vien %d: ", i+1);
        while ((getchar()) != '\n');
        fgets(a[i].hoten, 30, stdin);
		fflush(stdin);
		printf("\n ma sinh vien: ");
		scanf("c", &a[i].msv);
		while ((getchar()) != '\n');
		printf("\n toan, tin, anh: ");
		scanf(" %f", &a[i].toan);
		scanf(" %f", &a[i].tin);
		scanf(" %f", &a[i].anh);
		//scanf("%f %f %f", &a[i].toan, &a[i].tin, a[i].anh);
		a[i].dtb = (a[i].toan + a[i].tin + a[i].anh) / 3;
	}
}
1 Like

nhưng khi mình thêm mỗi cái getchar() này vào thì lại được và có thể bỏ hết được fflush đi

Vậy là đúng rồi, trước đó bị lỗi là do trong stdin vẫn còn sót lại kí tự xuống dòng nên khi chạy đến lệnh nhập họ tên sinh viên thì hàm gets của bạn nó đọc được kí tự xuống dòng và kết thúc luôn trước khi bạn thực sự nhập họ tên vào.

1 Like

như này cơ a, e bỏ hết fflush trong toàn ctrinh mà vẫn đc

printf("\n Ho ten sinh vien %d: ", i);
//fflush(stdin);
getchar();
gets(a[i].hoten);
//fflush(stdin);
printf("\n ma sinh vien: ");
//fflush(stdin);
gets(a[i].msv);
//fflush(stdin);
printf("\n toan, tin, anh: ");
scanf("%f%f%f", &a[i].toan, &a[i].tin, &a[i].anh);
a[i].dtb = (a[i].toan + a[i].tin + a[i].anh) / 3;

Như mình đã nói ở trên, vì lí do nào đó trước lúc bạn chạy gets(a[i].hoten); thì trong sdtin nó còn 1 kí tự xuống dòng nên lệnh gets(a[i].hoten) được thực thi nó sẽ đọc trong stdin ra thì gặp ngay kí tự xuống dòng và kết thúc luôn.

The C library function **char gets(char str) reads a line from stdin and stores it into the string pointed to by str. It stops when either the newline character is read or when the end-of-file is reached, whichever comes first.

Còn khi chạy

getchar();
gets(a[i].hoten);

thì hàm getchar() đọc kí tự còn sót trong stdin đi nên hàm gets bây giờ không còn bị bỏ qua bởi kí tự còn sót trước đó nữa.

1 Like

sao trong dev-c e dùng fflush(stdin) trước lệnh gets hoten thì nó lại xóa đc a :thinking:

hay trong vs fflush k xóa đc kí tự còn sót trong stdin ạ

Câu này không nên dùng, đến VS còn bỏ không hỗ trợ mà. Vì flush là xả nước => chỉ dùng cho luồng ghi.

2 Likes

Nó cũng tùy vào IDE đấy, a dùng code block test nó cũng chạy được.

1 Like

e tưởng dev c được thì vs cũng được :blush:

sao trong đoạn code trên chỉ có một dòng getchar() ở trước lệnh gets hoten để xóa kí tự sót trước đó nhưng trước lệnh gets msv không có hàm này (thì kí tự enter sẽ được truyền cho msv >> lệnh nhập msv bị bỏ qua không nhập được) nhưng sao vẫn nhập được msv a nhờ

kí tự enter nó không được được truyền cho msv đâu, oử đoạn nhập họ tên, kí tự xuống dòng nó còn sót lại là do hàm scanf ở ngoài hàm main đẻ lại, còn sau hàm gets thì nó bị xóa rồi nên lệnh sau không bị bỏ qua vẫn có thể nhập được từ bàn phím.

Nên bỏ hàm fflush và hàm gets (rất dễ bị lỗi tràn bộ đệm) đi, sử dụng hàm fgets thay thế cho hàm gets thì tốt hơn.

2 Likes

vâng em cảm ơn anh nhiều ạ :heart_eyes:

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?