Cプログラマへの道 #3 - 文字列

Last Edited: 7/22/2024

このブログ記事では、C言語における文字列の扱いを紹介します。

C String

C言語では、文字列は他の高級言語とは少し異なる方法で扱われます。このため、この記事ではC言語における文字列の仕組みを理解することに焦点を当てます。

文字列用の関数

C言語では、文字列は単なる文字(char)の配列ですが、広く使用されているため、文字列を扱うための様々な定義済み関数があります。 以下は便利な定義済み関数のいくつかの例です。

// 文字列用の定義済み関数を含むパッケージ
#include <string.h>
 
char firstName[] = "TK";
char lastName[] = "Blog";
 
// 文字列を小文字または大文字に変換
strlwr(lastName); // 小文字に変換 (blog)
strupr(lastName); // 大文字に変換 (BLOG)
 
// 二つの文字列を連結
strcat(firstName, lastName); // lastNameをfirstNameの末尾に連結 (TKBlog)
strncat(firstName, lastName, 1); // lastNameのn文字をfirstNameの末尾に連結 (TKB)
 
// 文字列を別の文字列にコピー
strcpy(firstName, lastName); // lastNameをfirstNameにコピー (firstName = Blog)
strncpy(firstName, lastName, 2); // lastNameのn文字をfirstNameにコピー (firstName = Bl)
 
// 文字列の内容を設定
strset(firstName, '?'); // firstNameの全文字を?に設定 (firstName = ??)
strnset(firstName, '?', 1); // firstNameの最初のn文字を?に設定 (firstName = ?K)
 
// 文字列を逆にする
strrev(lastName); // lastNameを逆にする (lastName = "gloB")
 
// 文字列の長さを取得
int l = strlen(lastName); // 文字列の長さをint型で返す (l = 4)
 
// 文字列の比較
int res = strcmp(firstName, lastName); // 文字列の全文字を比較 (同じなら0, 違うなら他の数字)
int res = strncmp(firstName, lastName, 2); // 文字列のn文字を比較 (同じなら0, 違うなら他の数字)
int res = strcmpi(firstName, lastName); // 大文字と小文字を無視して文字列の全文字を比較 (同じなら0, 違うなら他の数字)
int res = strnicmp(firstName, lastName, 2); // 大文字と小文字を無視して文字列のn文字を比較 (同じなら0, 違うなら他の数字)

他にも多くの定義済み関数がありますが、それらを完全に理解するためにはポインタの概念を学ぶ必要があるため、ここでは割愛します。

注意: 環境によっては、strlwrstruprstrcmpiなどの関数が使えない場合があります。これらは標準Cライブラリのstring.hに それらの関数が含まれていないためです。

2次元配列

配列の配列、つまり2次元配列を定義する場合は、次のようにします。

int matrix[2][3] = {{1,2,3},{4,5,6}};

配列の値を次のように変更し、表示することができます。

matrix[0][1] = 7; // 0行1列の値を7に設定
 
// sizeofを使って行数と列数を計算
int rows = sizeof(matrix) / sizeof(matrix[0]);
int cols = sizeof(matrix[0]) / sizeof(matrix[0][0]);
 
// ネストされたループで行列を表示
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        printf("%d ", matrix[i][j]);
    }
    printf("\n");
}
// => 1 7 3
//    4 5 6

文字列の配列

この記事は文字列についてのものなのに、なぜ2次元配列について話したのでしょうか?それは、文字列の配列が文字の2次元配列だからです。

char names[][10] = {"Drake", "Kendrick", "J Cole"};

通常の2次元配列と同じように、文字列の文字を変更できます。

names[0][1] = 'a'; // => 0番目の文字列の1番目の文字をaに設定 (Drake -> Daake)

ただし、配列全体の文字列を=で変更することはできません。その場合はstrcpy関数を使用する必要があります。 また、文字列の配列を表示するためにネストされたforループは必要ありません。

strcpy(names[0], "Adonis"); // 0番目の文字列を"Adonis"に設定 (Drake -> Adonis)
 
for (int i = 0; i < sizeof(names)/sizeof(names[0]); i++) {
    printf("%s\n", names[i]);
}
// => Adonis
//    Kendrick
//    J Cole

交換

二つの変数の値を交換したい場合、最初に変数の一つの値を一時的に保存するための新しい変数tempを設定する必要があります。

int x = 5;
int y = 4;
int temp;
 
temp = x; // x=5, y=4, temp=5
x = y; // x=4, y=4, temp=5
y = temp; // x=4, y=5, temp=5

しかし、文字列の配列の例で見たように、新しい文字列を代入するために=を使用することはできません。 文字列を交換する場合、strcpy関数を使用する必要があります。

char x[] = "TK";
char y[] = "Blog";
char temp[15];
 
strcpy(temp, x); // x=TK, y=Blog, temp=TK
strcpy(x, y); // x=Blog, y=Blog, temp=TK
strcpy(y, temp); // x=Blog, y=TK, temp=TK

ただし、strcpy関数を使用する際には、第二引数の文字列が短い場合、予期しない動作が発生する可能性があるため注意が必要です。 これを防ぐために、xyのサイズをchar x[15] = "TK"; char y[15] = "Blog"のように同じにすると良いでしょう。

クイズ

この記事では、学習した内容を確認するためのクイズを設けます。記事のメイン部分を読んだ後に、ぜひ自分で問題を解いてみることを強くお勧めします。各問題をクリックすると答えが表示されます。

リソース