「C言語の基礎 - 文字列」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(ページの作成:「== 文字列を初期化する == C言語で文字列を初期化するには、string.hのmemset関数を使用する。<br> <br> memset関数は、第1引数が指す…」)
 
209行目: 209行目:
<br><br>
<br><br>


== 文字列の先頭にある空白を削除する
== 文字列の先頭にある空白を削除する ==
C言語には、文字列の先頭にある空白を削除する関数やマクロは存在しないので、各自でこの機能を実装する必要がある。<br>
C言語には、文字列の先頭にある空白を削除する関数やマクロは存在しないので、各自でこの機能を実装する必要がある。<br>
<br>
<br>

2020年4月24日 (金) 00:08時点における版

文字列を初期化する

C言語で文字列を初期化するには、string.hのmemset関数を使用する。

memset関数は、第1引数が指すオブジェクトの先頭から第3引数の文字数分だけ、第2引数の文字列をセットする関数である。
この関数を利用すれば、文字列を指定した文字で埋めることができる。

注意
memset関数は、文字列の終端'\0'を自動的に付加しないので、'\0'以外の文字で埋める場合は、文字列の最後に終端'\0'を付加する必要がある。

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #define N 16
 
 int main(void)
 {
    char s[N];
 
    /* 文字列 s を 15 文字分 'z' で埋める. */
    memset(s, 'z', N);
    s[N - 1] = '\0';
 
    printf("s: %s\n", s);
 
    return EXIT_SUCCESS;
 }



文字列をコピーする

文字列をコピーするには、string.hのstrcpy関数またはstrncpy関数を使用する。
ただし、strcpy関数はバッファオーバーフローを発生させやすい関数なので、ここでは、strncpy関数を記載する。

strncpy関数は、第2引数が指す文字列から、第1引数が指す文字列に最大で第3引数の文字数分をコピーする関数である。
なお、第2引数が指す文字列の終端'\0'に続く文字はコピーされない。

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #define N 256
 
 int main(void)
 {
    char s1[N] = {'\0'};
    char s2[] = "Snoopy!";
 
    printf("-- コピー前 --\n");
    printf("s1: %s\n", s1);
    printf("s2: %s\n", s2);
 
    /* s2の内容をN文字分だけs1にコピー */
    strncpy(s1, s2, N);
    if ( N > 0 )
    {
       s1[N - 1] = '\0';
    }
 
    printf("\n-- コピー後 --\n");
    printf("s1: %s\n", s1);
    printf("s2: %s\n", s2);
 
    return EXIT_SUCCESS;
 }


注意
strncpy関数は、第3引数の値が第2引数のサイズよりも大きい場合、第1引数に文字列をコピーした後、自動的に文字列の最後まで'\0'を付加する。
しかし、第3引数の値が第2引数のサイズよりも小さい場合、終端'\0'を付加しない。
したがって、第2引数のサイズが第3引数の値よりも大きい場合は、なんらかの対策が必要になる。
最も簡単な対策法としては、コピー後の文字列のn - 1番目の要素に'\0'をセットする方法がある。
具体的には以下のように実装する。

 strncpy(s1, s2, n);
 if (n > 0)
 {
    s1[n - 1] = '\0';
 }



文字列を連結する

文字列を連結するには、string.hのstrcat関数またはstrncat関数を使用する。
ただし、strcat関数はバッファオーバーフローを発生させやすい関数なので、ここでは、strncat関数を記載する。

strncat関数は、第2引数が指す文字列から最大で第3引数の文字数分の文字列を、第1引数が指す文字列の最後に付加する。
なお、文字列の終端'\0'は自動的に付加されるので、第3引数の値が第2引数のサイズよりも小さい場合でも、手動で'\0'を付加する必要はない。

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #define N 256
 
 int main(void)
 {
    char s1[] = "Snoopy";
    char s2[] = "Charlie Brown";
 
    /* 文字列の連結 */
    strncat(s1, s2, 7);
    printf("s1 + s2 (7文字分) : %s\n", s1);
 
    return EXIT_SUCCESS;
 }



文字列を指定文字で分割する

文字列を指定文字で分割するには、string.hのstrtok関数を使用する。
strtok関数は、第1引数が指す文字列を、第2引数が指す文字列の中のいずれかの文字で区切られる字句の列に分割する関数である。
strtok関数は、1回の呼び出しで複数の分割を行うことができない。文字列の分割は、strtok関数を呼び出すごとに1回ずつ行われる。
strtok関数の1回目の呼び出しには、第1引数に分割する対象の文字列を指定する。
2回目以降の呼び出しは、第1引数にNULLを指定することで、前回分割された場所の次から分割を開始する。
分割できる文字列がなくなると、strtok関数はNULLを返す。

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 int main(void)
 {
    char s1[] = "0055,Ichiro Suzuki,Seattle,090-9999-9999";
    char *code, *name, *address, *tel, *empty;
 
    /* 1回目の呼出し */
    code = strtok(s1, ",");
 
    /* 2回目以降の呼出し */
    name = strtok(NULL, ",");
    address = strtok(NULL, ",");
    tel = strtok(NULL, ",");
    empty = strtok(NULL, ",");
 
    printf("code: %s\n", code);
    printf("name: %s\n", name);
    printf("address: %s\n", address);
    printf("tel: %s\n", tel);
    printf("empty: %s\n", empty);
 
    return EXIT_SUCCESS;
 }



文字列の先頭と末尾にある空白を削除する

C言語には、文字列の先頭と末尾にある空白を削除する関数やマクロは存在しない。
したがって、各自でこの機能を実装する必要がある。

実装は以下の手順で行うことが出来る。

  1. 文字列の末尾の位置を探す
  2. 手順 1 で探した末尾から順に,空白でない位置を探す
  3. 手順 2 で探した位置 + 1 に終端の '\0' を付加する
  4. 文字列の先頭から順番に空白でない位置を探す
  5. 手順 4 で探した位置から末尾まで文字列をコピーする


 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 int Trim(char *s);
 
 int main(void)
 {
    int ret;
    char snoopy[] = "   SNOOPY   ";
 
    ret = Trim(snoopy);
    printf("変換後: \"%s\"\n", snoopy);
    printf("削除した空白: %d文字\n", ret);
 
    return EXIT_SUCCESS;
 }
 
 /* 文字列の先頭と末尾にある空白を削除する */
 /* @param[in] s 対象文字列                */
 /* @return 削除した空白の数を返す         */
 int Trim(char *s)
 {
    int i;
    int count = 0;
 
    /* 空ポインタか? */
    if ( s == NULL )
    {
        return -1;
    }
 
    /* 文字列長を取得する */
    i = strlen(s);
 
    /* 末尾から順に空白でない位置を探す */
    while ( --i >= 0 && s[i] == ' ' ) count++;
 
    /* 終端ナル文字を付加する */
    s[i+1] = '\0';
 
    /* 先頭から順に空白でない位置を探す */
    i = 0;
    while ( s[i] != '\0' && s[i] == ' ' ) i++;
    strcpy(s, &s[i]);
 
    return i + count;
 }



文字列の先頭にある空白を削除する

C言語には、文字列の先頭にある空白を削除する関数やマクロは存在しないので、各自でこの機能を実装する必要がある。

実装は以下の手順で行うことが出来る。

  1. 文字列の先頭から順番に空白でない位置を探す
  2. 手順 1 で探した位置から末尾まで文字列をコピーする
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 int TrimStart(char *s);
 
 int main(void)
 {
    int ret;
    char snoopy[] = "   SNOOPY";
 
    ret = TrimStart(snoopy);
    printf("変換後: \"%s\"\n", snoopy);
    printf("削除した空白: %d文字\n", ret);
 
    return EXIT_SUCCESS;
 }
 
 /* 文字列の先頭にある空白を削除する */
 /* @param [in] s 対象文字列         */
 /* @return 削除した空白の数を返す   */
 int TrimStart(char *s)
 {
    int i = 0;
 
    /* 空ポインタか? */
    if ( s == NULL )
    {
        return -1;
    }
 
    /* 先頭から順に空白でない位置を探す */
    while ( s[i] != '\0' && s[i] == ' ' ) i++;
    strcpy(s, &s[i]);
 
    return i;
 }