第24章 文字列をいじろう

 文字列をいじくる関数はいろいろあります。そのうち、今回は strlen と sprintf について話します。

 これら以外のものは、後に出てくることもあるかもしれませんが、自分で調べてみるのもいいでしょう。


 今回の要点はこんなところです。


 では、いってみましょう。


 前回 for を使って文字列の要素を表示しましたね。

for(i = 0; i < 14; i++)
    cout << (int)(unsigned char)szHello[i] << ", ";

 この 14 という数値は szHello の大きさ−1です。何故1を引いているかといえば、最後の1つだけは ", " を表示しないので、処理を別にする必要があったからでした。

 しかし、文字列を変更するようなことがあったらどうなるでしょうか? いちいちこの数字も変えなくてはならないのは面倒です。そんなときのために、文字列の長さを取得する関数が用意されています。

strlen(szHello)

 この関数の戻り値は文字列の長さになります。このとき注意するのは、ヌルキャラクタは数えられないというところです。例えば、"やぁ、こんちは" では、14 が返ってくることになります。

プログラム
// String1b.cpp
#include <iostream.h>
#include <string.h>

int main()
{
    int i;
    char szHello[] = "やぁ、こんちは";

    cout << "「" << szHello << "」を文字コードに変えると、" << endl;

    for(i = 0; i < strlen(szHello); i++)
        cout << (int)(unsigned char)szHello[i] << ", ";

    cout << (int)(unsigned char)szHello[i] << endl
         << "になります。" << endl;

    return 0;
}

 ん? 何か見慣れないものがありますね。

#include <string.h>

 これは、文字列操作をするために必要なものです。詳しくは第27章に話します。

 まぁそれは置いておいて、これで文字列を変更してもループの回数のところを変更しなくてすむようになりました。このように、様々な変更に耐えうるプログラムを組むことはバグの抑制につながります。


 次は文字列を作ってみましょう。

 例えば、第8章の Func1b.cpp を見て下さい。

プログラム
// Func1b.cpp
#include <iostream.h>

void f(int x, int y)
{
    cout << "f(" << x << ", " << y
         << " = " << 2 * x + y << endl;
}

int main()
{
    f(1, 2);
    f(182, 144);
    return 0;
}

 cout のところがかなり面倒になっていますね。では、この表示される文字列をあらかじめ作っておいて、それを表示するようにしてみましょう。

 そのための関数が sprintf です。この関数は覚えるのがかなり面倒な関数ですが、利用価値は大きいです。

プログラム実行結果
// Func1c.cpp
#include <iostream.h>
#include <stdio.h>

void f(int x, int y)
{
    char szResult[50];

    sprintf(szResult, "f(%d, %d) = %d", x, y, 2 * x + y);
    cout << szResult << endl;
}

int main()
{
    f(1, 2);
    f(182, 144);
    return 0;
}
f(1, 2) = 4
f(182, 144) = 508

 また

#include <stdio.h>

という見慣れないものがありますが、これも sprintf を使うために必要なものです。

 先ず、作った文字列を入れておく容器が必要になります。それが szResult です。大きさは大きめにとっておくとよいでしょう。もし小さすぎても、この関数はそんなことお構いなしに文字列を入れてしまいます。そうなるとどうなってしまうかは、わかりません。

 で、文字列を作るのは

sprintf(szResult, "f(%d, %d) = %d", x, y, 2 * x + y);

の部分です。はじめの引数から順に説明していきます。

 先ず、第1引数は作った文字列を入れる容器です。ここにはもちろんさっき作った szResult を入れます。

 次に、第2引数は作る文字列の鋳型です。%d のところが第3引数以降に書いてある数値に置き換わって、それが第1引数 szResult に入るという要領です。

 すなわち、第3引数以降の引数は %d の数だけ必要になります。引数の個数が一定でないことに注意して下さい。

 ここでは、初めは x = 1, y = 2, 2 * x + y = 4 なので、順に 1, 2, 4 の入った文字列が作られます。次は x = 184, y = 144, 2 * x + y = 508 なので、順に 184, 144, 508 の入った文字列が作られます。


 sprintf はもっといろいろなパーツを組み合わせて文字列を作ることができます。パーツの種類は %... で表します。例えば %s は文字列を埋め込むことができます。そのほかにもいろいろありますが、多すぎて全部の機能をここで紹介することはできません。一部だけ表にします。

記号 %d %x %f %c %s
パーツ 整数 16進数 小数 1文字 文字列

 あと、実はこの書式と同じようにして文字列を表示する関数も存在します。それは printf です。ですから、ここは

printf("f(%d, %d) = %d", x, y, 2 * x + y);

とすることもできます。


 文字列を操作する関数は他にもいろいろあります。ですが、ここで逐一全てを説明するには限界があります。なので、重要なものを表にするに止めて、あとはヘルプで「文字列操作ルーチン」を確認して下さい。

関数名 引数 機能
strcpy 第1引数:容器
第2引数:文字列
第2引数の文字列を第1引数にコピーします。
strcat 文字列を2つ 第2引数の文字列を第1引数に追加します。第1引数の容量をオーバーしないよう気を付けて下さい。
strcmp 文字列を2つ 文字列の比較を行います。等しいときは0を返します。文字列を直接 == で比較することはできないので注意して下さい。
strchr 第1引数:文字列
第2引数:文字
指定した文字列の中で、指定した文字が最初に現れるアドレスを返します。見つからなければ NULL というものを返します。
strrchr 第1引数:文字列
第2引数:文字
指定した文字列の中で、指定した文字が最後に現れるアドレスを返します。見つからなければ NULL というものを返します。

補足

 新しいコンパイラでは、<string.h> の代わりに <cstring> と書きます。 <iostream.h> の場合は ".h" を除いただけですが、今回は頭に "c" をつけます。これは、C++ より前、つまり C の時代からある機能であることを表します。


 では、今回の要点です。


 次回は第25章ということで「ひとやすみ」と題し、VC++のヘルプ機能について話していきます。

 では、また次回まで。


第23章 文字列の扱い方 | 第25章 ひとやすみ...

Last update was done on 2004.1.22

この講座の著作権はロベールが保有しています