lesson8 (update:2019/11/28)

8.文字列処理


[ prev | next | index ]

目次


ここでは、文字と文字列を扱うプログラムについて解説します。C言語では、 1文字単位のデータはchar型の変数として扱うことができますが、文字列を 扱うためのデータ型は持っていません。従って、文字列を扱う場合には、 文字データが入る要素を持つ配列を使用します。すなわち、char型の配列 を用いることにより、文字列を扱います。

8.1 文字データの出力

文字を出力する関数には、printf()関数とputchar()関数があります。

例題8a

#include <stdio.h>

int main(void)
{
     char p = 'A';
     char q = 0x41;
     
     printf(" p=%c, p=%2x\n",p,p);
     printf(" q=%c, q=%2x\n",q,q);
     
     printf("\n putcharを使ったとき:p=");
     putchar(p);

     printf("\n putcharを使ったとき:q=");
     putchar(q);
     printf("\n");
     
     return 0;
}

実行結果:

 p=A, p=41
 q=A, q=41

 putcharを使ったとき:p=A
 putcharを使ったとき:q=A

この例題では、変数pに文字データ'A'を初期値として代入しています。 変数qには、16進数の41を初期値として代入しています。 0x41は、16進数で文字'A'のASCIIコードを表しています。 また、putchar()関数は、与えた引数を文字として出力する 標準ライブラリ関数で、この関数を使用するためには、 stdio.hをインクルードする必要があります。

8.2 文字データの入力

2-1 scanf()関数を用いる場合

標準入力であるキーボードから文字を入力する場合、入門書などにおいては、 多くはscanf()関数を用いて入力するように書かれています。 scanf()関数を用いた文字の入力は、次のようになります。

char p;

scanf("%c", &p);
printf("p=%c, p=%2x\n",p,p);

scanf()関数での変換指定子は、%cを用いています。これは、char型の変数に 入力することを意味しています。%cの代わりに16進数で入力することもできます。 その場合の変換指定子は、%xになります。 また、printf()関数も同様に、%c、%xを使用することができます。 printf()関数の出力の場合は、%xで文字のASCIIコードが出力されます。

2-2 getchar()関数を用いる場合

文字データを入力する別の方法に、getchar()関数があります。以下に getchar()関数を用いた文字データの入力の例を示します。

例題8b

#include <stdio.h>

int main(void)
{
     char p;
     
     printf("getchar関数で文字データを入力:");
     fflush(stdout);
     p = getchar();
     printf("p = %c, p = %2x\n",p,p);

     return 0;
}

実行結果:
getchar関数で文字データを入力:A
p = A, p = 41

getchar()関数は、標準入力より1文字入力し、その値を返す 標準ライブラリ関数です。getchar()関数の引数はありません。

8.3 文字列の出力

文字データの出力では、putchar()関数を利用しました。 しかし、 文字データを扱う場合、1文字ずつの文字データを扱うよりも 文字データをひとまとまりにした文字列として扱う方が多いです。 ここでは、printf()関数を用いた文字列を扱う場合の 文字列の出力の方法を示します。

例題8c

#include <stdio.h>

int main(void)
{
     char p[20] = "Personal Computer";
     
     printf("%s\n",&p[0]);
     
     return 0;
}

char型の配列pには、文字列と文字列の終端を表すヌル文字(\0)が 入ります。printf()関数で文字列を出力する場合の変換指定子には、 %sを使用します。printf()関数は、配列の先頭から文字を表示していき、 ヌル文字があると文字列の終端と判断します。

8.4 文字列処理

4-1 文字型配列への文字列の代入

文字列に変数を代入するには、ライブラリ関数strcpy()を用います。 この関数の定義は次のようになります。

char *strcpy(char *str1, const char *str2)
  機 能:文字列変数1(str1)に文字列2(str2)をコピー
  戻り値:str1

例題8d

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

int main(void)
{
     char p[20];
     
     strcpy(p,"Personal Computer");
     printf("%s\n",&p[0]);
     
     return 0;
}

文字列を代入するのに、p = "Personal Computer"; というふうに 書くことはできません。 宣言と初期化を同時に行う場合に限り、例題8cのように 書くことができます。また、この関数を用いるには、 string.hファイルをインクルードする必要があります。

※このプログラムをコンパイルするとwarningがでます。 Visual Studio の環境下では、strcpy()関数の代わりにstrcpy_s()関数の 使用が推奨されています。

4-2 文字列の連結

文字列を連結するには、ライブラリ関数strcat()を用います。 この関数の定義は次のようになります。

char *strcat(char *str1, const char *str2)
  機 能:文字列変数1(str1)に文字列2(str2)を連結
  戻り値:str1

例題8e

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

int main(void)
{
     char p[20]="Personal ";
     
     strcat(p,"Computer");
     printf("%s\n",&p[0]);  // printf("%s\n",p);と書いてもよい
     
     return 0;
}

※このプログラムをコンパイルするとwarningがでます。 Visual Studio の環境下では、strcat()関数の代わりにstrcat_s()関数の 使用が推奨されています。

4-3 その他の文字列処理関数

strcpy関数以外にも、文字や文字列を操作するためのライブラリ関数が準備されています。よく使われる文字列操作関数を表に示します。これらの関数を使用するためには、string.hファイルをインクルードする必要があります。

関数仕様

機能

strcpy(char s1[], char s2[])

s1にs2を末尾の\0も含めてコピーする

strcat(char s1[], char s2[])

s1にs2を末尾の\0も含めてつなげる

int strcmp(char s1[], char s2[])

s1とs2を比較し、同じ時に0を返す

int strlen(char s[])

文字列の文字数(\0は含まない)を返す

8.5 ビットを扱う演算

C言語には、算術演算や論理演算のほかにビットを扱う 演算が用意されています。

5-1 ビットごとの論理演算

short型のデータは16ビットで、これは2進数で16桁の数値になります。 ここでは、short型の変数を用いて各数値のビット演算を行ってみましょう。 ビット論理演算には、次のようなものがあります。

演算子

意味

ビットごとのAND演算

|

ビットごとのOR演算

^

ビットごとのXOR演算

~

ビットごとのNOT演算

例題8f

やってみよう!

例題8f で、変数a,bを2進数で表すと次のようになります。

a = 0000 0000 1111 1111
b = 1010 1010 1010 1010
※わかりやすように4桁ごとに区切ってあります。

これを踏まえて、出力がどうなるか予想してプログラムを実行してみよう。

5-2 ビットのシフト演算

ビットのシフト演算には、つぎのようなものがあります。

演算子

意味

<<

ビットを左にシフトする

x << 1 (変数xの値を左に1ビットシフト)

>>

ビットを右にシフトする

x >> 1 (変数xの値を右に1ビットシフト)

例題8g

#include <stdio.h>

int main(void)
{
    unsigned short x,y,z;
    x = 100;
    
    y = x << 1;
    z = x >> 1;
    
    printf("%5d [16進数 %4x]を左へ1ビットシフトすると%5d [16進数 %4x]\n",x,x,y,y);
    printf("%5d [16進数 %4x]を右へ1ビットシフトすると%5d [16進数 %4x]\n",x,x,z,z);

    return 0;
}

実行結果:
 100 [16進数   64]を左へ1ビットシフトすると  200 [16進数   c8]
 100 [16進数   64]を右へ1ビットシフトすると   50 [16進数   32]

「x << 1」は、変数xを左へ1ビットシフトします。 1左シフトは、変数xを2進数で考えたときに、1桁分左へ移動させる ことと同じです。1桁ずれれば、値は2倍になります。n左シフトすると 値は、2n倍となります。
また、「x >> 1」は、変数xを右へ1ビットシフトします。 1右シフトは、1桁分右へ移動させるので、値は1/2になります。 n右シフトは、値が1/2n倍になります。

8.6 演習課題

課題8 文字列の処理  

このファイル(p08.c)を使ってプログラムを作成すること。
講義後半にファイルをアップします。

次のプログラムを作りなさい。

(1)文字配列pの中から'm'の文字の場所を見つけて、その位置を配列の添字の数字で表示する。
(2)文字配列pの中から'f 'を見つけて、その個数を表示する。
(3)文字配列pの単語の個数を表示する。
(4)変数xの2の補数を表示する。

ただし、文字配列p、変数xは、次のように宣言するものとします。
char p[] = "He is a staff at the Department of Information Science and Biomedical Engineering";
short x = 100;

ヒント:
スペースのASCIIコードは0x20(10進で32)です。

出力結果は次のようになるようにします。 ○の中には値が入ります。

文字mが入っている添字番号: ○  ○  …
文字fの個数:○
単語の個数:○
x=100の補数:○


ホームワーク(文字列処理)

ソースコードと出力をWordに貼り付けてピアサポ室のポストに提出すること。 【提出期限 12月4日(水)まで】
レポート上部に「 プログラミング序論演習U 第8回 学籍番号 氏名 」を記入すること。

putchar()関数およびgetchar()関数を用いて、次のプログラムを完成させよ。

10文字以内の文字列を入力して出力するプログラム。の中を埋めてプログラムを完成させよう。

(※ 画像は10文字になっているが、文字数を必要におおじて増やすこと。)

※0x0Aは、LF(Line Feed)のアスキーコードで、ここでは、リターンキーが 押されたかどうかの検出のために用いています。


[ prev | next | index ]