文字列操作と文字操作関数
- 標準ヘッダstdlib.hをインクルードする
#include <stdlib.h>
機能 | 概要 | 備考 |
変換 | int atoi(char *nptr); | nptrの文字列を整数(int)に変換する |
long atol(char *nptr); | nptrの文字列を整数(long)に変換する |
double atof(char *nptr); | nptrの文字列を実数(double)に変換する |
実行 | int system(char *program) | programをOSのコマンドとして実行する |
停止 | int exit(int status); | プログラムを停止する |
乱数 | int rand(void); | 擬似乱数を生成する |
void srand(unsigned int seed); | 乱数のseed(種)を設定する |
動的 記憶 | void *malloc(size_t size); | sizeバイト分の動的記憶を割り当てる |
void free(void *ptr); | 動的に割り当てた記憶を解放する |
- 標準ヘッダstring.hをインクルードする
#include <string.h>
機能 | 概要 | 備考 |
連結 |
char *strcat(char *s, chat *a); | aをsの終わりに連結し、sを返す |
char *strncat(char *s, chat *a, int n); | aの最大n文字をsの終わりに連結し、sを返す |
比較 |
int strcmp(char *s, chat *t); | sとtを比較、s−t |
int strncmp(char *s, chat *t, int n); | sとtの最初のn文字を比較 |
コピー |
char *strcpy(char *d, chat *s); | sをdにコピーし、dを返す |
char *strncpy(char *d, chat *s, int n); | sの最大n文字をdにコピーし、dを返す |
長さ |
int strlen(chat *s); | sの長さを返す |
位置 | char *strchr(chat *s, int c); | sの中の最初に現れる文字cへのポインタ、なければNULLを返す |
char *strrchr(chat *s, int c); | sの中の最後に現れる文字cへのポインタ、なければNULLを返す |
char *strstr(chat *s, char *ss); | sの最初に現れる部分文字列ssへのポインタ、なければNULLを返す |
- 標準ヘッダctype.hをインクルードする
#include <ctype.h>
機能 | 概要 | 備考 |
テスト |
int isalpha(int c); | cがアルファベット? |
真か偽を返す |
int isupper(int c); | cが大文字? |
int islower(int c); | cが小文字? |
int isdigit(int c); | cが数字? |
int isalnum(int c); | cが英数字? |
int isspace(int c); | cが空白文字? |
int isprint(int c); | cが表示文字? |
変換 |
int toupper(int c); | cを大文字に | |
int tolower(int c); | cを小文字に | |
- 空白文字:スペース、タブ、改行
- 標準ライブラリ関数の仕様と異なるものもあるが、良いサンプルプログラムである。
- ソースプログラムの中に含める場合は、ライブラリ関数と違う名前にすること!
例:strlen() → mystrlen()
/* mystrlen: s の長さを返す */
int mystrlen(char *s)
{
int i;
i = 0;
while( s[i] != '\0' )
i++;
return( i );
}
/* testmystrlen.c */
- ポインタで受けて配列のように使っているが、どうしてこんなことができるのでしょうか?
→ s[i] は *(s+i) だから!
- 仮引数の宣言はint mystrlen(char s[])と書いても良い
1. 上の関数をforで書き換えてみよ!
- 文字列は代入できないので、ループを使った関数を作る
- 標準ライブラリのstrcpyはコピー先の文字列が返される
/* mystrcpy: t を s にコピーする;配列版 */
void mystrcpy(char *s, char *t)
{
int i;
i = 0;
while( (s[i] = t[i]) != '\0')
i++;
}
/* testmystrcpy.c */
- 仮引数の宣言はvoid mystrcpy(char s[], char t[])と書いても良い
2. 上の関数をforで書き換えてみよ!
/* mystrcpy: t を s にコピーする;ポインタ版1 */
void mystrcpy(char *s, char *t)
{
while( (*s = *t) != '\0')
{
s++;
t++;
}
}
3. 上の関数のwhileのブロックを式に書き換えてみよ!
2つの式を1つにする(ヒント:カンマ演算子)
/* mystrcpy: t を s にコピーする;ポインタ版2 */
void mystrcpy(char *s, char *t)
{
while( (*s++ = *t++) != '\0')
;
}
/* mystrcpy: t を s にコピーする;ポインタ版3 */
void mystrcpy(char *s, char *t)
{
while( *s++ = *t++ )
;
}
- どうして!= '\0'とちゃんと比較しなくても良いのでしょうか?
→真理値は、真がノンゼロで、偽がゼロだから
- 標準ライブラリのstrcatはの結果の文字列へのポインタが返される
/* mystrcat: t を s の終わりに連結する;s が指す領域は十分大きいこと */
void mystrcat(char *s, char *t)
{
int i, j;
i = j = 0;
while( s[i] != '\0') /* s の終わりを探す */
i++;
while( (s[i++] = t[j++]) != '\0') /* t をコピーする */
;
}
/* testmystrcat.c */
4. 上の関数をforで書き換えてみよ!
5. 上の関数をポインタ版に書き換えてみよ!
- s が t より辞書的な順序からみて小さいか等しいか大きいかによって、
それぞれ負、0、正の値を返す
/* mystrcmp: s - t */
int mystrcmp(char *s, char *t)
{
int i;
for( i = 0; s[i] == t[i]; i++ )
if( s[i] == '\0' )
return( 0 );
return( s[i] - t[i] );
}
/* testmystrcmp.c */
/* mystrcmp: s - t */
int mystrcmp(char *s, char *t)
{
for( ; *s == *t; s++, t++ )
if( *s == '\0' )
return( 0 );
return( *s - *t );
}
/* mytolower: c を小文字に変換する;ASCIIのみ */
int mytolower(int c)
{
if( c >= 'A' && c <='Z' )
return( c + 'a' - 'A' );
else
return( c );
}
/* testmytolower.c */
/* myisdigit: c が10進数字か?;ASCIIのみ */
int myisdigit(int c)
{
return( c >= '0' && c <='9' );
}
/* testmyisdigit.c */
(ライブラリ関数と比較検証するプログラムを作成してみよ!)
- 最初の最大 n 文字を扱う
- 仕様の詳細は標準ライブラリ参照
参考(Linux man コマンドより)
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
strcpy() 関数は src(終端文字‘\0’を含む)をポインタとする文字列を destをポインタとする配列にコピーする。
二つの文字列は重ならない。受け側の文字列であるdestはコピーを受け取るのに十分な程度に大きくなければならない。
src のnバイトを越えない数の文字がコピーされることを除けば、strncpy()関数も同様である。
したがって、もし srcの最初のnバイトの中に NUL 文字が無ければ、コピーの結果としてできる文字列は NUL で終端していないものになる。
src の長さが n よりも少ない場合は、dest の残りはヌルバイトで埋められる。
strcpy()関数とstrncpy()関数は受け側の文字列destへのポインタを返す。
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
strcat() 関数は、 dest の最後にある‘\0’文字を上書きして、dest 文字列の後に src 文字列を付け加える。
同時に終端文字‘\0’を加える。文字列は重ならない。
dest 文字列は、連結が正しい結果を得るような十分な領域を持っていなければならない。
strncat() は、src から最大で n 個の文字が使われることを除けば、strcat() と似ている。
結果は常に‘\0’文字で終端されるので、最大で n+1 個の文字が書き出される。
strcat() 関数と strncat() 関数は、結果としてできる文字列 dest へのポインタを返す。
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
strcmp() 関数は二つの文字列 s1 と s2 を較べる。
この関数は、s1 が s2 に較べて 1)小さい、2)等しい、3)大きい場合に、ゼロよりも 1)小さい、2)等しい、3)大きい整数を返す。
strncmp() 関数は、s1 と s2 の最初の n 文字だけを比較することを除けば、strcmp()と同様である。
strcmp() 関数と strncmp() 関数は整数を返す。
この整数は、ゼロよりも、1)小さい、2)等しい、3)大きいのいずれかである。
それぞれは、s1(または、この文字列の最初の n バイト)が s2 よりも、1)小さい、2)等しい、3)大きいに対応している。