Từ 1 tới 5 trên tổng số 5 kết quả

Đề tài: Không chạy được lệnh gets trong một hàm cấu trúc.

  1. #1
    Ngày gia nhập
    10 2007
    Nơi ở
    TP. HCM
    Bài viết
    52

    Mặc định Không chạy được lệnh gets trong một hàm cấu trúc.

    Mình làm một bài về cấu trúc đơn giản như sau:

    _ Vào số liệu cho một danh sách gồm m nhân viên gồm có họ tên (kiểu char), ngày tháng năm sinh (kiểu int) và bậc lương (kiểu float);
    _ In số liệu của các nhân viên vừa nhập.
    _ Sắp xếp danh sách m nhân viên này theo chiều tăng của năm sinh.
    _ In danh sách đã sắp xếp.

    Code của mình đây:
    C Code:
    1. #include <stdio.h>
    2. #include <conio.h>
    3. #include <string.h>
    4.  
    5. typedef struct {
    6.     int ng, th, n;
    7. } ngay;
    8.  
    9. typedef struct {
    10.     char ht[20];
    11.     ngay ns;
    12.     float bl;
    13. } nhan_vien;
    14.  
    15. /* vao so lieu cho mot nhan vien */
    16. void vaosl(nhan_vien *pnv)                     
    17. {
    18.     nhan_vien nv;
    19.  
    20.     printf("Nhap ho ten: ");
    21.     gets(nv.ht);
    22.  
    23.     printf("Nhap ngay sinh: ");
    24.     scanf("%d %d %d", &nv.ns.ng, &nv.ns.th, &nv.ns.n);
    25.    
    26.     printf("Nhap bac luong: ");
    27.     scanf("%f", &nv.bl);                       
    28.    
    29.     *pnv = nv;                                 
    30. }
    31.  
    32. /* ra so lieu cho mot nhan vien */
    33. void rasl(nhan_vien nv)
    34. {
    35.     printf("Ho ten: %s", nv.ht);
    36.     printf("\nNgay sinh: %d/%d/%d", nv.ns.ng, nv.ns.th, nv.ns.n);
    37.     printf("\nBac luong: %.2f", nv.bl);
    38. }
    39.  
    40. /* hoan vi hai nhan vien */
    41. void hoanvi(nhan_vien *nv1, nhan_vien *nv2)
    42. {
    43.     nhan_vien nvt;
    44.  
    45.     nvt = *nv1;
    46.     *nv1 = *nv2;
    47.     *nv2 = nvt;
    48. }
    49.  
    50. /* sap xep nhan vien tang theo nam sinh */
    51. void sapxep(nhan_vien ds[], int m)              // ds[] la mang cau truc nhan_vien, m la so nhan vien
    52. {
    53.     int i, j;
    54.  
    55.     for (i = 0; i < m - 1; i++) {
    56.         for (j = i + 1; j < m; j++)
    57.             if (ds[i].ns.n > ds[j].ns.n)
    58.                 hoanvi(&ds[i], &ds[j]);         // hoan vi 2 cau truc nhan vien
    59.     }
    60. }
    61.  
    62. int main()
    63. {
    64.     int i, m;                                   // m la so nhan vien
    65.     nhan_vien ds[50];                           // so nhan vien khong qua 50 nguoi
    66.    
    67.     printf("Nhap so nhan vien: ");
    68.     scanf("%d", &m);                           
    69.     /* nhap so lieu cho m nhan vien */
    70.     for (i = 0; i < m; i++) {
    71.         printf("Nhap so lieu cho nhan vien %d:\n", i);
    72.         vaosl(&ds[i]);
    73.         printf("\n");
    74.     }
    75.  
    76.     printf("\n\nSO LIEU CUA CAC NHAN VIEN VUA NHAP:\n\n");
    77.  
    78.     /* in so lieu cac nhan vien vua nhap */
    79.     for (i = 0; i < m; i++) {
    80.         printf("So lieu cua nhan vien %d:\n", i);
    81.         rasl(ds[i]);
    82.         printf("\n\n");
    83.     }
    84.  
    85.     sapxep(ds, m);
    86.  
    87.     printf("\n\nSAP XEP CAC NHAN VIEN TANG THEO NAM SINH:\n\n");
    88.  
    89.     for (i = 0; i < m; i++) {
    90.         printf("So lieu cua nhan vien %d:\n", i);
    91.         rasl(ds[i]);
    92.         printf("\n\n");
    93.     }
    94.  
    95.     getch();
    96.     return 0;
    97. }
    Vấn đề của mình là khi chạy chương trình, nó không dừng lại cho mình nhập họ tên mà nhảy qua nhập ngày, tháng, năm sinh luôn. Mình cho chạy chương trình từng bước thì thấy nó chạy tới hàm gets (trong hàm void vaosl(nhan_vien *pnv)) thì lại nhảy xuống dòng tiếp theo là nhập ngày, tháng, năm sinh mà không dừng màn hình lại cho mình nhập họ tên.

    Chỉ có mổi vấn đề này thôi còn các hàm khác đều chạy tốt. Nghĩ mãi mà vẫn không hiểu tại sao. Không biết có sai chổ nào không nữa. Mình dịch chương trình bằng Visual Studio 2008.
    /* The thing that I think is the thing that I do. */

  2. #2
    Ngày gia nhập
    04 2008
    Bài viết
    336

    hì, sau scanf("%d", &m); bạn thêm vào fflush(stdin); là hết.
    Lý do: sau khi scanf ký tự "\n" vẫn còn trong stdin nên đoạn nhập tiếp theo của bạn sẽ bị "trôi". fflush(stdin) sẽ xóa các ký tự dư trong stdin.
    nói chung là sau khi scanf nên có fflush(stdin) hoặc fflushall()
    Đã được chỉnh sửa lần cuối bởi 6220119 : 06-08-2008 lúc 08:44 AM.

  3. #3
    Ngày gia nhập
    10 2007
    Nơi ở
    TP. HCM
    Bài viết
    52

    Hì mới google thì biết được hàm fflush(stdin) dùng làm sạch dữ liệu trong dòng nhập chuẩn stdin. Không gets được là do bị trôi hàm như bạn nói. Tuy nhiên có ý kiến cho rằng không nên dùng fflush(stdin). Mình đọc được bài viết cũ của anh rox_rook có đoạn trích này:
    On occasions you may need to clear unwanted data in an input stream, most commonly keyboard input. One frequently suggested way of doing this is by using fflush(stdin). This is incorrect, and should be avoided, here is why. To learn how to flush the input buffer correctly, read this FAQ entry.

    stdin is a standard FILE* variable that points to the input stream normally used for keyboard input. The fflush() function is deemed to flush buffers. Put the two together and you have a method for clearing the input stream easily, right? WRONG! This is a common misconception in C and C++ programming, an extract from the C standard will help explain:

    int fflush(FILE *ostream);

    ostream points to an output stream 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.


    So, if the file stream is for input use, as stdin is, the behaviour is undefined, therefore it is not acceptable to use fflush() for clearing keyboard input.

    As usual, there are some exceptions, check your compiler's documentation to see if it has a (non-portable) method for flushing input.
    Mình đọc mà còn mơ hồ lắm. Ai dịch giúp đoạn này rõ ràng hơn được không.

    Mình cũng tìm được 1 cách không dùng fflush(stdin) nhưng mình không hiểu. Thay vì dùng fflush(stdin) như vầy:
    C Code:
    1. scanf("%d", &m); fflush(stdin);
    Thì người ta dùng thế này:
    C Code:
    1. scanf("%d%*c", &m);
    Không hiểu %*c ở đây có nghĩa là gì, tại sao thêm vào thì không bị trôi hàm?
    /* The thing that I think is the thing that I do. */

  4. #4
    Ngày gia nhập
    02 2008
    Nơi ở
    Việt Nam
    Bài viết
    577

    scanf("%d%*c", &m);
    Cái * có lần đọc ở một bài bạn nào đó hỏi trên diễn đàn, %c hiểu thông thường thôi là nhập kí tự char, và trong Th này kí tự đó là '\n' còn * thêm vào để bỏ qua kí tự khác kiểu lấy đúng kiểu char
    VD:
    Code:
    #include <stdio.h>
    
    int main()
    {
         int n=9;
         float x=4.5,y=6.7;
         printf("%f  %*f\n",y,n,x);
    }
    Kết quả:
    Code:
    6.700000
    4.500000
    Bỏ qua n vì nó không phải float

  5. #5
    Ngày gia nhập
    02 2008
    Nơi ở
    AYS 107
    Bài viết
    41

    Đây đúng là lỗi do kí tự \n vẫn được lưu trong bộ đệm gây ra sai lệch cho quá trình nhập liệu. Trong LINUX, ta có thể xóa bộ đệm rất đơn giản bằng câu lệnh:
    Code:
    while(getchar()!=\n);
    Còn trong WINDOWS hay DOS dùng hàm fflush(stdin) như bạn 6220119 nói, còn có dùng được câu lệnh kia ko mình cũng chưa thử
    I don't wanna waste another day

Các đề tài tương tự

  1. Bài tập về cấu trúc trong c | Cấu trúc sinh viên???
    Gửi bởi dddzzzjjjiii trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 14
    Bài viết cuối: 21-07-2012, 05:06 PM
  2. Biểu thức Regex chạy trong Expresso thì đúng nhưng chạy trong visual studio lại sai
    Gửi bởi rossoneri trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 0
    Bài viết cuối: 30-06-2012, 02:58 PM
  3. Trả lời: 12
    Bài viết cuối: 21-05-2012, 09:13 PM
  4. Chương trình cấu trúc dữ liệu cây cài đặt bằng con trỏ chạy không đúng?
    Gửi bởi naknah trong diễn đàn Thảo luận, góp ý code C/C++ của bạn
    Trả lời: 2
    Bài viết cuối: 23-12-2011, 12:08 PM
  5. Lập trình C Lỗi trong khi nhập mảng cấu trúc có họ tên sinh viên trong lập trình C?
    Gửi bởi trieuvan.n01 trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 8
    Bài viết cuối: 03-01-2011, 09:51 AM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn