MMGamesロゴ  MMGames
Twitterシェアボタン  Facebookシェアボタン   
 English 

しんで覚えるC言語
しんで覚えるC言語

文字列処理関数

数値への変換
C言語には、文字列を処理するためのさまざまな関数が用意されています。
それらをうまく使うことで、文字列を自由に処理できます。

atoi関数は、文字列を数値に変換した結果を変数に代入します。
atoi関数の使い方は次の通りです。
なお、atoi関数を使うには、stdlib.h を #include する必要があります。

ソースコード
変数 = atoi(文字列配列名);

次のプログラムは、atoi関数を使って数値を変換する例です。

ソースコード
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char str[] = "145";
    int suuti = atoi(str);
    printf("%d\n", suuti);
    return 0;
}

このプログラムの実行結果は次の通りになります。

実行結果
145

atoi関数では、+-の付いた符号付きの数字も変換できます。
もし、数字とは関係ない文字列が指定された場合は、0に変換されます。
実数に変換する場合には、atof関数を使用します。使い方は同じです。
文字列のコピー
strcpy関数を使うと、文字列のコピーを行うことができます。
strcpy関数の使い方は次の通りです。
なお、strcpy関数を使うには、string.h を #include する必要があります。

ソースコード
strcpy(コピー先文字列配列名, コピー元文字列配列名);

この関数は、文字列配列同士のコピーに使うのが元々の役目なのですが、
実際には、文字列の代入に使われることが多いようです。
次のプログラムは、strcpy関数を使って文字列を代入する例です。

ソースコード
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[10];
    strcpy(str, "MARIO");
    printf("%s\n", str);
    return 0;
}

このプログラムの実行結果は次の通りになります。

実行結果
MARIO

前章の最あとで、1つずつ代入する方法を説明しましたが、こちらのほうが簡単です。

さらに、先頭から指定された文字数だけをコピーするstrncpy関数もあります。
strncpy関数の使い方は次の通りです。

ソースコード
strncpy(コピー先文字列配列名, コピー元文字列配列名, コピーする文字数);

この関数は、文字数の分だけコピーするだけなので、
場合によっては、コピーされた文字列の最後にEOSが入っていないことがあります。
そのまま表示させると延々と表示され続けるので、必ずEOSを付けます。

ソースコード
strncpy(コピー先文字列配列名, コピー元文字列配列名, コピーする文字数);
コピー先文字列配列名[コピーする文字数] = '\0';

次のプログラムは、文字列の先頭から3文字を取り出して表示する例です。

ソースコード
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str1[] = "MARIO", str2[10];
    strncpy(str2, str1, 3);
    str2[3] = '\0'; /* EOSを付加 */
    printf("%s\n", str2);
    return 0;
}

このプログラムの実行結果は次の通りになります。

実行結果
MAR


strncpyは危険
strncpy関数では必ずEOSを付けなくてはなりません。
EOSを忘れてしまうと、無関係の文字がたくさん出てきて、エラーになってしまいます。
十分に気をつけて使用する必要があります。

文字列の連結
文字列リテラルを連結するだけなら関数は必要ありません。
文字列リテラルをただ並べるだけで連結されるからです。
次のプログラムは、文字列リテラルの連結を行う例です。

ソースコード
#include <stdio.h>
int main(void)
{
    char str[] = "DRAGON""QUEST";
    printf("%s\n", str);
    return 0;
}

このプログラムの実行結果は次の通りになります。

実行結果
DRAGONQUEST

DRAGON と QUEST が連結されていることがわかると思います。

ただし、配列に記憶された文字列を連結する場合には、配列名を並べても駄目です。
その場合はstrcat関数を使います。strcat関数の使い方は次の通りです。
なお、strcat関数を使うには、string.h を #include する必要があります。

ソースコード
strcat(元の文字列が記憶された配列, 追加する文字列の記憶された配列);

次のプログラムは、strcat関数を使って文字列を連結する例です。

ソースコード
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str1[12] = "DRAGON";
    char str2[] = "QUEST";
    strcat(str1, str2);
    printf("%s\n", str1);
    return 0;
}

このプログラムの実行結果は次の通りになります。

実行結果
DRAGONQUEST

この関数を使う時に注意してほしいのは、元の文字列が記憶された配列は、
元の文字列+追加する文字列だけの長さが必要になることです。
文字配列の長さが足りない場合、バッファオーバーランエラーの原因となってしまいます。

C言語はバグりやすい
この章に入ってから何度も出てきているように
C言語は、配列の長さを間違って使用すると、あっという間にバグってしまいます。
他のプログラミング言語よりも、バグが起こりやすい言語です。

究極の文字列合成関数
ここで、究極の文字列合成関数を紹介したいと思います。
筆者が調べた限りではほとんどの入門書ではこの関数が紹介されていないのですが、
この関数はあらゆる文字列合成に使用できる万能関数なので是非覚えるべきです。

sprintf関数は、printf関数と同じ機能を持った関数ですが、
sprintf関数の場合、結果を配列の中に記憶します。
printf関数のさまざまな機能を自由に取り扱うことができるのです。

sprintf関数の使い方は次の通りです。
なお、sprintf関数を使うには、stdio.h を #include する必要があります。

ソースコード
sprintf(結果を記憶する配列, 書式文字列, 各種変数・・・);

次のプログラムは、sprintf関数を使う例です。

ソースコード
#include <stdio.h>

int main(void)
{
    char str[16];
    char str1[12] = "DRAGON";
    char str2[] = "QUEST";
    int i = 3;
    sprintf(str, "%s%s%d\n", str1, str2, i);
    printf(str);
    return 0;
}

このプログラムの実行結果は次の通りになります。

実行結果
DRAGONQUEST3

この関数を使えば、ほとんどの文字列合成が実現できます。

直に文字配列
先ほどのプログラムでは文字列の表示に、
printf(str);
と、%s指定子を使用せずに直接文字配列 str を渡しています。
そもそも printf関数は文字列を表示する関数なので、
わざわざ %s指定子を使わなくても表示できるのです。
ただし、文字列中に % が含まれていると、
出力変換指定子と誤解して誤動作するので、その時は %s を用います。

文字列の入力
数値と同様、文字列を入力する場合にもscanf関数を使うことができます。
文字列を入力する場合、scanf関数で%s指定子を指定します。
ただし、配列名の前に&を付けません

&をつけない理由
実は、&をつけないことには非常に重大な理由があります。
配列は、C言語の本質であるポインタそのものであるからです。
これはC言語の根底をなす重要なことであるため、
後々じっくりと時間をとって、たっぷりと説明いたします。

次のプログラムは、入力した文字列をそのまま表示する例です。

ソースコード
#include <stdio.h>

int main(void)
{
    char str[32];
    scanf("%s", str);
    printf("%s\n", str);
    return 0;
}

このプログラムの実行結果は、次の通りになります。

実行結果
MARIO キーボードから入力した文字列
MARIO

これで、自由に文字列を入力できますが、注意点があります。

1つ目は、配列の要素数よりも多く入力すると、エラーの原因となってしまうことです。
第6章で説明した、入力ミスの恐怖と、同様の現象が発生してしまいます。

この問題を解決するには、文字配列の要素数を%とsの間で指定します。
たとえば、要素数が32の場合は%32sと指定すると、それ以上の文字は切り捨てられます。
次のプログラムは、文字列の切り捨ての例です。

ソースコード
#include <stdio.h>

int main(void)
{
    char str[32];
    scanf("%32s", str);
    printf("%s\n", str);
    return 0;
}

このプログラムの実行結果は、次の通りになります。

実行結果
0123456789012345678901234567890123456789 キーボードから入力した文字列
01234567890123456789012345678901

文字列は途中までですが、異常事態の発生は回避することができています。

2つ目は、この方法では、スペースを入力できないことです。
これは、スペースが区切り記号として認識されるためです。
残念ながら、こちらの解決は困難です。
文字数を数える
文字列の数を数えるのは難しいことではありません。
文字配列の先頭からEOSが出現するまでの数を数えるだけのことです。
次のプログラムは、入力された文字列の数を表示する例です。

ソースコード
#include <stdio.h>

int main(void)
{
    int i;

    char str[256];
    scanf("%s", str);

    for (i = 0; str[i] != '\0'; i++);

    printf("%d\n", i);

    return 0;
}

このプログラムの実行結果は、次の通りになります。

実行結果
ABCDEF  キーボードから入力した文字列
6

for文の意味が少しわかりにくいかも知れませんね。
配列要素の中にEOSが出現するまで、変数iをひたすら増加させているだけです。
変数iが増えればそれでよく、繰り返す文が必要ないので、繰り返す文は省略しているのです。

ただ、文字列の文字数を数えるために毎回for文を書くのは面倒です。
そのため、文字列の文字数を数えるstrlen関数が用意されています。
なお、strlen関数を使うには、string.h を #include する必要があります。

ソースコード
変数 = strlen(文字配列);

次のプログラムは、先ほどのプログラムをstrlen関数で書き直した例です。

ソースコード
#include <stdio.h>
#include <string.h>

int main(void)
{
    int i;

    char str[256];
    scanf("%s", str);

    i = strlen(str);

    printf("%d\n", i);

    return 0;
}

実行結果は先ほどと同じになります。
文字列の比較
文字配列の内容が同じかを比較する場合、次のようなプログラムでうまくいく気がしてしまいます。

ソースコード
str1 == str2;

しかし、文字配列同士の比較では==演算子を使うことはできません
具体的な理由は次章で明らかになりますが、ここで簡単に説明をしておくと、
この例では配列がまったく同じ(同じメモリを使う)配列なのかを比較しているのであって、
配列の中身が同じかどうかを比較しているわけではないためです。

文字配列の中身を比較するにはfor文で全要素を比較する必要があります。
次のプログラムは、入力された文字列が DRAGONQUEST であるかどうかを比較する例です。

ソースコード
#include <stdio.h>
#include <string.h>

int main(void)
{
    int len, i;
    char str1[256], str2[] = "DRAGONQUEST";

    scanf("%s", str1);

    len = strlen(str2);

    for (i = 0; i < len + 1; i++) {
        if (str1[i] != str2[i]) break;
    }
    
    if (i == len + 1) {
        printf("同じ\n");
    } else {
        printf("違う\n");
    }

    return 0;
}

``` このプログラムの実行結果は、次の通りになります。

実行結果
DRAGONQUEST キーボードから入力した文字列
同じ


実行結果
ABCDEF キーボードから入力した文字列
違う


実行結果
DRAGONQUEST3 キーボードから入力した文字列
違う

文字列の比較ではEOSまでが同じでなければならないため、 比較元の文字数よりも1文字大きく比較しています。
ただ、文字列を比較するために毎回for文を書くのは面倒です。
そのため、文字列を比較するstrcmp関数が用意されています。
なお、strcmp関数を使うには、string.h を #include する必要があります。

ソースコード
変数 = strcmp(文字配列1, 文字配列2);

この関数は、2つの文字配列の中身が同じである場合には0を返します。
次のプログラムは、先ほどのプログラムをstrcmp関数で書き直した例です。

ソースコード
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str1[256], str2[] = "DRAGONQUEST";

    scanf("%s", str1);

    if (strcmp(str1, str2) == 0) {
        printf("同じ\n");
    } else {
        printf("違う\n");
    }

    return 0;
}

実行結果は先ほどと同じになります。


本サイトについて

苦しんで覚えるC言語(苦C)は
C言語入門サイトの決定版です。
C言語の基本機能を体系立てて解説しており、
市販書籍と同等以上の完成度です。

第0部:プログラム概要編
  1. プログラムとは何か?
2章:プログラムの書き方
  1. 書き方のルール
  2. 書き方の慣習
  3. 練習問題2
3章:画面への表示
  1. 文字列の表示
  2. 改行文字
  3. 練習問題3
6章:キーボードからの入力
  1. 入力用の関数
  2. 入力の恐怖
  3. 練習問題6
9章:回数が決まっている繰り返し
  1. 繰り返しを行う文
  2. ループ動作の仕組み
  3. 練習問題9
10章:回数がわからない繰り返し
  1. 回数不明ループ
  2. 入力チェック
  3. 練習問題10
13章:複数の変数を一括して扱う
  1. 複数の変数をまとめて扱う
  2. 配列の使い方
  3. 練習問題13
20章:複数のソースファイル
  1. 最小限の分割
  2. 分割の定石
  3. 練習問題20

コメント
COMMENT

💬 コメント投稿欄を開く