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;
            }
tvp viết 20:52 ngày 30/09/2018

Bạn nhớ xóa stdin trước khi nhập pheptinh nnhé, sau khi nhập b, trong stdin vẫn còn kí tự '\n' nên pheptinh sẽ nhận kí tự này chứ ko cho mình nhập

Vo Dang Khoa viết 20:50 ngày 30/09/2018

Hi 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án scanf. 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ệnh scanf 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]

Pham Van Hai viết 20:50 ngày 30/09/2018

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àm fflush() chỉ có tác dụng cho stdoutstderr đối với stdin 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àm scanf là được scanf(" %c", &c); Bạn vui lòng tham khảo thêm ở đây:

G. Samaras – 15 Feb 13

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, …

tvp viết 20:55 ngày 30/09/2018

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ùng fflush()

Lưu Nguyễn Phát viết 20:50 ngày 30/09/2018

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!

Vu Van Chung viết 20:53 ngày 30/09/2018

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!!

Kiii viết 21:00 ngày 30/09/2018

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ớ?

hautruong2k viết 21:01 ngày 30/09/2018

Bạn có thể tham khảo bài của mình

/* Viet chuong trinh nhap vao 2 so x, y va 1 trong 4 toan tu +, -,  *, /.
Neu la + thi in ra ket qua x+y, neu la - thi in ra x-y, neu la * thi
in ra x*y, neu la / thi in ra x/y.(neu y=0 thi in thi thong bao khong
chia duoc) */
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<stdlib.h>

void phepToan()
{
    int ix, iy,iz;
    printf("Nhap vao gia tri cua x: ");
    scanf("%d", &ix);
    printf("Nhap vao gia tri cua y: ");
    scanf("%d", &iy);
    printf("Nhap vao phep toan thuc hien: \n");
    printf("1. Chon +\n2. Chon -\n3. Chon *\n4. Chon /\n");
    scanf("%d", &iz);
    switch(iz)
    {
        case 1: printf("%d + %d = %d",ix, iy, ix+iy );break;
        case 2: printf("%d - %d = %d",ix, iy, ix-iy );break;
        case 3: printf("%d * %d = %d",ix, iy, ix*iy );break;
        case 4:{
                if(iy!=0)
                    printf("%d / %d = %d", ix, iy,ix/iy);break;
                if(iy==0)
                    printf("Khong thuc hien duoc phep tinh vi khong chia duoc cho y=0\n");break;
                }break;
        default: printf("Ban nen nhap vao +, -, *, /");break;
     }

}
int main()
{
    while(1)
    {
      system("cls");
      phepToan();
      int iluachon;
      printf("Ban co muon tiep tuc?\n");
      printf("1. Co\n");
      printf("2. Khong\n");
      scanf("%d", &iluachon);
      if(iluachon==2)
      {
          break;
      }
    }
    getch();
}
rogp10 viết 20:54 ngày 30/09/2018

Đâ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

Bài liên quan
0