第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么“while(!feof(file))”總是錯的?

為什么“while(!feof(file))”總是錯的?

墨色風雨 2019-05-20 15:47:43
我看到人們最近在很多帖子中試圖讀取這樣的文件。碼#include <stdio.h>#include <stdlib.h>int main(int argc, char **argv){     char * path = argc > 1 ? argv[1] : "input.txt";     FILE * fp = fopen(path, "r");     if( fp == NULL ) {         perror(path);         return EXIT_FAILURE;     }     while( !feof(fp) ) {  /* THIS IS WRONG */         /* Read and process data from file… */     }     if( fclose(fp) == 0 ) {         return EXIT_SUCCESS;     } else {         perror(path);         return EXIT_FAILURE;     }}這個while( !feof(fp))循環(huán)有什么問題?
查看完整描述

5 回答

?
MMMHUHU

TA貢獻1834條經(jīng)驗 獲得超8個贊

我想提供一個抽象的,高層次的觀點。

并發(fā)性和同時性

I / O操作與環(huán)境交互。環(huán)境不是您的計劃的一部分,也不在您的控制之下。環(huán)境真正與您的程序“同時”存在。與所有并發(fā)的事情一樣,關于“當前狀態(tài)”的問題沒有意義:并發(fā)事件中沒有“同時性”的概念。國家的許多屬性根本不同時存在。

讓我更準確地說:假設你想問,“你有更多的數(shù)據(jù)嗎?” 您可以詢問并發(fā)容器或I / O系統(tǒng)。但答案通常是不可行的,因而毫無意義。那么如果容器說“是” - 當你嘗試閱讀時,它可能不再有數(shù)據(jù)。同樣,如果答案為“否”,則在您嘗試閱讀時,數(shù)據(jù)可能已到達。結論是,目前根本沒有像“我有數(shù)據(jù)”這樣的屬性,因為你無法對任何可能的答案做出有意義的回應。(緩沖輸入的情況略好一些,你可以想象得到一個“是的,我有數(shù)據(jù)”構成某種保證,但你仍然必須能夠處理相反的情況。并且輸出情況肯定和我描述的一樣糟糕:你永遠不知道那個磁盤或那個網(wǎng)絡緩沖區(qū)是否已滿。)

因此,我們得出結論,這是不可能的,而事實上未合理的,要問的I / O系統(tǒng)是否能夠執(zhí)行I / O操作。我們可以與它交互的唯一可能方式(就像并發(fā)容器一樣)是嘗試操作并檢查它是成功還是失敗。在您與環(huán)境交互的那一刻,然后才能知道交互是否真的可能,并且此時您必須承諾執(zhí)行交互。(如果你愿意的話,這是一個“同步點”。)

EOF

現(xiàn)在我們到了EOF。EOF是您嘗試的 I / O操作獲得的響應。這意味著您正在嘗試讀取或寫入某些內(nèi)容,但在執(zhí)行此操作時,您無法讀取或寫入任何數(shù)據(jù),而是遇到了輸入或輸出的結尾。對于基本上所有的I / O API都是如此,無論是C標準庫,C ++ iostream還是其他庫。只要I / O操作成功,您就無法知道未來的操作是否會成功。您必須首先嘗試操作然后響應成功或失敗。

例子

在每個示例中,請注意我們首先嘗試I / O操作,然后在結果有效時使用結果。進一步注意,我們總是必須使用I / O操作的結果,盡管結果在每個示例中采用不同的形狀和形式。

  • C stdio,從文件中讀?。?/p>

    for (;;) {
        size_t n = fread(buf, 1, bufsize, infile);
        consume(buf, n);
        if (n < bufsize) { break; }}

    我們必須使用的結果是n,讀取的元素數(shù)量(可能只有零)。

  • C STDIO, scanf

    for (int a, b, c; scanf("%d %d %d", &a, &b, &c) == 3; ) {
        consume(a, b, c);}

    我們必須使用的結果是scanf轉換的元素的返回值。

  • C ++,iostreams格式化提?。?/p>

    for (int n; std::cin >> n; ) {
        consume(n);}

    我們必須使用的結果std::cin本身,可以在布爾上下文中進行評估,并告訴我們流是否仍然處于good()狀態(tài)。

  • C ++,iostreams getline:

    for (std::string line; std::getline(std::cin, line); ) {
        consume(line);}

    我們必須再次使用的結果std::cin,就像以前一樣。

  • POSIX,write(2)刷新緩沖區(qū):

    char const * p = buf;ssize_t n = bufsize;for (ssize_t k = bufsize; (k = write(fd, p, n)) > 0; p += k, n -= k) {}if (n != 0)
  •  { /* error, failed to write complete buffer */ }

    我們在這里使用的結果是k,寫入的字節(jié)數(shù)。這里的要點是我們只能知道寫操作寫入了多少字節(jié)。

  • POSIX getline()

    char *buffer = NULL;size_t bufsiz = 0;ssize_t nbytes;while ((nbytes = getline(&buffer, &bufsiz, fp)) != -1){
        /* Use nbytes of data in buffer */}free(buffer);

    我們必須使用的結果是nbytes,直到并包括換行符的字節(jié)數(shù)(如果文件沒有以換行符結尾,則為EOF)。

    請注意,-1當發(fā)生錯誤或達到EOF時,函數(shù)顯式返回(而不是EOF?。?/p>

您可能會注意到我們很少拼出實際的單詞“EOF”。我們通常以某種其他方式檢測錯誤條件,這對我們來說更加有趣(例如,無法執(zhí)行我們期望的I / O)。在每個示例中都有一些API功能可以明確告訴我們已經(jīng)遇到EOF狀態(tài),但事實上這并不是一個非常有用的信息。它比我們經(jīng)常關心的更詳細。重要的是I / O是否成功,比失敗更重要。

  • 實際查詢EOF狀態(tài)的最后一個示例:假設您有一個字符串并且想要測試它是否完整地表示整數(shù),除了空格之外沒有額外的位。使用C ++ iostream,它是這樣的:

    std::string input = "   123   ";   // examplestd::istringstream iss(input);int value;if (iss >> value >> std::ws && iss.get() == EOF) {
        consume(value);} else {
        // error, "input" is not parsable as an integer}

    我們在這里使用兩個結果。第一個是iss流對象本身,用于檢查格式化的提取是否value成功。但是,在消耗空白之后,我們執(zhí)行另一個I / O /操作,iss.get()并期望它作為EOF失敗,如果整個字符串已經(jīng)被格式化提取消耗,則會出現(xiàn)這種情況。

    在C標準庫中,您可以strto*l通過檢查結束指針是否已到達輸入字符串的末尾來實現(xiàn)與函數(shù)類似的操作。

答案

while(!eof)這是錯誤的,因為它測試的東西是無關緊要的,無法測試你需要知道的東西。結果是您錯誤地執(zhí)行了代碼,該代碼假定它正在訪問已成功讀取的數(shù)據(jù),而事實上這種情況從未發(fā)生過。


查看完整回答
反對 回復 2019-05-20
?
12345678_0001

TA貢獻1802條經(jīng)驗 獲得超5個贊

不,這并不總是錯的。如果您的循環(huán)條件是“我們還沒有嘗試讀取文件末尾”,那么您可以使用while (!feof(f))。然而,這不是一個常見的循環(huán)條件 - 通常你想測試其他東西(例如“我可以閱讀更多”)。while (!feof(f))沒錯,它只是錯了。


查看完整回答
反對 回復 2019-05-20
?
交互式愛情

TA貢獻1712條經(jīng)驗 獲得超3個贊

feof()表示是否曾嘗試讀取文件末尾。這意味著它幾乎沒有預測效果:如果它是真的,你確定下一個輸入操作將失?。悴淮_定前一個輸入操作是否失敗),但如果它是假的,你不確定下一個輸入操作會成功。此外,輸入操作可能由于文件結尾之外的其他原因而失敗(格式化輸入的格式錯誤,純IO故障 - 磁盤故障,網(wǎng)絡超時 - 適用于所有輸入類型),因此即使您可以預測文件的結尾(任何嘗試實現(xiàn)Ada one的人,如果你需要跳過空格,并且它對交互式設備有不良影響,它會告訴你它可能很復雜 - 有時會強迫輸入下一個在開始處理上一個之前的行),

因此,C語中的正確習慣是將IO操作成功循環(huán)作為循環(huán)條件,然后測試失敗的原因。例如:

while (fgets(line, sizeof(line), file)) {
    /* note that fgets don't strip the terminating \n, checking its
       presence allow to handle lines longer that sizeof(line), not showed here */
    ...}if (ferror(file)) {
   /* IO failure */} else if (feof(file)) {
   /* format error (not possible with fgets, but would be with fscanf) or end of file */} else {
   /* format error (not possible with fgets, but would be with fscanf) */}


查看完整回答
反對 回復 2019-05-20
  • 5 回答
  • 0 關注
  • 1461 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號