C言語関係掲示板

過去ログ

No.437.文字列検索

[戻る] [ホームページ]
No.3089

文字列検索
投稿者---シスコ(2002/10/23 23:27:00)


こんにちは。

文字列検索プログラムを作ろうと、関数を作って
いるのですが、上手くいきません。
コンパイルはエラーが出ないのですが、実効する
とWindowsがおかしくなります。

自分では自身満々なのですが…

関数の仕様としては、ある文字列Aから、ある文字列B
を検索し、見つかるとその文字列までの文字をかえす。
見つからないときはNULLをかえす。です。


#include<stdio.h>
#include<string.h>

char *sstrn(const char *original, const char *target);

int main(void)
{
	char target[256] = "POSITION=";
	char line[256] = "U 1420 10 15 0 9 3 POSITION=12";
	

	if((sstrn(line, target)) != NULL)
		printf("find\n");
	else
		printf("not found\n");
	
	return(0);	
}

char *sstrn(const char *original, const char *target)
{
	int o_len, t_len;
	int i;
	char *return_str;
	
	o_len = strlen(original);
	t_len = strlen(target);
	
	for(i = 0; i <= o_len - t_len; i++){
		
		if(strncmp((original + i), target, t_len) == 0){
			strncpy(return_str, original, i + t_len);
			*(return_str + i + t_len) = '\0';
			return(return_str);
		}
	}
	
	return(NULL);
}


No.3098

Re:文字列検索
投稿者---TDa(2002/10/24 07:42:14)


strncpy(return_str,&nbsp;original,&nbsp;i&nbsp;+&nbsp;t_len);
この部分、retrun_strの領域が確保されていません。

No.3101

Re:文字列検索
投稿者---TDa(2002/10/24 10:33:31)


コピペしたら訳わかんなくなりました。

元のコードを生かせばこんな感じになるんでしょうか。

#include<stdio.h>
#include<string.h>

char *sstrn(const char *original, const char *target, char *buf)
{
	int o_len, t_len;
	int i;
	char *return_str = buf;
	
	o_len = strlen(original);
	t_len = strlen(target);
	
	for(i = 0; i <= o_len - t_len; i++){
		
		if(strncmp((original + i), target, t_len) == 0){
			strncpy(return_str, original, i + t_len);
			*(return_str + i + t_len) = '\0';
			return(return_str);
		}
	}
	
	return(NULL);
}

int main(void)
{
	char target[256] = "POSITION=";
	char line[256] = "U 1420 10 15 0 9 3 POSITION=12";
	char buf[256];
    sstrn(line, target, buf)
	
	return(0);	
}


でもbufには(NULLか)originalの文字列が入りますけど余り意味がないんじゃないかと思います。strstrみたいに見つかった文字列の先頭を指すポインタを返す方が有用じゃないですか。

No.3128

Re:文字列検索
投稿者---シスコ(2002/10/24 22:59:21)


TDaさん。こんばんわ。

返信ありがとうございます。
早速試してみた結果上手くいきました。

しかし、すこし疑問が残ります。

私のソースで、
retrun_strの領域が確保されていないとの
事でしたので、配列(char retrun_str[256];)
のように宣言してみましたが、上手くいき
ませんでした。うーん、わかりません。

また、
>strstrみたいに見つかった文字列の先頭を指すポインタを返す方が有用
とのことですが、その場合"U 1420 10 15 0 9 3 POSITION="を取得する
方法はあるのでしょうか?
ちなみに、strstr知りませんでした。
私の呼んでいる参考書(入門編)には、記載されていなかったので
Webで調べました。よのなか便利な標準関数があるのですね。

お手数をおかけして、大変恐縮ですが、ご返事ください。

No.3143

Re:文字列検索
投稿者---TDa(2002/10/25 18:11:27)


retrun_strの領域が確保されていないとの
事でしたので、配列(char retrun_str[256];)
のように宣言してみましたが、上手くいき
ませんでした。

もし
char *sstrn(const char *original, const char *target)
{
char return_str[256];
・・・・

return return_str;
}

という風にやってしまったのならだめです。あなたが何を返したのかよく考えてみてください。
return_strは関数sstrn()内で宣言した自動変数です。よってこの関数を抜けるときこの変数の
領域は開放されます。戻された返り値は不正なポインタとなります。これを回避する手っ取り早い方
法はreturn_strを自動変数でなく静的変数にすることです。static char return_str[256];と宣言
すればいいのです。


>>strstrみたいに見つかった文字列の先頭を指すポインタを返す方が有用
>とのことですが、その場合"U 1420 10 15 0 9 3 POSITION="を取得する
>方法はあるのでしょうか?
だってoriginalがそうですよね。上記の関数を下のように書き換えました。
何が返されているかわかりますよね。originalの中でtargetと一致する先頭を指すポインタが返ります。

#include<stdio.h>
#include<string.h>

char *sstrn(const char *original, const char *target)
{
	int o_len, t_len;
	int i;
	char *return_position;
	
	o_len = strlen(original);
	t_len = strlen(target);
	
	for(i = 0; i <= o_len - t_len; i++){
		
		if(strncmp((original + i), target, t_len) == 0){
			return_position = original + i;
			return return_position;
		}
	}
	
	return NULL;
}

int main(void)
{
	char target[256] = "POSITION=";
	char line[256] = "U 1420 10 15 0 9 3 POSITION=12";
	char *pos;
    
    pos = sstrn(line, target);
	
    printf("%s\n", pos);
    
	return(0);	
}


No.3146

Re:文字列検索
投稿者---シスコ(2002/10/25 20:16:11)


TDaさん。こんにちわ。

再び返信ありがとうございます。

return_strを静的変数(static)にすることで上手くいきました。
すごくわかりやすい説明で、理解することができました。
ポインタって難しいですね。
頭の中で「わかった」⇒「やっぱわからない』を繰り返しています。
(今は理解しているつもりですが)

また、現在は先にご掲示いただいたプログラム
「U 1420 10 15 0 9 3 POSITION=12」のなかから
「POSITION=12」を取得するで良いのですが、
最終的には、「U 1420 10 15 0 9 3 POSITION=」
が取得できれば良いと考えていましたので、
前回のレスでstrstrについて追加質問させていただきました。