Index |
||||||||||||||||||||||||||||||||
C++の壺・検索置換篇
C++の基本テクニックのTipsです。C言語の文字列処理は慣れると非常に便利です。検索置換篇では、標準関数を利用した、文字列の検索と置換の方法を扱います。
sasaraan programming ![]() Exposition ●検索とstrstr
文字列の検索は、strstr 関数を利用すると簡単に結果を得ることができます。この関数は、対象文字列の先頭から検索文字列を探し、見つかればその先頭位置へのポインタを、見つからなければ NULL を返します。検索には、終端の NULL 文字は含まれません。
// 文字列の検索
#include <stdio.h> // printf
#include <conio.h> // getch
#include <string.h> // strstr
// main 関数
void main()
{
char src[256] = "They Will Leave for Kyoto on Sunday"; // 対象文字列
char *find = "Kyoto"; // 検索文字列
char *res; // 結果文字列
res = strstr(src, find); // 検索の実行
if (res == NULL) {
printf("Not Found\n");
} else {
printf("%s\n", res); // "Kyoto on Sunday"
}
if (getch()) return;
}
●置換とmemmove
置換は、まず [1]検索 を行い、見つかったら、以降の文字列を必要に応じて [2]移動 し、検索文字列に置換文字列を [3]上書き するという手順になります。[2]の段階で、検索文字列の長さと、置換文字列の長さが異なる場合は、置換場所以降の文字列の移動(シフト)が必要です。
*** 置換A : 文字列が増えるケース ("Kyoto" を "Fukuoka" に置換) ***
// 文字列の置換
#include <stdio.h> // printf
#include <conio.h> // getch
#include <string.h> // strstr, memmove
// main 関数
void main()
{
char src[256] = "They Will Leave for Kyoto on Sunday"; // 対象文字列
char *find = "Kyoto"; // 検索文字列
char *rep = "Fukuoka"; // 置換文字列
int shift =(int)(strlen(rep) - strlen(find)); // = 2 : 文字数の差(シフトさせる値)
// [1]検索実行
char *res; // 結果文字列
res = strstr(src, find); // "Kyoto on Sunday"
if (res != NULL)
{
// [2]文字列のシフト
if (shift > 0) {
memmove(res+shift, res, strlen(res)+1); // 文字列を広げる
} else if (shift < 0) {
memmove(res, res-shift, strlen(res)+shift+1); // 文字列を詰める
}
// [3]置換の実行
memmove(res, rep, strlen(rep));
}
printf("%s\n", src); // "They Will Leave for Fukuoka on Sunday"
if (getch()) return;
}
上記のサンプルでは省いてありますが、実際には、置換後の文字列長がオーバーしないように気を配ることも必要となります。
●すべて置換
文字列内の特定の文字列すべてを一度に置換するには、[1]検索、[2]移動(シフト)、[3]置換 を、検索結果 が NULL になるまでくりかえします。以下にその例を挙げておきます。なお、ここでは置換後の文字列長のチェックは行っていません。
// すべて置換する例
#include <stdio.h> // printf
#include <conio.h> // getch
#include <string.h> // strstr, memmove
// 対象文字列 ('\' は行の連結記号 / 下線は検索文字列)
char src[1024] = "ぼろぼろの身なりにやせ馬。五十石の分際で二人の郎党。"\
"そんな伊右衛門のもとに嫁が来ることに。もと浅井家家来・若宮家の一人娘・千代。"\
"いかにも頼りなげな伊右衛門に対し、千代は美人で賢い上につつましやか。"\
"この時千代は、律儀だけが取柄の伊右衛門を一国一城の主にしようと決意します。";
// main 関数
void main()
{
char *find = "伊右衛門"; // 検索文字列
char *rep = "一豊"; // 置換文字列
size_t find_len = strlen(find); // 検索文字列の長さ = 8
size_t rep_len = strlen(rep); // 置換文字列の長さ = 4
int shift = (int)(rep_len - find_len); // 移動文字(バイト)数 = -4
char *start = src; // 検索開始位置へのポインタ
char *hit; // 見つかった位置へのポインタ
// 検索結果が NULL になるまでループ
while ((hit = strstr(start, find)) != NULL) /* [1]検索 */
{
// [2]シフト
if (shift > 0) {
memmove(hit+shift, hit, strlen(hit)+1); // 拡張
} else if (shift < 0) {
memmove(hit, hit-shift, strlen(hit)+shift+1); // 切詰
}
start = hit + rep_len; // 次の検索開始位置
// [3]置換
memmove(hit, rep, rep_len);
}
printf("%s\n", src); // 出力(下記参照 / 下線は置換文字列)
if (getch()) return;
}
ぼろぼろの身なりにやせ馬。五十石の分際で二人の郎党。 そんな一豊のもとに嫁が来ることに。もと浅井家家来・若宮家の一人娘・千代。 いかにも頼りなげな一豊に対し、千代は美人で賢い上につつましやか。 この時千代は、律儀だけが取柄の一豊を一国一城の主にしようと決意します。 |
||||||||||||||||||||||||||||||||
www.sasaraan.net |
(c) morijoh |
|||||||||||||||||||||||||||||||