30/09/2018, 18:49
Gặp lỗi với hàm scanf trong C
Em có một chương trình, nhập hai biến a,b. Sau đó nhập phép tính CỘNG TRỪ NHÂN CHIA rồi xuất kết quả. Tại sao nó lại bỏ qua bước nhập phép tính?
Cụ thể hơn là nó bỏ qua luôn câu lệnh scanf("%s", &pheptinh);
Nhưng nó lại đúng khi chuyển câu lệnh này lên trên bước nhập a, b?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int main()
{
// Nhap A, B
int a = 0, b = 0;
printf("A: "); scanf("%d", &a);
printf("B: "); scanf("%d", &b);
// Chon phep tinh
char pheptinh;
printf("+ - * \
");
scanf("%c", &pheptinh);
// Thuc hien phep tinh
int ketqua = 0;
switch (pheptinh)
{
case '+':
{ketqua = a + b; printf("Answer: %d
", ketqua);} break;
case '-':
{ketqua = a - b; printf("Answer: %d
", ketqua);} break;
case '*':
{ketqua = a * b; printf("Answer: %d
", ketqua);} break;
case '/':
{float ketqua = (float) a / (float) b; printf("Answer: %.1f
", ketqua);} break;
}
system("pause"); return 0;
}
Bài liên quan
Bạn nhớ xóa stdin trước khi nhập
pheptinh
nnhé, sau khi nhậpb
, trong stdin vẫn còn kí tự'\n'
nênpheptinh
sẽ nhận kí tự này chứ ko cho mình nhậpHi bạn,
Do tất cả dữ liệu khi nhập vào máy tính sẽ được lưu trước trong vùng nhớ đệm
stdin
sau đó mới truyền giá trị vào cho từng biến thông qua lệnh gánscanf
. Trong trường hợp bạn nhập dư dữ liệu, các giá trị còn tồn trên stdin sẽ được chuyển tiếp cho các lệnh gán tiếp theo.Đặc biệt, mỗi lần kết thúc lệnh nhập của bạn bằng phím enter đều lưu trên vùng nhớ đệm dưới dạng kí tự
\n
.Đối với kiểu số nguyên
%d
, lệnhscanf
chỉ tra các giá trị có kiểu số nguyên nên sẽ bỏ qua kí tự\n
. Do vậy, bạn nhập sốB
không gặp vấn đề gì.Riêng đối với kiểu kí tự
%c
, kí tự\n
sẽ được đọc dựa theo bảng mã ASCII, do vậy vô tình làm trôi lệnh gán đối với kiểu kí tự của bạn.Cách khắc phục: Bạn xóa vùng nhớ đệm trước khi cần nhập kiểu kí tự nào bằng lệnh
fflush(stdin)
trước lệnh [quote=“Steven_Luu, post:1, topic:16850”]scanf("%c", &pheptinh);
[/quote]
Tại sao lỗi các bạn trên đã giải thích rõ ràng, mình chỉ không đồng ý khi các bạn ấy gợi ý dùng lệnh
fflush(stdin)
. Mình không hiểu lý do gì mà mọi người hay dùng lênh đó gọi là xóa bộ đệm vì theo như mô tả thì hàmfflush()
chỉ có tác dụng chostdout
vàstderr
đối vớistdin
nó là không xác định.int fflush(FILE *ostream); ostream points to an output stream (stdout) or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
Trong trường hợp của bạn chỉ cần thêm khoảng trắng trước
%c
trong hàmscanf
là đượcscanf(" %c", &c);
Bạn vui lòng tham khảo thêm ở đây:Caution when reading char with scanf (C)
Quite often I see the following problem in people’s code ( as a matter of fact, aliens don’t do that mistake :p ), when trying to input a character again and again with scanf. Usually, …
Mình thấy người ta khuyên dùng
int ch
;while((ch=getchar())!='\n'&&ch!=EOF)
; để xóa stdin hơn là dùngfflush()
Trong số các giải pháp mà các anh bên dưới đưa ra, em thấy giải pháp này hiệu quả nhất, đỡ phải nhớ câu lệnh fflush(stdin). Cách giải quyết rất đơn giản!
Trong sách các thầy hay dạy trước khi nhập xâu phải xóa bộ đệm bằng cách thêm lệnh fflush(stdin) trước!!
Người ta luôn cố gắng chạy theo cái gọi là “Chuẩn” thì bạn lại đi ngược lại chỉ vì nó dễ nhớ?
Bạn có thể tham khảo bài của mình
Đây là một trong những lí do không nên đọc sách cũ (sách đấy cũ lắm rồi) câu lệnh này hết xài rồi.
^ Khá ổn, để 1 2 3 4 được rồi