30/09/2018, 20:41

Hỏi về câu lệnh fflush(stdin) trong c

cô giáo mình bảo lệnh này để xóa bộ nhớ đệm trong c à
mình có một đoạn code như sau à

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
typedef struct
{
char name[30];
int diem;
}sv;
sv sinhvien[5];
char c[30];
for(int i=0;i<5;i++)
{
printf("moi ban nhap ten cua sinh vien thu %d:",i+1); 
gets(sinhvien[i].name);
printf("moi nhap diem cua sinh vien nha:");
scanf("%d",&sinhvien[i].diem);
}

đoạn code này chạy không hề ổn một tọe nào cả nó chỉ thực hiện vòng lặp thứ 1 đến vòng thứ 2 là tòe luôn à (minh họa sẽ bằng hình ảnh sau)
còn đây là đoạn code thứ 2 nó chỉ thêm mỗi lênh này thôi là lại ok à vậy tại sao khi có lệnh này nó lại chạy ổn
đây là đoạn code thứ 2 à

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
typedef struct
{
char name[30];
int diem;
}sv;
sv sinhvien[5];
char c[30];
for(int i=0;i<5;i++)
{
printf("moi ban nhap ten cua sinh vien thu %d:",i+1);
 fflush(stdin);
gets(sinhvien[i].name);
printf("moi nhap diem cua sinh vien nha:");
scanf("%d",&sinhvien[i].diem);
}
}

mong các bác chỉ giáo thêm

Ngô Doãn Tuấn viết 22:47 ngày 30/09/2018

fflush(stdin);

Khi nhập xâu thì kết thúc bằng một ký tự xuống dòng ‘\n’. Nhưng compiler vẫn nhận đây là một xâu cho tới bộ nhớ tạm thời và truyền nó vào biến xâu tiếp theo của chương trình.
fflush(stdin); với mục đích xóa đi bộ nhớ tạm thời của chương trình để không tồn tại những giá trị rác như bên trên.
Nhưng về bản chất thì nên dùng cin.ignore(100,'\n');

Jobs Apple Steve viết 22:52 ngày 30/09/2018

nhưng nếu không có đoạn code này phía dưới thì nó vẫn chạy bình thường @TheSky

printf("moi nhap diem cua sinh vien nha:");
scanf("%d",&sinhvien[i].diem);
Ngô Doãn Tuấn viết 22:57 ngày 30/09/2018

Ngay phía trên là nhập một xâu và kết thúc là một kí tự enter thì nó vẫn truyền vào biến nhận giá trị đằng sau.
diem kiểu giá trị khác với kí tự nên khi nhận giá trị sẽ báo lỗi.
thêm một đoạn

printf("moi nhap diem cua sinh vien nha:");
 fflush(stdin);
scanf("%d",&sinhvien[i].diem);
cescnghia viết 22:46 ngày 30/09/2018

0[quote=“Jobs_Apple_Steve, post:1, topic:25479”]

for(int i=0;i<5;i++) {
     printf("moi ban nhap ten cua sinh vien thu %d:",i+1); 
     gets(sinhvien[i].name);
     printf("moi nhap diem cua sinh vien nha:");
     scanf("%d",&sinhvien[i].diem);
}

[/quote]
Khi i = 0 : vẫn chạy bình thường, nhưng hàm scanf() chỉ lấy số điểm và không nhảy xuống hàng mới. Con trỏ lúc này nó chỉ vào ngay sau cái số đó. => lần kế tiếp gets() sẽ get những khoảng trống => abort trap

Giải pháp: fflush(stdin) có nghĩa là dọn dẹp sạch cái stdin, ko còn cái gì ở đó nữa, lúc này tên mà bạn nhập vào sẽ đc lấy.

Mình muốn hỏi bạn là tại sao bạn ko sử dụng char* name vì char name[30] rất là nguy hiểm…

Jobs Apple Steve viết 22:54 ngày 30/09/2018

tai sao char name[30]
lai nguy hiem ha ban

cescnghia viết 22:58 ngày 30/09/2018

Bạn thử tưởng tượng khi 1 ai đó nhập tên của họ lớn hơn 30 kí tự thì sẽ như thế nào ? (Buffer Overflow). Và nếu như mình phải nhập điểm cho 10000 người thì mỗi người chiếm 30 Bytes cho phần tên là khá nhiều, với calloc thì bạn có thể tiết kiệm hơn tuỳ vào độ dài tên của họ

Jobs Apple Steve viết 22:48 ngày 30/09/2018

y anh la dung cáp phát động á

cescnghia viết 22:58 ngày 30/09/2018

Yes, nếu bạn dùng cấp phát động thì cô giáo sẽ vui hơn rất nhiều

Jobs Apple Steve viết 22:50 ngày 30/09/2018

malloc voi calooc khac nhau cho nao nhi ma anh dang hoc o dau the anh

Haruhiro viết 22:46 ngày 30/09/2018

malloc thì cần phải tính toán vùng nhớ trước rồi mới truyền vào cho malloc.
calloc thì không cần nó tự tính luôn.
malloc nhanh hơn calloc vì calloc cần thời gian gán giá trị cho vùng nhớ nó vừa cấp.
tùy th mà sử dụng thôi lưu ý malloc có nhiều giá trị rác lắm nhé.

Jobs Apple Steve viết 22:51 ngày 30/09/2018

chang nhe lai hoi ho xem ten cua ho dai bao nhieu tu ha ban

Do Quang Duy viết 22:47 ngày 30/09/2018

Uhm, mình cũng thắc mắc như bạn @Jobs_Apple_Steve Jobs_Apple_Steve , mình biết dùng mỗi malloc thôi, mà malloc phải biết kích thước mảng để cấp phát nên không biết cấp phát như thế nào nhỉ

Haruhiro viết 22:46 ngày 30/09/2018

Dùng calloc nó sẽ tự cấp phát ô nhớ cho đối tượng luôn chỉ cần khai báo thôi :v

Do Quang Duy viết 22:46 ngày 30/09/2018

@auphuocnguyen Uầy, hay vậy, trước giờ mình toàn dùng malloc, ngu quá, phải xem lại mới được

Haruhiro viết 22:46 ngày 30/09/2018

tùy TH mà dùng bạn ơi chứ không phải bài nào mình cũng dùng calloc được

*grab popcorn* viết 22:45 ngày 30/09/2018

Ko cần
dùng fgets(char * str, int limit, FILE * stream) là ok
Như bạn chỉnh cần sửa lại thành
fgets(name, 30, stdin); là an toàn rồi

Thôi thì vô cplusplus coi cho lẹ: http://www.cplusplus.com/reference/cstdio/fgets/ char* fgets ( char* str, int num, FILE * stream ); Đọc kí tự từ stream và lưu vào chuỗi (kiểu trong C), tham số thứ 2 là số kí tự sẽ đọc (từ 0 đến num-1), tham số thứ 3 mặc định là file stdin (đọc từ file khác thì bỏ link file vào đó). Thông thường mấy bạn mới học chỉ dùng mỗi tham số thứ 1 cho hàm fgets nên cứ nghĩ fgets chỉ cần 1 tham số là cái chuỗi cần đọc dữ liệu vào từ bàn phím.

Bài liên quan
0