C   文字列

ホーム   C/C++チュートリアル


char の配列

C の文字列は char という文字を一個だけ格納する型の配列になっています。

char_ary.c


#include <stdio.h>

int main()
{
    char hello[ ] = {'H', 'e', 'l', 'l', 'o'};
    char world[6] = {'w', 'o', 'r', 'l', 'd'};
    char again[6] = {'a', 'g', 'a', 'i', 'n', 0};
    char excla[2] = {'!'};  // [2]以上なら[10]などでも良い
    
    printf
    ("-------------------------------------------------------\n");
    
    printf("%s " , hello);
    printf("%s " , world);
    printf("%s"  , again);
    printf("%s\n", excla);
        
    char hello5[5] = {'H', 'e', 'l', 'l', 'o'};
    char world5[5] = {'w', 'o', 'r', 'l', 'd'};
    char again5[5] = {'a', 'g', 'a', 'i', 'n'};
    char excla1[1] = {'!'};
    
    printf("%s " , hello5);
    printf("%sn" , world5);
    printf("%s"  , again5);
    printf("%s\n", excla1);
        
    char str[] = "Hello world again!";
    printf("%s\n", str);
    
    printf
    ("-------------------------------------------------------\n");
    
    return 0;
}
    

実行結果


-------------------------------------------------------
Hello world again!
Hello! worldHello!nagainworldHello!!againworldHello!
Hello world again!
-------------------------------------------------------
    

コード説明

  1. char hello[ ]
    配列の定義と同時に初期化もする場合は、配列の要素数の指定を省略できます。
  2. {'H', 'e', 'l', 'l', 'o'};
    配列全体に値を代入する場合は、{ と } の間に個々の要素をカンマ , で区切って記述します。
  3. 'H'
    一文字は ' と ' で囲んで表します。
  4. char world[6]
    配列の要素数を指定して定義する場合は、[ と ] の間に配列の要素数を指定します。
    指定した要素数が、実際の要素数よりも小さかった場合は、 はみ出した要素は代入されません。
    指定した要素数が、実際の要素数よりも大きかった場合は、 余った部分が、空白のままメモリーに残ります。
    ここでは、world配列の要素数は 6 ですが、代入する値は 5 文字です。
    文字列は、最後に '\0'(ヌル) という特殊な文字を付け加えることによって、 そこで文字列が終了していると判断します。そのために '\0' が入るスペースが必要です。
    要素数を指定せずに同時に初期化を行った場合は、自動的に '\0' の入るスペースも確保 されています。
  5. char hello5[5]
    hello5以降の配列は、文字の個数しか要素を確保していません。そのために 文字列の終了位置がわからず、実行結果では変な文字列を表示しています。
  6. char str[] = "Hello world again!";
    char配列の値は、" " と囲むことでも作れるようになっています。
    このようにプログラミング言語によって簡単な記述方法が用意されているものを 「糖衣構文(Syntax sugar)」と言います。
    なお、この配列に付けた str という名前は、 文字列(Strig)の変数名として良く使われます。
  7. 同じように、このソースコードの名前 char_ary.c の ary は、配列(Array) を表す名前(識別子)として良く使われます。


char のポインター

char_ptr.c


#include <stdio.h>

int main()
{
    char *hello = "Hello world again!";
    printf("%s\n", hello);
    
    char *again[] = {"Hello ", "world ", "again!"};
    printf("%s\n", *again);
    
    for (int i = 0; i < 3; i++)
    {
        printf("%s", again[i]);
    }
    printf("\n");
    
    char world[][50] = {"Hello ", "world ", "again!"};
    printf("%s\n", *world);
    
    for (int i = 0; i < 3; i++)
    {
        printf("%s", world[i]);
    }
    printf("\n");
    
    return 0;
}
    

実行結果


Hello world again!
Hello 
Hello world again!
Hello 
Hello world again!
    

コード説明

  1. char *hello = "Hello world!";
    本来ポインターは、まず変数を定義して、 その変数のアドレスをポインターに格納します。 しかし、char のポインターに限っては、文字列を自動的にメモリーに格納して、
    そのアドレスをポインターに代入するということを自動的にやります。
  2. printf("%s\n", hello);
    またchar ポインターの値は、文字列が格納されたアドレスではなく、文字列そのものの 値になります。
  3. char *again[] = {"Hello ", "world ", "again!"};
    このコードが、文字列を char のポインターに格納する有利な点を表しています。
    文字の配列(文字列)の配列を作ろうとした場合 char* がすでに文字列なので、 char *again[] とすれば、文字列の配列が作れます。
    これに対して、char ポインターを使わない場合は、 char world[ ][50] = {"Hello ", "world ", "again!"}; と記述しなければなりません。
    つまり char world[ ][50] と個々の文字列のサイズを指定しなければなりません。 この場合、無駄なメモリーを使う可能性もありますし、 逆にサイズが足りなくなる可能性も出てきます。
  4. printf("%s\n", *again);
    文字列の配列を参照する場合、ポインター型であるかどうかにかかわらず、配列名の前に * (明日クタリスク)を付けなければなりません。ただし、この方法では、 配列の最初の文字列しか参照できません。
  5. printf("%s", again[i]);
    文字列配列の個々の文字列を参照するには、アスタリスクを付けずに 配列名[ 要素番号 ]と記述します。この方法は、配列をポインターにした場合もしなかった場合も同じです。
    このあたりが少し難しいところです。


要素数の取得

strarycount.c


#include <stdio.h>

int main()
{
    char *strary[] = {"Hello", "world", "again!"};
    
    int count      = sizeof strary / sizeof strary[0];
    printf("%d\n", count);
    
    for (int i = 0; i < count; i++)
    {
        printf("%s\n", strary[i]);
    }
    
    return 0;
}
    

実行結果


3
Hello
world
again!
    


文字列を数値に変換する

atoi.c


#include <stdio.h>
#include <stdlib.h>         // for atoi

int main()
{
    char *str = "123";
    
    printf("%d\n", *str);   // 49  と表示される
    printf("%d\n", '1');    // 49  と表示される
    
    int num = atoi(str);    // 文字"123"を整数123に変換
    
    printf("%d\n", num);    // 123 と表示される
    
    printf("Enter number: ");
    scanf("%d", &num);
    printf(" You entered: %d\n", num);
    
    return 0;
}
    

実行結果


49
49
123
Enter number: 2005
 You entered: 2005
    

コード説明

  1. printf("%d\n", *str);
    文字列(文字配列)の最初の要素 '1'の文字コードが表示されます。
  2. printf("%d\n", '1');
    実際に '1' という文字の文字コードは 49 です。
  3. int num = atoi(str);
    atoi( )関数で、引数の文字列を整数に変換できます。atoi( )関数を使うためには、 stdlib.h をインクルードしておく必要があります。
    整数値に変換できない文字列の場合は 0 になります。 "2.5" などの少数(浮動小数点数) は整数部分のみを取り出し 2 になります。
  4. scanf("%d", &num);
    scanf( )関数はキーボードから入力された文字列を
    1. 第1引数で指定した %d などの変換指定子で指定したデータ型に変換し
    2. 第2引数で指定した ポインターの指し示すアドレスに上書きします


数値を文字列に変換する

ntos.h


#include <stdio.h>
//#include <stdlib.h>   // 必要な場合があるかもしれません

int main()
{
    int num = 2005;
    char *str;
    
    int c = snprintf(str, -1, "%d", num);
    puts(str);
    printf("%d\n", c);
    
    float f = 10.5;
    c = snprintf(str, -1, "%f", f);
    puts(str);
    printf("%d\n", c);
    
    return 0;
}
    

実行結果


2005
4
10.500000
9
    

コード説明

  1. #include <stdlib.h>
    stdlib.h は、おそらく不要だと思いますが、 もしかすると必要な場合もあるかもしれません。
  2. int c = snprintf(str, -1, "%d", num);
    snprintf( )関数で数値を文字列に変換します。引数は次のとおりです
    1. 第1引数に返還された文字列を格納する char * 型の変数を指定します
    2. 第2引数に変換する文字数を指定します。-1 にすると制限なしになるみたいです
    3. 第3引数に変換指定子を指定します。 整数に変換する場合は %d を、少数に変換する場合は %f を指定します
    4. 第4引数に変換する数値を指定します。変数でも実際の値を直接記述しても構いません
    5. 戻り値として変換した文字数を返すそうですが、 実際には元の数値の文字数をそのまま返すみたいです
  3. puts(str);
    puts( )関数は、引数に指定した文字列をターミナルに出力して改行します。 printfのように数値を出力することはできませんが、シンプルです。
    puts の 反対として gets( )関数もあります。 get( )関数はターミナルに入力した文字列を引数で指定した文字列変数に代入します。
  4. なお、GTK では、文字列を数値に変換する場合は、atoi を使い、 数値を文字列に変換する場合は、g_strdup_printf( )という関数を使います。


文字列の比較

strcmp


#include <stdio.h>
#include <string.h> // for strcmp

int main ()
{
    char *str1 = "あいうえお";
    char *str2 = "かきくけこ";
    
    printf("%d\n", strcmp(str1, str2));
    
    str1 = "xyz";
    str2 = "abc";
    
    printf("%d\n", strcmp(str1, str2));
    
    str1 = "C言語";
    str2 = "C言語";
    
    printf("%d\n", strcmp(str1, str2));
    
    return 0;
}
    

実行結果


-9
23
0
    

コード説明

  1. printf("%d\n", strcmp(str1, str2));
    strcmp( )関数は、第1引数の文字列と第2引数の文字列を比較して、その大小によって 次の結果を返します。
    1. 第2引数のほうが大きかった場合はマイナスの整数を返します
    2. 第1引数のほうが大きかった場合はプラスの整数を返します
    3. 第1引数と第2引数が同じだっt場合は 0 を返します
  2. なお、大小とは、辞書順の後ろのほうが大きいと判断されます。
  3. GTK でも、strcmp( )関数を使います。


1152 visits
Posted: Dec. 24, 2019
Update: Dec. 24, 2019

ホーム   C/C++チュートリアル   目次