文字と文字列

文字

C言語における文字とは,文字型変数に格納可能なデータを意味する.文字型変数の型名はcharである.char型は,1バイトのサイズを持ち,格納できる値は-128〜127までの整数である.表 1にC言語で利用可能な変数の型の一部を示す.

表 1. C言語で使用出来るデータ型(の一部,Windows 64bit)
種類 型名 サイズ(Byte) 値の範囲

文字型

char

1

-27 〜 27-1

整数型

short

2

-215 〜 215-1

int

4

-231 〜 231-1

longlong

8

-263 〜 263-1

浮動小数点型

float

4

1.175494×10-38 〜 3.402823× 1038

double

8

2.225074×10-308 〜 1.797693×10308

long double

16

3.362103×10-4932 〜 1.189731×104932

文字型に格納可能な値と,ファイルに記録あるいは画面に表示される文字との対応関係を定めたものがASCIIコードである.表 2にASCIIコードを示す.0番から31番までは制御コードであり,画面に表示されないことに注意.

表 2. ASCIIコード表

0

NUL

1

SOH

2

STX

3

ETX

4

EOT

5

ENQ

6

ACK

7

BEL

8

BS

9

HT

10

NL

11

VT

12

NP

13

CR

14

SO

15

SI

16

DLE

17

DC1

18

DC2

19

DC3

20

DC4

21

NAK

22

SYN

23

ETB

24

CAN

25

EM

26

SUB

27

ESC

28

FS

29

GS

30

RS

31

US

32

SP

33

!

34

"

35

#

36

$

37

%

38

&

39

'

40

(

41

)

42

*

43

+

44

,

45

-

46

.

47

/

48

0

49

1

50

2

51

3

52

4

53

5

54

6

55

7

56

8

57

9

58

:

59

;

60

<

61

=

62

>

63

?

64

@

65

A

66

B

67

C

68

D

69

E

70

F

71

G

72

H

73

I

74

J

75

K

76

L

77

M

78

N

79

O

80

P

81

Q

82

R

83

S

84

T

85

U

86

V

87

W

88

X

89

Y

90

Z

91

[

92

\

93

]

94

^

95

_

96

`

97

a

98

b

99

c

100

d

101

e

102

f

103

g

104

h

105

i

106

j

107

k

108

l

109

m

110

n

111

o

112

p

113

q

114

r

115

s

116

t

117

u

118

v

119

w

120

x

121

y

122

z

123

{

124

|

125

}

126

~

127

del

文字型変数に値を代入し,printf 関数によって表示するサンプルソースコードをリスト 1に,また,その実行結果をリスト 2に示す.printf関数での書式指定によって,変数の中身を文字として表示するか,数値として表示するかを制御できることが分かる.

リスト 1. char型変数への代入
char a, b;
a = 65;
b = 'A';
printf("char: %c %c\n", a, b);
printf("value: %d %d\n", a, b);
リスト 2. char型変数への代入の実行結果

A A
65 65

文字列

文字列とは文字の集合体である.では,char 型の値(すなわち,文字)の集合体はどのように定義するのだろうか.C言語では同じ型の値の集合体を定義するための,配列(array) と呼ばれるデータ構造が用意されている.以下では,文字列を定義するための配列の利用方法について解説する.

配列についての一般的な内容は次回で学習する.

文字列を定義するためには,文字型変数の配列を宣言する.配列の宣言には,配列の要素数を予め決定し,明示する必要がある.例えば,10文字からなる文字列nameを宣言するには,

char name[10];

と記述する.この宣言によって図 1のように,char型の値を10個格納するため領域が,メモリ上に確保される.

{half-width}
図 1. 10文字からなる文字列name

配列の各要素には0から始まる添字と,大かっこを用いてname[3]のようにアクセスできる.添字には定数以外にも,整数式を用いることができる.例えば

int i = 1;
char a[30];
a[2*i+1] = 'A';

などと記述することができる.なお,宣言直後の配列の中身はランダムな値が入っているため,初期化することが望ましい.配列の初期化の典型的なパターンをリスト 3に示す.

リスト 3. 配列の初期化
char data[20];
int i;
for (i = 0; i < 20 /* 配列の要素数 */; ++i) {
  data[i] = 0;
}

図 1の配列に,Takushokuという単語をキーボードから入力するには

scanf("%s", &name[0]);

と記述する.scanfの第2引数には,キーボードからの入力を格納する変数のアドレスを与えるが,ここではnameという配列の先頭の要素を指すアドレスを与えていることがわかる.配列の先頭アドレスの省略形として配列名を使うこともできる.

次回で学習する多次元配列ではこの限りではないので注意.

すなわち,省略形を使う場合には,

scanf("%s", name);

と記述する.

キーボードからTakushokuと入力した直後のメモリの中身は図 2のようになっている.

02 fig array filled
図 2. Takushokuと入力後の文字列nameの中身

最後の要素にキーボードからの入力ではない\0が挿入されていることがわかる.この\0は文字列の区切りを表すためのシンボルであり,null記号と呼ばれる.したがって,配列の宣言時には,想定される文字数の最大値+1を配列の要素数とする必要がある.\0の役割は,要素数よりも短い文字数の単語が入力された場合に,その単語の終わりを示すことである.

ファイル入出力

プログラム内でデータファイルを読み書き,すなわち入出力を行うためには,ファイルのオープンおよびクローズ処理が必要となる.

ファイルのオープン

ファイルをオープンするためには,fopen関数を用いる.基本的な使用方法は以下のとおりである.

FILE *fp; // ファイルポインタ
fp = fopen("ファイルのパス\ファイル名", モード);
ファイルポインタ

オープン後のファイルからデータを読み込んだり,あるいはファイルにデータを書き込む際に,ファイル名の代わりに使う識別子のようなもの.

モード

オープンしたファイルからデータを読み込むときには"r",ファイルにデータを上書きするときには"w",追記するときには"a"を用いる.また,データの格納形式はバイナリ形式の際には"rb", "wb"のようにbを追加する.

ファイルのクローズ

ファイルをクローズするにはfclose関数を用いる.使用方法は以下の通りである.

fclose(クローズするファイルのファイルポインタ);

ファイルから1文字を読み込む

オープンしたファイルから1文字を読み込むにはgetc関数を用いる.使用例をリスト 4に示す.

リスト 4. getc関数の使い方
int c;
FILE *fp = fopen("myData.txt", "r");
do {
  c = getc(fp);
  printf("%c", c);
} while (c != EOF);
fclose(fp);

ここで,6行目のc != EOFについて解説する.EOFはEnd of Fileの略であり,ファイルの終端を示す特別な値である.EOFの値は,コンパイラによって異なってもよいことになっており,char 型の範囲外の値も取りうるため,getc関数はint 型の値を返す仕様となっている.

本講義で用いるコンパイラではEOFの値は-1を取る

文字検査関数

ファイルから読み込んだ文字の種類を判別する必要が生じることがある.たとえば,その文字が数字なのか,アルファベットなのか,アルファベットなら大文字なのか,小文字なのか,といった具合である.この判別を可能とするのが文字検査関数である.文字検査関数を使用するにはctype.hをインクルードする必要がある.

リスト 5に,文字が10進数の数字かどうかを判別するisdigit()関数の使用例 を示す.

リスト 5. isdigit関数の使用例
#include <ctype.h>  //文字検査関数のために必須
#include <stdio.h>

int main() {
  int c;
  FILE *fp;
  fp = fopen("myText.txt", "r");

  c = getc(fp);

  if (isdigit(c)) {
    printf("読み込んだ文字%cは数字です.\n", c);
  } else {
    printf("読み込んだ文字%cは数字では有りません.\n", c);
  }

  fclose(fp);
}

すべての文字検査関数はその引数にint型を取る.isdigit関数においては,引数の文字が10進数の数字であったときに,非ゼロの値が,10進数の数字ではなかったときにゼロが戻り値となる.以下に,文字検査関数の一覧を示す.

isalnum

文字がアルファベットもしくは数字かどうか

isalpha

文字がアルファベットかどうか

isblank

文字が標準ブランク文字かどうか

iscntr

文字が制御文字 (control character) かどうか

isdigit

文字が10進数の数字かどうか

isgraph

文字が空白 (' ') を除く表示文字 (printing character) かどうか

islower

文字がアルファベットの小文字かどうか

isprint

文字が表示文字かどうか

ispunct

文字が区切り文字 (punctuation character) かどうか

isspace

文字が標準空白類文字かどうか

isupper

文字がアルファベットの大文字かどうか

isxdigit

文字が16進数の数字かどうか

文字列処理関数

string.hをインクルードすることで文字列を操作するための標準関数 が使えるようになる.そのうち,よく用いられる関数について以下で説明する.

strcmp

文字列の比較を行う.2つの文字列があり,その先頭アドレスをs1s2とするとき,

if (strcmp(s1, s2) == 0) {
	:

のように用いる.この関数はs1の中身のASCIIコード < s2の中身のASCIIコードならば負の値,s1の中身のASCIIコード == s2の中身のASCIIコードならばゼロ,はs1の中身のASCIIコード > s2の先中身のASCIIコードならば正の値を返す.これを用いて例えばアルファベット順での順位の比較などを行うことができる.

strcpy

文字列のコピーを行う.コピー元の文字列の先頭アドレスをsrc,コピー先の文字列の先頭アドレスをdstとするとき,

strcpy(dst, src)

のように用いる.終端記号\0までコピーされる.コピー先のアドレスで示される領域とコピー元の領域に重なりがある場合,この関数の動作は未定義であるため,使用には注意を要する.

この他にもmemcpy, memmove, memsetなどよく使われる関数があるが,ここでは説明を割愛する.