2010-06-24 22 views
7

Tôi bối rối bởi sự khác biệt trong hành vi sau đây:fscanf/fscanf_s sự khác biệt trong hành vi

// suppose myfile.txt contains a single line with the single character 's' 
    errno_t res; 
    FILE* fp; 
    char cmd[81]; 

    res = fopen_s(&fp, "D:\\myfile.txt", "rb"); 
    fscanf(fp,"%80s",cmd); // cmd now contains 's/0' 
    fclose(fp); 

    res = fopen_s(&fp, "D:\\myfile.txt", "rb"); 
    fscanf_s(fp,"%80s",cmd); // cmd now contains '/0' ! 
    fclose(fp); 

Kết quả không phụ thuộc vào thứ tự của cuộc gọi (ví dụ, gọi fscanf_s đầu tiên, bạn sẽ nhận được sự trống rỗng chuỗi đầu tiên). Biên soạn trên VC++ - VS2005. Bất cứ ai có thể sao chép? Bất cứ ai có thể giải thích?

Cảm ơn!

Trả lời

8

Từ các tài liệu trên fscanf_s(), http://msdn.microsoft.com/en-us/library/6ybhk9kc.aspx:

Sự khác biệt chính giữa các chức năng an toàn (với hậu tố _s) và các chức năng cũ là các chức năng an toàn yêu cầu kích thước của mỗi c, C, s, S và [trường loại sẽ được chuyển thành đối số ngay sau biến đó. Để biết thêm thông tin, xem scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l và scanf Chiều rộng Đặc điểm kỹ thuật.

http://msdn.microsoft.com/en-us/library/w40768et.aspx:

Không giống như scanf và wscanf, scanf_s và wscanf_s yêu cầu kích thước bộ đệm được xác định cho tất cả các thông số đầu vào của loại c, C, s, S, hoặc [. Kích thước bộ đệm được chuyển như một tham số bổ sung ngay sau con trỏ tới bộ đệm hoặc biến. Ví dụ: nếu đọc chuỗi, kích thước bộ đệm cho chuỗi đó được chuyển như sau:

char s [10];

scanf ("% 9s", s, 10);

Vì vậy, bạn nên gọi nó như vậy:

fscanf_s(fp,"%80s",cmd, sizeof(cmd)); 
6

fscanf_s (và cả gia đình scanf_s) đòi hỏi bạn phải vượt qua các kích thước của bất kỳ %c, %C, %s, %S, hoặc %[ sau khi bộ đệm riêng của mình; bạn đang bỏ qua rằng lý lẽ:

fscanf_s(fp, "%80s", cmd, 81); 
+3

Điều này có vẻ giống như cách sử dụng sai. '81' được cho là kích thước của bộ đệm' cmd'. Nhưng nó là? Đây là cách tốt để viết mã bị treo, ngay cả khi sử dụng chức năng "an toàn". Nên có 'sizeof (cmd)' trong trường hợp đọc vào một mảng ký tự tĩnh, một số biến lưu trữ độ dài bộ đệm được cấp phát, hoặc một cuộc gọi đến chức năng kích thước/dung lượng của một bộ đệm đã cho. Mặc dù ví dụ của bạn về mặt kỹ thuật chính xác nhưng nó có thể gây hiểu lầm cho nhiều người. –

2

Câu hỏi của bạn được gắn thẻ C++ và bạn đang biên soạn trong VC++, nhưng sử dụng fscanf? Nhận một std :: ifstream.

std::string buffer; 
std::ifstream fp("my filepath"); 
fp >> buffer;