C言語 文字列処理の復習

C言語の文字と文字列を復習してみる

文字

C言語で文字型はchar型というデータ型で1バイトのメモリサイズをもつ。

int main(void) {
    char x;
    x = 'a';
    printf("%c\n", x);
    
    return 0;
}

出力結果
a

プログラム中の'a'は「aという文字」を表すchar型定数。1バイト文字でないと駄目。
日本語は2バイト文字の為char型定数にはならない。

文字列

C言語には文字列型という型はなくchar型の配列で表される。その配列は「文字列の最後に
終端を表す'\0'(ヌル文字)がついている」という約束を守っている必要がある。

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

int main(void) {
    char mojiretu[] = "ABCDEFGHIJ";

    printf("strlen %zd\n", strlen(mojiretu));
    printf("sizeof %ld\n", sizeof(mojiretu));

    return 0;
}

出力結果
strlen 10  ※文字列長は10
sizeof 11 ※文字列サイズは11

終端記号として'\0'が付加されているためサイズは11になる。
⇒ダブルクォーテーションで囲まれた文字列には自動的に\0が付加される

char mojiretu[] = "ABCDEFGHIJ"は
char mojiretu2[11]={"ABCDEFGHIJ"と同じ意味になる。
(char mojiretu[11]={'A','B','C','D','E','F','G','H','I','J','\0'}とも同じ)
配列の宣言時には\0のメモリを確保しないといけないので
最低でも確保する文字数+1の要素数が必要。

文字列をコピーする場合(標準ライブラリ関数を使用しない場合)
配列の中身を一文字ずつコピーして最後に\0を付ければよい

#include <stdio.h>

int main(void) {
    
    char mojiretu[] = "ABCDEFGHIJ";
    char cpmojiretu[11];
    int i;

    printf("mojiretu:%s\n", mojiretu);

    while(mojiretu[i] != '\0') {
        cpmojiretu[i] = mojiretu[i];
        i++;
    }
    cpmojiretu[i] = '\0';
    printf("コピー後の文字列:%s\n", cpmojiretu);

    return 0;
}

文字列処理の標準ライブラリ関数

strcpy 文字列のコピー
終端文字までコピーされる

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

int main(void) {
    
    char mojiretu[] = "ABCDEFGHIJ";
    char cpmojiretu[11];

    printf("mojiretu:%s\n", mojiretu);

    strcpy(cpmojiretu, mojiretu);
    printf("copyされた文字:%s\n", cpmojiretu);

    return 0;
}

出力結果
mojiretu:ABCDEFGHIJ
copyされた文字:ABCDEFGHIJ

strncpy 文字列のコピー(文字数制限あり)

終端文字はコピーされないので自分で付ける必要がある

int main(void) {
    
    char mojiretu[] = "ABCDEFGHIJ";
    char cpmojiretu[6];

    printf("mojiretu:%s\n", mojiretu);

    strncpy(cpmojiretu, mojiretu, 5);
    cpmojiretu[5] = '\0';
    printf("copyされた文字:%s\n", cpmojiretu);

    return 0;
}

strncpyで終端文字を入れなかった場合

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

int main(void) {
    /* コピーする文字列 */
    char mojiretu[] = "Afro-Blue";
    /* コピー先文字列 */
    char cpmojiretu[4];
 
   strncpy(cpmojiretu, mojiretu, sizeof(cpmojiretu));
    printf("%s\n", cpmojiretu);
    printf("mojiretu:  strlen %2zd  sizeof %2ld  %p\n",
           strlen(mojiretu), sizeof(mojiretu), mojiretu);
    printf("cpmojiretu:  strlen %2zd  sizeof %2ld  %p\n",
           strlen(cpmojiretu), sizeof(cpmojiretu), cpmojiretu);

    return 0;
}

出力結果
AfroAfro-Blue
mojiretu: strlen 9 sizeof 10 0x7fff6e813aee
cpmojiretu: strlen 13 sizeof 4 0x7fff6e813aea

cpmojiretuに最大4文字分コピーされるが終端文字がないため、直後の配列mojiretuの
値も表示している。
⇒cpmojiretuが0x7fff6e813aeaにあって4文字分(0x....aedまで)コピーされている
 そのとなり(0x....aee)にmojiretuがあるため、mojiretuの内容まで表示されている

strncpyでコピーした文字列は最後に終端文字(\0)を入れないといけない。

strcmp 文字列の比較

strcmp(A, B)は文字列を比較して等しいときには0、Aが小さいときは負の値、Aが大きいときは正の値を返す。

int main(void) {
    
    char mojiretu[] = "ABCDEFGHIJ";
    char mojiretu2[11]={"ABCDEFGHIJ"};

    cmp = strcmp(mojiretu, mojiretu2);

    if (strcmp(mojiretu, mojiretu2) == 0) {
        printf("Equal\n");
    } else {
        printf("Not Equal\n");
    }
    return 0;
}

出力結果
Equal

strncmp 文字列の比較(文字数制限あり)

これは文字数指定のあるstrcmp。内容は省略。

strchr 文字列中で文字を探しそのポインタを返却

int main(void) {

    int cmp;
    char mojiretu[] = "ABCDEFGHIJ";
    char *p;

    p = strchr(mojiretu, 'F');
    printf("'F'以降の文字:%s\n", p);

    return 0;
}

出力結果
'F'以降の文字:FGHIJ

strstr 文字列中で部分文字列を探しそのポインタを返却

int main(void) {

    int cmp;
    char mojiretu[] = "ABCDEFGHIJ";
    char search[] = "EFG";
    char *p;

    p = strstr(mojiretu, search);
    printf("文字列EFG以降の文字:%s\n", p);
}

出力結果
文字列EFG以降の文字:EFGHIJ