第4回文字列操作2(5月12日)

今日のポイント

■ 文字列操作のライブラリ

課題1

文字列操作のライブラリを作ろう.
/*
 * my_string_operation.h
 */

#ifndef _MY_STRING_OPERATION_H_
#define _MY_STRING_OPERATION_H_

#include <stdio.h>

// 標準入力などからの入力を文字列として受け取る
//   第1引数:入力元.標準入力の際 STDIN stdin とする.
//   第2引数:格納先.文字列を格納する場所を指定する.
//   第3引数:サイズ.文字列の格納できる大きさを指定する.この値 - 1
//             以上の長さの入力があるとエラー終了とする.
//   返り値:なし
void mystr_inkey( FILE *, char *, int );

#endif
/*
 * my_string_operation.c
 */

#include "my_string_operation.h"

void mystr_inkey( FILE *fp, char *buff, int sz ){
  ? fp から fgets して,改行文字をカットしたり,特定の長さ以上ならばエ
  ラー終了とする.なお,buff は sz 個の char のぶんだけメモリが確保さ
  れていることを前提にする.
}

■ 文字の検索

課題2

文字列を先頭から1文字ずつ読み,検索キーとなる文字を検出すると,そ の位置を返す関数 mystr_find_char_in_string() を作ろう.もし見つからなければ,- 1 を返すことにする.my_string_operation のライブラリに追加しよう.以下 に C言語のソースファイルの例を示す.ヘッダファイルも適切に作成しよう.
// 第一引数の文字列の中から,第二引数の文字のみつかった最初の位置を返
// す.見付からないときは,-1 を返す.
int mystr_find_char_in_string( char *str, char key ){
  int i;

  i = 0;
  while( str[i] != ???? ){ // 終端文字 \0 になるまでループする.
    if( str[i] ???? ){
      ???? // 見つかったので,場所を返す.
    }
    ???? // i 番目の文字は検査しおわったので,次の文字を検査するために...
  }
  return -1;   // 見つからないとき
}

■ 文字列の検索:strstr

課題3

文字列の中に検索キーとなる文字列を検出すると,その位置を返す関数 mystr_find_str_in_string() を作ろう.もし見つからなければ,-1 を返すことにす る.my_string_operation のライブラリに追加しよう.実装は,strstr を使 う.
int mystr_find_str_in_string( char *str, char *key ){
  char *p;

  p = strstr( str, key );
  if( p == NULL ){
    ???? // 見付からないとき
  }
  return p - str;
}

※ 最後の行の return p - str; は、動作するが、正しい使い方 ではない。 return stelen(str) - strlen(p); とすればよい。

課題4

動作確認をしよう.
/* list0401.c */
#include ??????

#define MAX 10

int main(){
  char *s1, *key1, key2;
  int p1, p2;

  s1 = ???? malloc ???? 大きさMAXの文字列のメモリ確保
  ?? おやくそく
  key1 = ??? malloc ???? 大きさMAXの文字列のメモリ確保
  ?? おやくそく

  mystr_inkey( ???? s1 に文字列をキーボードから入力 )
  mystr_inkey( ???? key1 に文字列をキーボードから入力 )
  key2 = getchar();

  printf("文字列全体:%s\n", s1);
  p1 = mystr_find_str_in_string( ??? s1 から key1 の場所を探す )
  printf("%sは%d文字目から%d文字目\n", key1, p1, p1 + strlen(key1) - 1 );
  p2 = mystr_find_char_in_string( ??? s1 から key2 の場所を探す )
  printf("%cは%d文字目\n", key2, p2);

  return 0;  // プリントでは抜けていました。
}

■ 文字列の結合:strcat

文字列 s1 の後に文字列s2を結合するには,strcat( s1, s2 ); と実行すれ ば良い.ただし,s1 の文字列のメモリ領域に,s2 を含むことができるだけの 大きさが必要である.

しかし,strcat では,s2 の部分文字列を抽出して,結合することはできない.

課題5

文字列 s1 の後に文字列 s2 の p1 文字目から p2 文字目の手前までを結 合する関数mystr_strpcat( s1, s2, p1, p2 ) を作成しよう.s1 にメモリが 十分確保されていることを前提にしてよい.返り値はない.

たとえば,mystr_strpcat( s1, "abcdefghi", 2, 5 ) とすると,s1 の末 尾に "cde" が結合される.
void mystr_strpcat( char *s1, char *s2, int p1, int p2 ){
  int i, k;

  i = 0;
  ? s1 の末尾'\0'を,i が指すようにする.
  for( k = p1; k ??? p2; i += 1, k += 1 ){
    ? s1の i 番目に s2 の k 番目の文字を代入
  }
  ? s1 に終端文字を追加する
}

なお,strncat を使って同等の動作をさせることができる.わかった人は, 上記の for 文を使うのではなく,strncat を使って実現しよう.

□ 宿題(小レポート)

上記の課題を完遂し,次の表示がでるように,prac0401.c を補完せよ.

My name is Toridai Taro.

my_string_operation.h および my_string_operation.c を印刷し,手書 きでコメントを記入して提出せよ.
/* prac0401.c */

#include "my_string_operation.h"
#define MSG "My name is "

int main(){
  char *s1, *s2;
  int p1, p2;

  s1 = "名前は「Toridai Taro」です.";
  p1 = ? Toridai Taro の先頭の文字 T の位置
  p2 = ? Toridai Taro の末尾の文字 o の位置 + 1,すなわち,"」"の位置
  s2 = (char *)malloc(sizeof(char) * (p2 - p1) + strlen( MSG ) + 1);
  strcat( s2, MSG);
  mystr_strpcat( s2, s1, p1, p2 );
  strcat( s2, ".");

  printf("%s\n", s2);
  return 0;
}


(c) Masato TOKUHISA (2006, April, 26.) (2006, May 12)