2016-07-23 8 views
-3

私はCプログラミング言語の初心者です。私はCプログラミング言語のヌル文字('\0')について非常に混乱しています。Cの文字配列?

以下のプログラムに基づいて、行の文字長は10MAXLINE10)です。長さ9のNavindrenのような入力は、配列インデックス08を占有します。新しい行文字に達すると、それはインデックス9に追加され、iは、1だけインクリメントされます。 iは今度はであり、と割り当てられているのは'\0'で、s[10]です。

ここでは混乱していますが、配列はインデックスから割り当てられた領域だけであるため、どうすれば可能ですか0 - 9?私は多くのオンラインリソースを参照しようとしましたが、説明だけでは十分ではありません。

主な機能:

#include<stdio.h> 
#define MAXLINE 10 

int getline(char line[], int maxline); 
void copy(char to[], char from[]); 

main() { 
    int len;    /*current line length*/ 
    int max;    /*maximum length seen so far*/ 
    char line[MAXLINE];  /*current input line*/ 
    char longest[MAXLINE]; /*longest line saved here*/ 

    max = 0; 
    while ((len = getline(line, MAXLINE)) > 0) { 
     printf("%d\n", len); 
     if (len > max) { 
      max = len; 
      copy(longest, line); 
     } 
    } 

    if (max > 0) /* there was a line */ { 
     printf("%s", longest); 
    } else { 
     printf("No Lines Detected\n"); 
    } 

    return 0; 
} 

getline関数:

int getline(char s[], int lim) { 
    int c; 
    int i; 

    for (i = 0; i < MAXLINE - 1 && (c = getchar()) != EOF && c != '\n'; i++) { 
      s[i] = c; 
    } 

    if (c == '\n') { 
     s[i] = '\n'; 
     ++i; 
    } 

    s[i] = '\0'; 
    return i; 
} 

コピー機能:i9とき、または次のバイトからの読み取りに達したときに

/*copy: copy `from` into `to`; assume to is big enough*/ 
void copy(char to[], char from[]) { 
    int i; 
    i = 0; 

    while ((to[i] = from[i]) != '\0') { 
     ++i; 
    } 
} 
+4

'lines [10]'である '[10]'は、範囲外であるためアクセスされてはいけません(読み書きされません)。それにアクセスすると*未定義の動作*が呼び出されます。 – MikeCAT

+0

Cコンパイラが索引が範囲外であるかどうかを確認するためのコードを生成するのが面倒であるため、 "これはどうですか" *未定義の動作*が呼び出されたときに何かが起きる可能性があります。 – MikeCAT

+0

これはエラーを表示しないことを意味しますか? – naveenath

答えて

2

getline関数はどちらか停止しますファイルは'\n'です。ループの最後に両方の条件を設定することはできないため、i9未満の場合にのみ'\n'が追加されるため、無効な位置s[10]は決して格納されません。

のは、入力ファイルにバイトが含まれていると仮定しましょう。ここでは

+---+---+---+---+---+---+---+---+---+---+ 
| N | a | v | i | n | d | r | e | n |\n | 
+---+---+---+---+---+---+---+---+---+---+ 

getline()によって実行される手順は次のとおりです。

  • i = 0(一度実行ループ初期化文)
  • i < 9 - >真
  • c = getchar() - >cは>真
  • c != '\n' - - >真
  • s[i] = cから
  • c != EOF>is[8]'n'を受信するまでループ上記の手順を繰り返す今1

ある - >s[0]'N'

  • i++が受信しますi9にインクリメントされます。

    最終的な手順は次のとおりです

    • i < 9 - > falseの場合、ループが終了します。
    • if (c == '\n') - > false、'n'で、'\n'ではなく、改行が読み取られていません。 ifブランチはスキップされます。
    • s[i] = '\n' - >s[9]はヌルバイト'\0'を受け取ります。
    • return i; - >値9が呼び出し側に返されます。

    getline()の実装に問題は確かにあります:あなたは、コピー先の配列のサイズの引数を渡すが、コードではなく、ハードコードされた値MAXLINEを使用しています。

    この問題以外の動作は、fgets()の動作と非常によく似ています。あなたはこれをこのように意図したのでしょうか、または後に改行を入れずに行を読むつもりでしたか?古い安全でない関数gets()は以前から何をしていましたか?

  • +0

    私はあなたが質問を誤解したと思っています。例えば、入力が文字列 "Navindren"のときに何が起こるのでしょうか?この入力を使ってコードをデバッグして、あなたが見ていることを明確に教えてください。 – naveenath

    +0

    この回答はすでにヒントを与えています。「コードをデバッグする」部分はあなた自身の仕事です – artm