2017-09-16 3 views
-1

私はこのコードを書いて、自分のテキストのすべての文字を読み込んでそれを自分のchar配列に入れました。私の問題は、ファイルの末尾が検出されないので、fscanf()は、最後の文字が入力されるたびにテキストの最後の後に戻ります。どうすればそれを防ぐことができますか?私はC.CのtxtファイルのEOFを検出

でマイコードをプログラミングしています:

int main() { 
    char array[50][50]; 
    char buff; 
    FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r"); 

    for (int i = 0; i < 50; i++) { 
     for (int k = 0; k < 50; k++) { 
      fscanf(cola, "%c", &buff); 
      array[i][k] = buff; 
     } 
    } 

    fclose(cola); 

    for (int i = 0; i < 50; i++) { 
     for (int k = 0; k < 50; k++) { 
      printf("%c", array[i][k]); 
     } 
    } 
    return 0; 
} 

はあなたの助けをいただき、ありがとうございます。

Here is a Screenshot of my Code

+3

画像を投稿しないでくださいあなたのコードの。代わりに、実際のコードを含むコードブロックを作成します。 –

+4

'fscanf'の戻り値を確認してください。 – BLUEPIXY

+0

私は今私の投稿を編集しました。 –

答えて

1

置換:

for (int i = 0; i < 50; i++) { 
    for (int k = 0; k < 50; k++) { 
     fscanf(cola, "%c", &buff); 
     array[i][k] = buff; 
    } 
} 

を有する:

for (int i = 0; i < 50; i++) { 
    for (int k = 0; k < 50; k++) { 
     int c = getc(cola); 
     if (c == EOF) 
      break; 
     array[i][k] = c; 
    } 
} 

buffが未使用であるので、それを定義しません。 getc()の返品タイプは、charだけでなく、intであることに注意してください。成功/失敗のためにI/O機能を常にチェックしてください。元のコードでは、I/O操作が成功したかどうかをチェックしなくても、EOFを検出できなくなります。

このコードでは、正当な理由があるかどうかにかかわらず、さまざまな前提があります。たとえば、ファイル内の各行が49文字と改行で構成されているとします。情報を '文字列'として印刷する必要はないと仮定しています(既存のコードは文字ではなく、安全です)。各行がnullであることと、変数arrayに結果を格納し、

50本のまでの49文字でラインプラス各行の改行までを読む
  • :あなたは、入力を記述する場合があります

    終了した文字列。

これは、一般的な問題(短線、長い線、十分な線ではない)よりも弾力性があります。そのためのコードは次のようになります。

enum { LINE_LEN = 50, NUM_LINES = 50 }; 
char array[NUM_LINES][LINE_LEN]; 
int i; 
for (i = 0; i < LINE_LEN; i++) 
{ 
    int c; 
    int k; 
    for (k = 0; k < LINE_LEN; k++) 
    { 
     c = getc(cola); 
     if (c == EOF || c == '\n') 
      break; 
     if (k == LINE_LEN - 1) 
     { 
      /* Too long - gobble excess */ 
      while ((c = getc(cola)) != EOF && c != '\n') 
       ; 
      break; 
     } 
     array[i][k] = c; 
    } 
    array[i][k] = '\0'; 
    if (c == EOF) 
     break; 
} 
int num_lines = i; // You have num_lines lines of data in your array 

私はあなたがあなたのイメージを持っているものに似ているhttps://www.ascii-code.com/ascii-art/logos/coca-cola.phpでコカ・コーラ™ASCIIアート画像の1バージョンを発見したが、他の多くの情報源と亜種があります。

  __        ___ __  .ama  , 
     ,d888a       ,d88888888888ba. ,88"I) d 
    a88']8i       a88".8"8) `"8888:88 " _a8' 
    .d8P' PP      .d8P'.8 d)  "8:88:baad8P' 
    ,d8P' ,ama, .aa, .ama.g ,mmm d8P' 8 .8'  88):888P' 
,d88' d8[ "8..a8"88 ,8I"88[ I88' d88 ]IaI"  d8[   
a88' dP "bm8mP8'(8'.8I 8[  d88' `"   .88   
,88I ]8' .d'.8  88' ,8' I[ ,88P ,ama ,ama, d8[ .ama.g 
[88' I8, .d' ]8, ,88B ,d8 aI (88',88"8) d8[ "8. 88 ,8I"88[ 
]88 `888P' `8888" "88P"8m" I88 88[ 8[ dP "bm8m88[.8I 8[ 
]88,   _,,aaaaaa,_  I88 8" 8 ]P' .d' 88 88' ,8' I[ 
`888a,. ,aadd88888888888bma. )88, ,]I I8, .d')88a8B ,d8 aI 
    "888888PP"'  `8""""""8 "888PP' `888P' `88P"88P"8m" 

このファイルの最も長い行は、最初の67文字に改行を加えたものです。最短は61文字と改行です。このファイルには合計13行と845文字(LF行末)しかありません。したがって、あなたのプログラムは、この特定のデータファイルを処理する能力がありません。それは2,500文字を探し、それらを取得しません。

私の完全なテストコードは、固定ファイル名ではなく、標準入力から読み込むように設定されていました。

#include <stdio.h> 

int main(void) 
{ 
    FILE *cola = stdin; 

    enum { LINE_LEN = 80, NUM_LINES = 50 }; 
    char array[NUM_LINES][LINE_LEN]; 
    int i;  // Need value of i after loop 
    for (i = 0; i < NUM_LINES; i++) 
    { 
     int c; // Need value of c after loop 
     int k; 
     for (k = 0; k < LINE_LEN; k++) 
     { 
      c = getc(cola); 
      if (c == EOF || c == '\n') 
       break; 
      if (k == LINE_LEN - 1) 
      { 
       /* Too long - gobble excess */ 
       while ((c = getc(cola)) != EOF && c != '\n') 
        ; 
       break; 
      } 
      array[i][k] = c; 
     } 
     array[i][k] = '\0'; 
     if (c == EOF) 
      break; 
    } 
    int num_lines = i; // You have num_lines lines of data in your array 

    for (i = 0; i < num_lines; i++) 
     puts(array[i]); 

    return 0; 
} 

最後に空の行が表示され、空白行の後に79文字を超える2行が表示されます。それはすべての特殊なケースを正しく処理しました。ユーザーの入力を処理するのは難しいことに注意してください。間違ったユーザ入力を処理することはより困難です。コードはコンパクトではありません。ルールを変更し、一致するようにコードを変更することができます。私はこれをコード化するための最も簡単な方法であるとは思わない。しかし、それは動作します。内側の入力ループを処理する関数を持つ方が良いかもしれません。外部ループはその関数からの戻り値をテストできます。これは特別なケースの取り扱いを減らすでしょう。

#include <assert.h> 
#include <limits.h> 
#include <stdio.h> 

static int read_line(FILE *fp, size_t buflen, char *buffer) 
{ 
    assert(buflen < INT_MAX); 
    int c;  // Need value of c after loop 
    size_t k; // Need value of k after loop 
    for (k = 0; k < buflen; k++) 
    { 
     if ((c = getc(fp)) == EOF || c == '\n') 
      break; 
     if (k == buflen - 1) 
     { 
      /* Too long - gobble excess */ 
      while ((c = getc(fp)) != EOF && c != '\n') 
       ; 
      break; 
     } 
     buffer[k] = c; 
    } 
    buffer[k] = '\0'; 
    return (k == 0 && c == EOF) ? EOF : (int)k; 
} 

int main(void) 
{ 
    enum { LINE_LEN = 80, NUM_LINES = 50 }; 
    char array[NUM_LINES][LINE_LEN]; 
    int i; 
    for (i = 0; i < NUM_LINES; i++) 
    { 
     if (read_line(stdin, LINE_LEN, array[i]) == EOF) 
      break; 
    } 
    int num_lines = i; 

    for (i = 0; i < num_lines; i++) 
     puts(array[i]); 

    return 0; 
} 

これは、以前のバージョンと同じ入力から同じ出力を生成します。

+0

これは変更だけでは問題が解決されない場合、印刷ループは配列の初期化されていない部分にアクセスし、未定義の動作を呼び出します。 – chqrlie

+0

@chqrlie - あなたはおそらく正しいでしょう。私は見出しの問題(EOFを検出しないこと)についてのみ説明しました。私はコードの残りの部分を見ていませんでした。私は何もコンパイルしていない。私はまた、オーバーフロー防止などの場所に、 –

+0

印象的な努力と良い洞察力を持っていない、誰もが行の長さの問題を逃した。 – chqrlie

-1
int main() { 
//char array[50][50]; 
char buff; 
int t; 
FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r"); 

if (cola == NULL) 
{ 
    printf("Cannot open file \n"); 
    exit(0); 
} 
while (1) { 
    t = fgetc(cola); 
    if (t == EOF) 
     break; 
    buff = t; 
    printf("%c", buff); 
} 


fclose(cola); 

return 0; 
} 
+1

'printf("%c "、buff);'で文字を印刷する前に 'EOF' **をテストする必要があります。さらに、 'fgetc(cola)'を使用してストリームから読み込むと、 'EOF'が正しく検出されるように' int '型の 'buff'を定義しなければなりません。' putchar buff) 'を出力します。 – chqrlie

+0

@chqrlie 'fgetc()'はintを返しますが、戻り値をcharデータ型に格納すると、自動的に戻りASCIIの文字が格納されます。すなわち暗黙のうちに型キャストされる。 – Aashish

+1

テストする前に 'getc()'とその親類の値を 'char'に保存すると、EOFの表示が捨てられます。プレーン 'char'が符号付きの型であれば、有効な文字をEOFとして誤って識別します。署名されていない型であれば、EOFは検出されません。どちらも悪いです。 –

2

fscanf()は成功したコンバージョン数を返します。あなたは、戻り値をテストしても、具体的に改行文字を処理する必要があります

#include <stdio.h> 

int main(void) { 
    char array[50][50]; 
    char buff; 
    FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r"); 

    if (cola == NULL) { 
     return 1; 
    } 
    for (int i = 0; i < 50; i++) { 
     for (int k = 0; k < 50; k++) { 
      if (fscanf(cola, "%c", &buff) != 1 || buff == '\n') { 
       array[i][k] = '\0'; 
       break; 
      } 
      array[i][k] = buff; 
     } 
    } 
    fclose(cola); 

    for (int i = 0; i < 50; i++) { 
     for (int k = 0; k < 50 && array[i][k] != '\0'; k++) { 
      printf("%c", array[i][k]); 
     } 
     printf("\n"); 
    } 
    return 0; 
} 

コードは、ファイルからバイトを読み取るためにgetc()の代わりfscanf()を使用する場合に簡略化することができます。

#include <stdio.h> 

int main(void) { 
    char array[50][51]; 
    int c, i, k, n; 
    FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r"); 

    if (cola == NULL) { 
     return 1; 
    } 
    for (n = 0; n < 50; n++) { 
     for (k = 0; k < 50; k++) { 
      if ((c = getc(cola)) == EOF || c == '\n') { 
       break; 
      } 
      array[n][k] = c; 
     } 
     array[n][k] = '\0'; 
     if (c == EOF && k == 0) 
      break; 
    } 
    fclose(cola); 

    for (i = 0; i < n; i++) { 
     puts(array[i]); 
    } 
    return 0; 
} 
+0

あなたは正しい - 最初はそれを見なかった。 – chux

関連する問題