web-dev-qa-db-ja.com

Cで文字列を反復処理する方法は?

今私はこれを試しています:

#include <stdio.h>

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

    if (argc != 3) {

        printf("Usage: %s %s sourcecode input", argv[0], argv[1]);
    }
    else {
        char source[] = "This is an example.";
        int i;

        for (i = 0; i < sizeof(source); i++) {

            printf("%c", source[i]);
        }
    }

    getchar();

    return 0;
}

これも機能しません:

char *source = "This is an example.";
int i;

for (i = 0; i < strlen(source); i++){

    printf("%c", source[i]);
}

エラーが表示されます

Test.exeの0x5bf714cf(msvcr100d.dll)で未処理の例外:0xC0000005:位置0x00000054で読み取り中のアクセス違反。

(ドイツ語から疎訳)

私のコードの何が問題になっていますか?

48
Vincent

あなたが欲しい:

for (i = 0; i < strlen(source); i++){

sizeofは、文字列ではなく、ポインターのサイズを示します。ただし、ポインターを配列として宣言した場合は機能します。

char source[] = "This is an example.";

しかし、関数に配列を渡すと、それもポインターに減衰します。文字列には、常にstrlenを使用するのが最善です。そして、%cを使用するようにprintfを変更することについて他の人が言ったことに注意してください。また、効率に関するmmyersのコメントを考慮して、呼び出しをstrlenからループ外に移動する方がよいでしょう。

int len = strlen( source );
for (i = 0; i < len; i++){

またはループを書き換えます:

for (i = 0; source[i] != 0; i++){
55
anon

一般的なイディオムは次のとおりです。

_char* c = source;
while (*c) putchar(*c++);
_

いくつかのメモ:

  • Cでは、文字列は null-terminated です。読み取り文字がヌル文字ではない間、繰り返します。
  • _*c++_はcをインクリメントし、cの逆参照old値を返します。
  • printf("%s")は、charではなくnullで終わる文字列を出力します。これがアクセス違反の原因です。
39
Alexandre C.

上記のようにstrlenを使用するのではなく、単にNULL文字を確認できます。

#include <stdio.h>

int main(int argc, char *argv[])
{
    const char *const pszSource = "This is an example.";
    const char *pszChar = pszSource;

    while (pszChar != NULL && *pszChar != '\0')
    {
        printf("%s", *pszChar);
        ++pszChar;
    }

    getchar();

    return 0;
}
3
Mark Ingram

sizeof(source)は、ポインター_char*_に必要なバイト数を返します。これをstrlen(source)に置き換える必要があります。これは、表示しようとしている文字列の長さになります。

また、文字を表示しているので、おそらくprintf("%s",source[i])printf("%c",source[i])に置き換える必要があります。

2
Jacob

これは動作するはずです

 #include <stdio.h>
 #include <string.h>

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

    char *source = "This is an example.";
    int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation
    for (int i = 0; i < length; i++) 
    {

       printf("%c", source[i]);

    }


 }
2
Prasoon Saurav
  1. sizeof()には、終端のヌル文字が含まれます。 strlen()を使用する必要があります(ただし、ループの外側で呼び出しを行い、変数に保存します)が、それがおそらく例外の原因ではありません。
  2. printfでは「%s」ではなく「%c」を使用する必要があります。文字列ではなく文字を印刷しています。
2
KenE
  • sizeof(source)は、文字列の長さではなく、_char*_のサイズを返します。 strlen(source)を使用する必要があり、それをループ外に移動する必要があります。そうしないと、ループごとに文字列のサイズが再計算されます。
  • _%s_形式修飾子を使用して印刷することにより、printfは_char*_を探しますが、実際にはcharを渡します。 _%c_修飾子を使用する必要があります。
1
JSBձոգչ

Strlenでsizeofを変更するだけです。

このような:

char *source = "This is an example.";
int i;

for (i = 0; i < strlen(source); i++){

    printf("%c", source[i]);

}
0

Sizeofをstrlenに置き換えると、動作するはずです。

0
Keith Randall

ANSI文字列を取得するには、最初の文字へのポインターが必要です。

_printf("%s", source + i);
_

仕事をする

さらに、もちろん、strlen(source)ではなくsizeof(source)を意味するはずです。

0
ULysses

sizeof(source)は、ソースがchar *として宣言されているため、ポインターのサイズを返します。正しい使用方法はstrlen(source)です。

次:

printf("%s",source[i]); 

文字列が必要です。つまり、%sは文字列を予期していますが、各文字を出力するためにループで反復しています。したがって、%cを使用します。

ただし、インデックスiを使用して文字列にアクセス(反復)する方法は正しいため、他の問題はありません。

0
Praveen S

C-Stringの最後のインデックスは常に整数値0であるため、「null terminate string」というフレーズが使用されます。整数0はCのブール値falseと同じであるため、これを使用してforループの単純なwhile句を作成できます。最後のインデックスに到達すると、ゼロを見つけてそれをfalseと等しくし、forループを終了します。

for(int i = 0; string[i]; i++) { printf("Char at position %d is %c\n", i, string[i]); }
0
Edwin Jata