プログラミング演習II

「文字列データ」

文字列データ操作ライブラリ関数 string.h

C言語の標準ライブラリには文字列データを扱うためのライブラリ関数が用意されている。以下はその一部である。
これらの関数は string.hをインクルードすることで使用可能となる。

size_t strlen(const char *s);
sが指す文字列の長さを返す。(末尾の'¥0'は含まない)
char *strcpy(char *dst, const char *src);
srcが指す文字列をdstが指す配列にコピーする。dstの値を返す。
char *strcat(char *dst, const char *src);
srcが指す文字列をdstが指す配列の末尾にコピーする。dstの値を返す。
int strcmp(const char *s1, const char *s2);
s1が指す文字列とs2が指す文字列を比較する。等しければ0、s1がs2より(辞書式順序で)大きければ正の値、s1がs2より小さければ負の値を返す。

※ 引数としてポインタ変数(引数名の前に"*"がついている)を取る仕様になっているが、ポインタについては後で解説する。ここでは引数として文字列データを与えるものと考えてよい。

Exercise 5: 文字列のコピー・連結・比較

check-string.cをコンパイル・実行し、文字列操作関数の使い方を確認してください。

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

void check_string(char str[])
{
    char tmpbuf[256];    /* 十分な大きさにする(ここでは256) */

    /* strの文字列を tmpbufにコピー */
    strcpy(tmpbuf, str);

    /* それぞれの文字列の内容と長さを表示 */
    printf("original string = '%s' (len=%d)\n", str, strlen(str));
    printf("copy string = '%s' (len=%d)\n", tmpbuf, strlen(tmpbuf));

    /* 文字列の比較(ここでは同じはず) */
    if (strcmp(tmpbuf, str) == 0)
	printf("2 string is same\n");
    else
	printf("2 string is different\n");

    printf("\n");

    /* tmpbufの文字列の後ろに別の文字列を連結 */
    strcat(tmpbuf, ", far away");

    /* それぞれの文字列の内容と長さを表示 */
    /* (連結した分 tmpbuf側の文字列が長くなっている) */
    printf("original string = '%s' (len=%d)\n", str, strlen(str));
    printf("copy string = '%s' (len=%d)\n", tmpbuf, strlen(tmpbuf));

    /* 文字列の比較(ここでは異なるはず) */
    if (strcmp(tmpbuf, str) == 0)
	printf("2 string is same\n");
    else
	printf("2 string is different\n");
}

int main(void)
{
    check_string("A Long time ago in a galaxy");

    return 0;
}

実行結果は以下のようになります。

original string = 'A Long time ago in a galaxy' (len=27)
copy string = 'A Long time ago in a galaxy' (len=27)
2 string is same

original string = 'A Long time ago in a galaxy' (len=27)
copy string = 'A Long time ago in a galaxy, far away' (len=37)
2 string is different

文字列データ入出力ライブラリ関数

文字列データの入出力として以下の関数が用意されている。
これらの関数は stdio.hをインクルードすることで使用可能となる。

char *fgets (char *sbuf, int n, FILE *stream);
最初の改行文字(¥n)まで、ストリームの終わりまで、または読み取られる文字数が n-1になるまでの、いずれか早い方の位置までの文字を読み取る。
入力として、入力した文字列を格納するためのバッファ領域(char型の配列)と入力文字数、ストリーム(標準入力やファイル)を与える。
入力が正常に終了した場合にはsbufのポインタを返す。
int fputs(const char *sbuf, FILE *stream);
指定した文字列を出力する。ストリングの最後のヌル文字 (\0) は書き込まない。
int型の返り値を持つが、実際には使用されず捨てられることが多い。(出力に失敗したエラー時にEOFを返す)

Exercise 6: 文字列の入出力

delete-spc.cをコンパイル・実行し、fgets関数とfputs関数の使い方を確認してください。

#include <ctype.h>
#include <stdio.h>

#define	MAXSTRLEN    1000        /* 最大1000文字 */

/* 空白文字除去 */
void delete_space(char dst[], char src[])
{
    int i, j;

    i = 0; j = 0;

    while (src[i] != '\0') {
	if (isspace(src[i])) {    /* 空白文字ならば読み飛ばす */
	    i++;
	}
	else {
	    dst[j++] = src[i++];  /* そうでなければ、srcからdstに1文字コピー */
	}
    }
    
    dst[j] = '\0';        /* 最後にNULL文字をセット */
}

int main(void)
{
    char strbuf[MAXSTRLEN+1];    /* 文字列入力用バッファ */
    char strbuf2[MAXSTRLEN+1];   /* 文字列変換結果格納用バッファ */

    printf("input=");
    while (fgets(strbuf, sizeof(strbuf), stdin) != NULL) {        /* 1行入力 */
                                          /* (入力終了時はNULLが返る) */
	delete_space(strbuf2, strbuf);

	printf("input string=");
	fputs(strbuf, stdout);   /* 改行コードも含まれる */
	printf("space deleted=");
	fputs(strbuf2, stdout);  /* isspace()の判定には\nも含まれるので、改行コードは取り除かれている */
	printf("\ninput=");
    }

    return 0;
}

実行結果例:

input=A = 123 + 45 - 67*8 / 9
input string=A = 123 + 45 - 67*8 / 9
space deleted=A=123+45-67*8/9

1行入力後エンターキーを叩くと、入力した文字列から空白文字が除去されて出力されます。
(プログラムの終了はCtrl-Z(windowsの場合)を押して入力を終了するか、Ctrl-Cを押して強制終了する)

文字列データ変換ライブラリ関数

C言語の標準ライブラリには文字列から数値データへの変換を行なう関数が用意されている。
これらの関数は stdlib.hをインクルードすることで使用可能となる。

int atoi(const char *s);
sが指す文字列をint型に変換する。
double atof(const char *s);
sが指す文字列をdouble型に変換する。

Exercise 7: 文字列の入出力

atox-test.cをコンパイル・実行し、文字列を数値として処理する方法を確認してください。

#include <stdlib.h>    /* stdlib.hをインクルード */
#include <stdio.h>

int main(void)
{
    char strbuf[500];        /* 文字列入力用のバッファ(最大499文字分) */

    printf("input number=");
    fgets(strbuf, sizeof(strbuf), stdin);   /* 1行入力 */

    printf("input string = '%s'\n", strbuf);
    printf("atoi = %d\n", atoi(strbuf));    /* intに変換 %dで表示 */
    printf("atof = %g\n", atof(strbuf));    /* doubleに変換 %gで表示 */

    return 0;
}

実行結果は以下のようになります。

input number=3.1415926535
input string = '3.1415926535'
atoi = 3
atof = 3.14159

他にも有用な関数が用意されているので、Visual Studioのヘルプを使って調べてみるとよい。