2016-10-29 6 views
2

私はargvから指定したファイル内にある行や文字の数を数えようとしています。しかし、私は何らかの理由でwhileループにぶつかったときにセグメント化エラーが発生します。プログラムはwhileループなしでうまく動作しますが、一回しか流れません。私のwhileループのセグメンテーションフォールト

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) { 

    if(argc != 2) { 
      return 0; 
    } 


    FILE *fp; 
    char c; 
    int lines = 0; 
    int chs = 0; 
    fp = fopen(argv[1], "r"); 

    //Segmentation Fault happens here on the while loop 
    while((c = fgetc(fp)) != EOF) { 
      if(c == '\n') { 
        lines += 1; 
      } 
      else { 
        chs += 1; 
      } 

    } 

    printf("Charaters: %d\n", chs); 
    printf("lines: %d\n", lines); 


    if(fp){ 
      fclose(fp); 
    } 
    return 0; 
} 
+3

あなたはチェックしていません。 'NULL'ポインタを' fgetc() 'に渡すと、未定義の動作が起こります。 – Peter

+1

'fgetc'は意図的に' int'を返します。 – Olaf

+0

問題は、私がnullファイルを開いていたことでした。だから私はそれが最初にnullであったかどうかを調べたはずです。 – Sharpbombs

答えて

2
  • あなたのコードはより密接に慣用的なCに従うことが必要です。
  • fpを既に使用しようとした後ではなく、すぐにfopenを検証する必要があります。
  • fgetcintで、charではありません。これは、ストリームのステータスに関するサイドチャネル情報(つまり、EOF)を返す必要があるためです。この情報はcharで表すことはできませんが、EOFでない場合は、の値をcharに安全にキャストできます。
  • \r\nが改行(単なる孤独なものではなく)を表すのが普通の場合、コードでは\rを通常の文字として扱います。異なる文字クラスをどのように扱うかを検討するとよいでしょう。
  • あなたのプログラムでは、単純なエンコーディングは処理されません。つまり、システムのネイティブエンコーディング(ASCIIの場合もある)のファイルのみが正しく処理されます。たとえば、プログラムはUTF-8のサロゲートペアを1ではなく2つの文字として扱い、UTF-16ファイルを間違ってカウントします。たとえば、ファイルから個々の文字を正しく読み取るには、Unicodeライブラリを使用する必要があります。

ベター: `はfopen()`ループに入る前に(! `FP = NULL`を)成功した​​場合

FILE* fp = fopen(argv[1], "r"); 
if(!fp) { 
    printf("Could not open file \"%s\" for reading.\r\n", argv[1]); 
    return 1; 
} 

int lines = 0; 
int chars = 0; 

int nc; 
while((nc = fgetc(fp)) != EOF) { 

    char c = (char)nc; 

    if  (c == '\n') lines++; 
    else if(c != '\r') chars++; 
} 

printf("Characters: %d\r\nLines: %d\r\n", chars, lines); 

fclose(fp); 

return 0;