2012-01-27 15 views
0

私はC言語ではあまりよくありませんが、大文字と小文字を区別しないファイルを読み込むGLUTアプリケーションを設計しています。簡単にするために、私は文字列をすべて小文字に変換したいと思っています。私は、参照によって渡された変数を変更しているmakeLower関数を作成しました。小文字の問題に未知の長さ文字列をカバーする

whileループの最初の繰り返しの一部を取得してEXEがクラッシュするようなmakeLowメソッドにWhileループがあります。すべてのヒントは素晴らしいだろう、ありがとう!

出力:

C:\Users\Mark\Documents\Visual Studio 2010\Projects\Project 1\Debug>"Project 1.e 
xe" ez.txt 

Line is #draw a diamond ring 

Character is # 

その後エラー "プロジェクト1.EXEは動作を停止しました"

コード:

void makeLower(char *input[]){ 
    int i = 0; 
    printf("Line is %s\n", *input); 

    while(input[i] != "\0"){ 
     printf("Character is %c\n", *input[i]); 
     if(*input[i] >= 'A' && *input[i] <= 'Z'){ 
      *input[i] = tolower(*input[i]); 
     } 
     i++; 
    } 

} 

int main(int argc, char *argv[]) { 
    FILE *file = fopen(argv[1], "r"); 
    char linebyline [50], *lineStr = linebyline; 
    char test; 

    glutInit(&argc, argv); 

    while(!feof(file) && file != NULL){ 
     fgets(lineStr , 100, file); 
     makeLower(&lineStr); 
     printf("%s",lineStr); 

     //directFile(); 

    } 
    fclose(file); 


    glutMainLoop(); 
} 
+0

デバッガで実行してみましたか?それ以外にも、私はあなたにヒントを与えることができます:例えば、 '* input [i]'のようなポインタ間接演算子( '*')が何であるか知っていますか?私はそれらをすべて見てみることをお勧めします。 :) –

+0

変数を尊重しないのですか?それは参照によって関数に渡されて以来?私はCのtbhとあまりよくはありません。 – meriley

+1

文字列( 'char'へのポインタ)があれば' string [i] 'を使って1文字を得ることができます。ここで' i'は0から文字列の長さ-1を引いた数字です。文字列+ i) '。後者は、実際にはコンパイラが 'string [i]'を ''に変換するものです。 –

答えて

3

に役立ちます願っています:

あなたは50文字の配列を割り当てますが、100文字まで取得するにはfgetsを伝え、 fgetsが文字列にないメモリを上書きするため、致命的な可能性があります。

C文字列を関数に渡すときに、ポインタのアドレスを文字列(&lineStr)に渡す必要はなく、実際のポインタまたは配列は大丈夫です。つまり、makeLowerの機能をvoid makeLower(char *input)またはvoid makeLower(char input[])に変更することができます。現在、makeLowerへの引数は、charの配列へのポインタではなく、配列またはcharポインタとして宣言されています。

*(input + i)(私は、上記の提案あなたは配列( input[i])として、またはポインタのいずれかとして、単一の文字にアクセスすることができますオフセットを加えた。私は私のコメントで言ったように、最後のバージョンは、コンパイラは、おそらく作成するものです新しい makeLower

。あなたが最初に使用しますが、最初は読みやすくている場合ので、私はそれを示唆

またmakeLowerには、文字列ではなく文字で"\0"との比較を、作るこれは右、実際にはほとんどです:。。あなたはinput[i] != '\0'を使用する必要があります

最後にこれを実装する方法は次のとおりです。

void makeLower(char *input) 
{ 
    while (*input != '\0') /* "while (*input)" would also work */ 
    { 
     *input = tolower(*input); 
     input++; 
    } 
} 

機能に関するいくつかの説明:

  • すべてチャーアレイは、他の方法の周りチャーポインタに変換され、なくすることができます。文字列を受け入れるすべての標準関数(strlenまたはstrcpyなど)からわかるように、文字ポインタを渡す最も一般的な方法は、文字ポインタを渡すことです。)
  • *input逆参照(つまり、ポインタが指すものの値をとる)文字列。これは*(input + 0)と同じで、文字列の最初の文字の値を取得します。
  • 文字列の最初の文字が'\0'(技術的には通常のゼロ)ではありませんが、ループします。
  • 文字列の最初の文字を取得し、tolower関数に渡します。文字が何であってもこれは動作しますが、tolowerは大文字のみを小文字に変換し、それ以外の文字はすべてそのまま返します。
  • tolowerの結果が最初の文字にコピーされました。これは、代入の前に代入の右辺を実行する必要があるため、エラーや問題は発生しません。
  • 最後にポインタを1つ増やします。これにより、inputは文字列の次の文字を指します。これは、inputがローカル変数であるため、ポインタの操作は、呼び出し元の関数には何も影響しません。

この関数は次のように呼び出すことができます。

char input[100]; 
fgets(input, sizeof(input), stdin); 
printf("before: \"%s\"\n", input); 
makeLower(input); 
printf("after : \"%s\"\n", input); 
+0

参考になると、Cでかなりひどいです。あなたの記事は私の問題を解決し、啓発されました!その説明で私は病気が参照渡しで問題を抱えているとは思わない。特に文字列の場合。ありがとうございました。 – meriley

0

私はこの問題は、あなたがそれを知らないということだと思いますあなたが望むとき、文字列は '\ 0'に等しくなります。だからあなたは、文字列の長さを知らない可能性が高い範囲外に出ている可能性があります。

+0

最初のイタレーションは仕上げさえしていないものです。文字は# で、行の最初の文字のみです。次の出力に 'Character is d'と表示されます。 – meriley

+0

次に、私がC++で知っているので、Joachimが正しいと思うのは、配列演算子表記を使って自動的にポインタを逆参照します。 – emschorsch

1

あなたはあなたのものではなく(* input [i]!= "\ 0")してみましたか?なんらかの理由で、あなたの関数にchar(* input [])へのポインタと& lineStrを渡すように見えるので、文字列ターミネータ文字 "\ 0"をチェックするときに2回間参照を解除すると意味があります....

だけで考えたのは、私が今、多くの問題を参照してくださいので、私は答えに私のコメントを延ばすことが

0

を私の知る限りの事を理解し、それは「\ 0」tolower()に渡す罰金です。有効なunsigned charの値です。tolower()は、変換を実行できない場合は入力文字を返します。これはtolower()への1つの以上の呼び出しを行いますが、それは短いですし、(IMO)かなり明確

while(input[i] = tolower(input[i])) 
    ++i; 

:として

したがって、ループが簡潔に置くことができます。代わりにそれを言いたかっただけです。

関連する問題