【C言語入門】文字列の連結・分割(strcat、strtok)

文字列の連結・分割関数を使ったことがありますでしょうか?

C言語ではそれぞれ便利な関数が用意されていますので、ぜひ学んでみましょう!


複数の文字列を一つに繋げたい

区切り文字を持った文字列を分解したい

今回はそんな課題を持つ人たちに向けて、strcat関数やstrtok関数についてみていきたいと思います。

  • [基本]strcatで文字列を結合する方法
  • [基本]sprintfで文字列を結合する方法
  • [応用]strcat、sprintf関数を使わない方法
  • [基本]strcat関数による文字列の分割について
  • [応用]文字列の使い方総まとめ

このような内容で、文字列の連結・分割について、使い方をわかりやすく解説しますね!

よろしくお願いいたします。

目次

文字列の連結について

2つの文字列を連結するにはstrcat関数をよく使います。それ以外にもsprintf関数を使う方法もありますし、どちらも使わない方法もあります。

それぞれの使い方について、解説していきます。

strcatで結合する方法

まずは、strcat関数を使う方法について解説します。

この関数を使うためには、まずヘッダーファイル「string.h」が必要です。最初にこのファイルををインクルードしましょう。

次にstracat関数の具体的な使い方です。この関数は、第1引数に指定した文字列の最後に、第2引数に指定した文字列を追加してくれます。

さっそくサンプルコードで確認していきましょう!

#include <stdio.h>
#include <string.h>
 
int main(void) {
    char str1[30] = "Hello ";
    char str2[] = "World!";
    
    // 文字列の連結
    strcat(str1, str2);
    printf("str1の文字列は: %s\n", str1);
    
    return 0;
}

実行結果:

str1の文字列は: Hello World!

このサンプルコードでは文字列「str1」に「str2」を追加し、その後「str1」を表示しています。

この時【 「str1」に「str2」を追加 】というのが注意しなければならない点です。

str1変数へ「Hello World!」という文字列が入る、ということです。str1変数に結合後の文字列が入りきらない場合、エラーが発生します。

第一引数へ渡す変数は必ず、結合後の文字列が入る大きさを確保しておきましょう。

sprintfで結合する方法

sprintf関数を使って文字列を結合させることもできます。

以下のように記述します。

sprintf(代入する文字列名, “出力文字列書式”, 変数1, 変数2, ・・・・)

sprintf関数の第3引数以降は可変長変数です。

ですので、sprintf関数では3つ以上の文字列も連結させることができます。

sprintf関数の第1引数に代入する文字配列名を指定し、第2引数に出力文字列を、第3引数以降に出力文字列に含まれる変数を入力します。

サンプルコードで確認しましょう。

#include <stdio.h>
 
int main(void) {
    char *str1 = "Hello";
    char *str2 = "World!";
 
    char str3[30];
 
    sprintf(str3, "%s %s\n", str1, str2);
    printf("%s", str3);
 
    return 0;
}

実行結果:

Hello World!

このサンプルコードではsprintf関数を使って、文字配列「str1」と「str2」を使用した出力文字列を文字列「str3」に代入しています。

そして文字列「str3」をprintf関数を使って出力表示しています。

sprintf関数の使い方については、こちらで詳しく解説していますので、ぜひ参考にしてください。

strcat、sprintf関数を使わない方法

これまで文字列の連結について、strcat関数およびsprintf関数を使う方法についてお伝えしてきました。

使うタイミングは限られますが、これらの方法以外にも関数を使わずに、連結する方法もあります。文字列リテラルを並べるだけで連結させる方法です。

サンプルコードで確認しましょう。

#include <stdio.h>
 
int main(void) {
    char str[] = "Hello " "World!";

    printf("%s", str);
 
    return 0;
}

実行結果:

Hello World!

このサンプルコードでは、文字列リテラルを並べて初期化した文字列strを宣言、定義しています。

この文字列をprintf関数を使って表示確認すると、2つの文字列リテラルが連結されているのがわかります。

文字列の分割について

文字列を区切り文字で分割するにはstrtok関数を使用します。

strtok関数の使い方

使い方が少し難しい関数ですので、今回は最初にサンプルを見て、それから理解を深めていきましょう。

今回は文字列「”Hello,Tokyo,Osaka,Nagoya”」をカンマ(,)区切りにして、個別に出力することにしましょう。

まずはサンプルコードです。

#include 
#include 

int main(void) {
    char str[32] = "Hello,Tokyo,Osaka,Nagoya";
    char *ptr;
    
    // カンマを区切りに文字列を分割
    // 1回目
    ptr = strtok(str, ",");
    printf("%s\n", ptr);
    
    // 2回目以降
    while(ptr != NULL) {
        // strtok関数により変更されたNULLのポインタが先頭
        ptr = strtok(NULL, ",");
        
        // ptrがNULLの場合エラーが発生するので対処
        if(ptr != NULL) {
            printf("%s\n", ptr);
        }
    }
    
    return 0;
}

実行結果:

Hello
Tokyo
Osaka
Nagoya

ちゃんと文字列「”Hello,Tokyo,Osaka,Nagoya”」がカンマ区切りで、それぞれ表示できていますね!

まずstrtok関数を使うためにはヘッダーファイル「string.h」をインクルードする必要があります。

#include 

これはいつもの通りですね。

次に主役のstrtok関数を見てみましょう。

// カンマを区切りに文字列を分割
// 1回目
ptr = strtok(str, ",");
printf("%s\n", ptr);

strtok関数の第1引数には分解する文字列のアドレスを、第2引数には区切り文字群を指定します。

今回はカンマ(,)を区切り文字にしているわけですね!

この際戻り値は区切り文字が登場するまでの、最初の文字列のポインタを返します。もし区切り文字が見つからない場合はNULLを返します。1回目に呼び出されているこの部分は「Hello」を取得・表示しているわけですね!

そしてここからが重要な点です。

2回目以降は第1引数をNULLにすることで、繰り返し実行が行えるのです。

// 2回目以降
while(ptr != NULL) {
    // strtok関数により変更されたNULLのポインタが先頭
    ptr = strtok(NULL, ",");
    
    // ptrがNULLの場合エラーが発生するので対処
    if(ptr != NULL) {
        printf("%s\n", ptr);
    }
}

strtok関数は次の文字の、先頭のポインタを返してくれます。

先ほど説明した通り、もう見つからなくなったらNULLを返してくれるわけなので、whileループで終了と判定する形で、繰り返しています。

一つづつ紐解いてみていけば簡単な仕組みですね!

[補足]strtok関数のいろいろ

区切り文字で分解を行ってくれる「strtok関数」が便利なことはわかりました。

ここではいくつか補足がありますので見ていきましょう。

渡した文字列には変更がかかる

strtok関数を使用して分解した文字列へは変更がかかります。

区切り文字が文字列の終端文字NULLに変更されてしまうのです。元々の文字列から値が変わってしまいますので注意しましょう!

区切り文字は複数設定できる

見出しの通りです。

区切り文字は複数設定が可能です。

たとえば、スペースとカンマ(,)を区切り文字にしたい場合は、以下の通りです。

ptr = strtok(str, " ,");

文字列の使い方総まとめ

この記事では紹介しきれなかった文字列のいろいろな使い方を次の記事にまとめているので、ぜひ確認してください!

まとめ

ここでは、文字列を連結・分割する方法について説明しました。

文字列を連結する場合はstrcat関数を、分割する場合はstrtok関数を使用します。

連結する場合はsprintf関数を使用したり、文字列リテラルを並べるだけで連結することもできます。

それぞれの関数を使いこなすことができるように、この記事を何度も参考にして下さいね!

この記事を書いた人

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
info@sss-lab.com

目次