Announcement

Collapse
No announcement yet.

tại sao lệnh scanf không được thực hiện???

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • [C++] tại sao lệnh scanf không được thực hiện???

    e có 2 thắc mắc trong khúc code này, mấy a xem qua rồi giải thích dùm e nhé.
    Code:
    1.   #include "iostream"
    2.   #include "conio.h"
    3.   #include "stdio.h"
    4.   void main()
    5.   {
    6.          int i=0;
    7.          char s='y';
    
    8.       while(s=='y')
    9.       {
    10.              printf("\n\t\ti: %d\n",i++);
    11.           scanf("%c",&s);
    12.       }
    
    13.       printf("\n gia tri cua s: %c",s);
    14.       system("PAUSE");
    15.   }

    1. tại sao khi nhập vào ký tự 'y' thì lệnh while chỉ lặp lại 1 lần và còn bỏ qua lệnh scanf

    2. tại sao khi nhập s='y' thì lệnh printf ở dòng 13 ko in ra chữ y mà lại đưa con trỏ xuống dòng.
    Last edited by BiThuDoan; 04-12-2011, 20:53.

  • #2
    tình hình là khi bạn nhập lệnh scanf lần thứ nhất thì kí tự "enter" cuối cùng bị lưu lại trong bộ đệm của keyboard, nên khi chạy scanf lần thứ 2 thì máy sẽ hiểu kí tự bạn nhập vào là phím "enter" của lần nhập trước => không nhập gì cả, khi đó s="" nên sẽ thoát vòng lặp và xuất ra 1 ký tự rỗng.
    Muốn giải quyết vấn đề thì bạn thêm hàm fflush(stdin); vào giữa dòng số 9 và 10 nhé. Hàm đó đơn giản là xóa bộ đệm ấy đi thôi.
    Nếu bạn không đủ giỏi, đừng cố đi ngược đám đông.

    Comment


    • #3
      Cái này là lỗi thuật toán của em nè.
      em cho việc nhập xuất đặt vào trong vòng lặp while với điều kiện là nếu s còn có giá trị là y thì còn lặp. Em nhập y vào thì thỏa mãn điều kiện nên nó sẽ chạy tiếp các câu lệnh trong vòng lặp. Tới hàm scanf thì đợi em nhập xuất từ bàn phím vào (nên nó nhảy xuống dòng). Em thử nhập 1 ký tự khác thì nó sẽ in ra cho em xem.

      Comment


      • #4
        Originally posted by 11520126 View Post
        tình hình là khi bạn nhập lệnh scanf lần thứ nhất thì kí tự "enter" cuối cùng bị lưu lại trong bộ đệm của keyboard, nên khi chạy scanf lần thứ 2 thì máy sẽ hiểu kí tự bạn nhập vào là phím "enter" của lần nhập trước => không nhập gì cả, khi đó s="" nên sẽ thoát vòng lặp và xuất ra 1 ký tự rỗng
        nghe bạn nói cũng có lý, nhưng tại sao điều này không xảy ra nếu biến s là kiểu int.

        Comment


        • #5
          Đây là lỗi ko mong muốn thỉnh thoảng xảy ra với câu lệnh scanf thôi bạn à, và cũng chẳng ai biết khi nào nó xảy ra cả. Cách tốt nhất là luôn sử dụng hàm fflush(stdin) vào đầu mỗi vòng lặp nếu có lệnh scanf. (Nghe thầy nói vậy) ^^!
          Nếu bạn không đủ giỏi, đừng cố đi ngược đám đông.

          Comment


          • #6
            À, nghĩ ra rồi. Theo mình thì kí tự "enter" trong mã ASCII có mã là #13, và đây là kiểu dữ liệu thuộc kiểu char nên kiểu int sẽ ko nhận nó. Tức là trước cậu lệnh nhập chuỗi nó mới bị lỗi này.
            Bạn làm VD sau sẽ rõ:
            Code:
              #include "iostream"
             #include "stdio.h"
            int main()
             {
                int n,i;
                char s,c;
                printf("Nhap so\n");  //2 bien int nhap binh thuong
                scanf("%d",&n);
                scanf("%d",&i);           
                printf("Nhap chu\n");  //2 bien char nhung chi nhap duoc 1 lan
                scanf("%c",&s);           
                scanf("%c",&c);
                printf("s=%c \n c=%c",s,c); //chi co 1 ki tu \n giua s va c ma xuong dong 2 lan => s nhan gia tri la ki tu enter (xuong dong)
             }
            P/S: mình chỉ hiểu như vậy, có anh nào ghé wa thấy bất hợp lý thì giải thích lại hộ em nhé.
            Last edited by 11520126; 04-12-2011, 01:51.
            Nếu bạn không đủ giỏi, đừng cố đi ngược đám đông.

            Comment


            • #7
              Originally posted by 11520126 View Post
              Đây là lỗi ko mong muốn thỉnh thoảng xảy ra với câu lệnh scanf thôi bạn à, và cũng chẳng ai biết khi nào nó xảy ra cả. Cách tốt nhất là luôn sử dụng hàm fflush(stdin) vào đầu mỗi vòng lặp nếu có lệnh scanf. (Nghe thầy nói vậy) ^^!
              Hàm scanf và tất các hàm khác trong C Không có lỗi gì cả và nó có cơ chế hoạt động có quy tắc đảm bảo tính chính xác, chúng ta hoàn toàn có thể nắm bắt và xử lí theo chủ ý của mình. Trong lập trình nên hiểu rõ vấn đề và yêu cầu tính chính xác minh bạch, ko nên "Đây là lỗi ko mong muốn" hay "chẳng ai biết khi nào nó xảy ra cả. Cách tốt nhất là luôn...".
              E giải thích rất đúng 1 điều từ hàm scanf trong trường hợp này là nó bị dư lại kí tự "enter" nên nó sẽ bỏ qua hàm scanf thứ hai và biến s lúc đó sẽ nhận giá trị là "". Có lẽ điều tiếp theo sau e chưa biết.

              Originally posted by 11520408 View Post
              nhưng tại sao điều này không xảy ra nếu biến s là kiểu int.
              Hàm scanf là hàm nhập có định dạng. Khi gọi hàm, nó sẽ tìm trên bộ đệm bàn phím giá trị phù hợp với kiểu dữ liệu của biến truyền vào hàm, nếu ko có nó sẽ chờ cho đến khi tìm thấy. Vì vậy, nếu s là biến kiểu char, kí tự "enter" sẽ được gán cho biến s. Bây giờ thử xét nếu s là biến kiểu int, tất nhiên trong kiểu dữ liệu int ko có giá trị mà chúng ta đag tạm gọi là "enter", nên kí tự "enter" ko phù hợp, và như vậy, theo cơ chế nó sẽ chờ cho đến khi chúng ta nhập vào và nó lấy được một giá trị kiểu int, ko thể lấy "enter" gán cho 1 biến int đc .
              Lúc trước học nhớ cuốn tin đại cương trường mình cũng có nói về phần này rất rõ các bạn tham khảo thêm nhé.

              Hơi lủng củng chắc đọc cũng hiểu

              Comment


              • #8
                scanf khi nhập vào số nó bỏ rơi ký tự xuống dòng lại standard input và khi nhập chữ thì nó lại đọc những ký tự xuống dòng còn thừa này.
                Cách chuẩn nhất là sử dụng gets (hoặc cin.getline với C++) trong mọi trường hợp và tự xử lý chuỗi được nhập vào. Phổ biến hơn nữa là sử dụng một thư viện thao tác dòng lệnh nào đó như ncurse chẳng hạn.

                Nhưng cấp độ tin đại cương thì các bạn không cần quá cầu toàn phần này. Nhập xuất là vấn đề muôn thuở rắc rối nên trong quá trình học mặc định cứ xem như người dùng sẽ nhập đúng yêu cầu.

                Comment


                • #9
                  Originally posted by 09520334 View Post
                  Hàm scanf và tất các hàm khác trong C Không có lỗi gì cả và nó có cơ chế hoạt động có quy tắc đảm bảo tính chính xác, chúng ta hoàn toàn có thể nắm bắt và xử lí theo chủ ý của mình. Trong lập trình nên hiểu rõ vấn đề và yêu cầu tính chính xác minh bạch, ko nên "Đây là lỗi ko mong muốn" hay "chẳng ai biết khi nào nó xảy ra cả. Cách tốt nhất là luôn...".
                  Vâng, đúng là lúc đầu em hiểu sai vấn đề thật, thanks anh!
                  Nếu bạn không đủ giỏi, đừng cố đi ngược đám đông.

                  Comment


                  • #10
                    Originally posted by 11520126 View Post
                    À, nghĩ ra rồi. Theo mình thì kí tự "enter" trong mã ASCII có mã là #13, và đây là kiểu dữ liệu thuộc kiểu char nên kiểu int sẽ ko nhận nó. Tức là trước cậu lệnh nhập chuỗi nó mới bị lỗi này.
                    Bạn làm VD sau sẽ rõ:
                    Code:
                      #include "iostream"
                     #include "stdio.h"
                    int main()
                     {
                        int n,i;
                        char s,c;
                        printf("Nhap so\n");  //2 bien int nhap binh thuong
                        scanf("%d",&n);
                        scanf("%d",&i);           
                        printf("Nhap chu\n");  //2 bien char nhung chi nhap duoc 1 lan
                        scanf("%c",&s);           
                        scanf("%c",&c);
                        printf("s=%c \n c=%c",s,c); //chi co 1 ki tu \n giua s va c ma xuong dong 2 lan => s nhan gia tri la ki tu enter (xuong dong)
                     }
                    P/S: mình chỉ hiểu như vậy, có anh nào ghé wa thấy bất hợp lý thì giải thích lại hộ em nhé.
                    đã include<stdio.h> rồi còn include<iostream> chi

                    Comment


                    • #11
                      Originally posted by 11520118 View Post
                      đã include<stdio.h> rồi còn include<iostream> chi
                      À mình copy cái đoạn code của bạn ấy để test, mới xóa cái conio.h, ko để ý thằng stdio.h
                      Nếu bạn không đủ giỏi, đừng cố đi ngược đám đông.

                      Comment


                      • #12
                        Originally posted by 09520334 View Post
                        Hàm scanf là hàm nhập có định dạng. Khi gọi hàm, nó sẽ tìm trên bộ đệm bàn phím giá trị phù hợp với kiểu dữ liệu của biến truyền vào hàm, nếu ko có nó sẽ chờ cho đến khi tìm thấy. Vì vậy, nếu s là biến kiểu char, kí tự "enter" sẽ được gán cho biến s. Bây giờ thử xét nếu s là biến kiểu int, tất nhiên trong kiểu dữ liệu int ko có giá trị mà chúng ta đag tạm gọi là "enter", nên kí tự "enter" ko phù hợp, và như vậy, theo cơ chế nó sẽ chờ cho đến khi chúng ta nhập vào và nó lấy được một giá trị kiểu int, ko thể lấy "enter" gán cho 1 biến int đc .
                        Lúc trước học nhớ cuốn tin đại cương trường mình cũng có nói về phần này rất rõ các bạn tham khảo thêm nhé.

                        Hơi lủng củng chắc đọc cũng hiểu

                        am hiểu sâu xa quá, cám ơn đại ca nhiều. Nhân tiện cho e hỏi phần này nằm ở chỗ nào trong cuốn tin học đại cương trường mình vậy

                        Comment


                        • #13
                          Hình như ngay cái chỗ đó thì ko có trong cuốn tin học đại cương trường mình.

                          Comment


                          • #14
                            Originally posted by 11520408 View Post
                            am hiểu sâu xa quá, cám ơn đại ca nhiều. Nhân tiện cho e hỏi phần này nằm ở chỗ nào trong cuốn tin học đại cương trường mình vậy
                            2 năm rồi nên ko bjk trường mình có thay đổi giáo trình ko, chứ ở phần nói về hàm scanf có đề cập đến stdin, nói ko đầy đủ lắm nhưng ở dưới có cái ví dụ, chạy cái ví dụ đó là hiểu hết tất cả.

                            Comment


                            • #15
                              Originally posted by 07520004 View Post
                              scanf khi nhập vào số nó bỏ rơi ký tự xuống dòng lại standard input và khi nhập chữ thì nó lại đọc những ký tự xuống dòng còn thừa này.
                              Cách chuẩn nhất là sử dụng gets (hoặc cin.getline với C++) trong mọi trường hợp và tự xử lý chuỗi được nhập vào. Phổ biến hơn nữa là sử dụng một thư viện thao tác dòng lệnh nào đó như ncurse chẳng hạn.

                              Nhưng cấp độ tin đại cương thì các bạn không cần quá cầu toàn phần này. Nhập xuất là vấn đề muôn thuở rắc rối nên trong quá trình học mặc định cứ xem như người dùng sẽ nhập đúng yêu cầu.
                              gets nó yêu cầu phải có độ dài xác định của chuỗi cần nhập anh ơi
                              Be different and always different
                              http://archlinuxvn.org/
                              http://theslinux.org
                              http://lab.infosec.xyz

                              Comment

                              LHQC

                              Collapse
                              Working...
                              X