特定の文字列と特定の文字列間の文字列削除コードについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ぺーぺー

特定の文字列と特定の文字列間の文字列削除コードについて

#1

投稿記事 by ぺーぺー » 14年前

はじめてこのサイトを利用させていただきます。今特定の文字列と特定の文字列間の文字列削除コードを作っています。例えば" both of japan grrfrbsebs korea great "という文章だったら"both of japan and korea great "
とするようなコードです。また、削除するのはjapanからkoreaの間の文字列のみで、koreaからjapanの間の文字列は削除しません。またjapanとkoreaの文字列は交互に並んでいるとします。
このような処理をするコードで、japanとkoreaの文字列が一つずつしかないような時にしか対応できないコードは作ることができました。しかし複数マッチに対応するコードがどうもうまくいきません。今のところ下のようなコードになっているのですが、output.txtに出力される内容はinput.txtと全く同じ内容になってしまっている状況です。
input.txtは"japan somesome korea friends japan somesomerr korea friends japan somesomerw korea friends japan"とします。
今まで様々の方に質問してきたのですが、解決できず困っていました。みなさんにご協力いただきたいです。よろしくお願いします。

コード:

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void chop_crlf(char* buf);
char* FindAndDeleteString(char* buf, char* head, char* tail);
FILE *fp;
const char* ifile = "input.txt";
#define HEAD	"japan"
#define TAIL	"korea"
char *p,buf[5040]; 
   
	

 
int main(int argc, char* argv[])
{
   
    
 FILE *hp = fopen("output.txt","w");
if ( hp == NULL ){
fprintf(stderr,"cannot output to file.\n");}
    
     
    if ( ( fp = fopen(ifile,"r") ) == NULL ) {
        fprintf(stderr,"%s: no such file or directory.\n", ifile);
        return -1;
    }
 
    
    // 文字列の検索(文字列の置換)
    rewind(fp);
    while ( fgets(buf,5040,fp) ) {
        chop_crlf(buf);
         
        p = FindAndDeleteString(buf,(char*)HEAD,(char*)TAIL);
        
       fprintf(hp,"%s\n",p);
        if ( p != buf ) free(p);
    }
  
    fclose(fp);
    fclose(hp);  
    return 0;
}
 
char* FindAndDeleteString(char* buf, char* head, char* tail)
{
char *newstring,*sp,*oldsp,*check;
oldsp = buf;
sp = strstr(buf,head)+strlen(head);
if ( strstr(buf,head) == NULL && strstr(buf,tail) == NULL ) return buf;
newstring = (char*)calloc(sizeof(char),strlen(buf));

while((check = strstr(sp,head)) != NULL){
strncpy(newstring+strlen(newstring),oldsp,sp-oldsp);
oldsp = strstr(sp,tail);
sp = strstr(oldsp,head)+strlen(head);
}
strncpy(newstring+strlen(newstring),oldsp,sp - oldsp);
return newstring;
}
// 改行コードの除去
void chop_crlf(char* buf)
{
    for ( unsigned i=0; i<strlen(buf); i++ ) {
        if ( buf[i] == '\r' || buf[i] == '\n' ) buf[i] = 0;
    }
}
 

フリオ

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#2

投稿記事 by フリオ » 14年前

 
 とりあえず、気なったことだけを、

>例えば" both of japan grrfrbsebs korea great "という文章だったら"both of japan and korea great "
 この、" and " は何処から出てきたのでしょうか。

>削除するのはjapanからkoreaの間の文字列のみで
 ということは、"japanese somesome korean" だと、"japankorean" になるのでしょうか。
 

フリオ

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#3

投稿記事 by フリオ » 14年前

 
 それから、FindAndDeleteString 関数は、
calloc を使うことも含めて、仕様が決まっているのでしょうか。
 

ペーペー

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#4

投稿記事 by ペーペー » 14年前

フリオ さんが書きました: 
 とりあえず、気なったことだけを、

>例えば" both of japan grrfrbsebs korea great "という文章だったら"both of japan and korea great "
 この、" and " は何処から出てきたのでしょうか。

解答ありがとうございます。このandは完全に私のミスです。"both of japan korea great "となればokでjapanとkoreaの間の文字列は完全に削除するということが目的です

>削除するのはjapanからkoreaの間の文字列のみで
 ということは、"japanese somesome korean" だと、"japankorean" になるのでしょうか。

そういう事になります。よろしくお願いします。

 

ぺーぺー

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#5

投稿記事 by ぺーぺー » 14年前

フリオ さんが書きました: 
 それから、FindAndDeleteString 関数は、
calloc を使うことも含めて、仕様が決まっているのでしょうか。

当方C言語ペーペーのものですので、「関数の仕様がきまる」という事がどういう事かわからないのですが、ある友達からは、このcallocの部分はいらない、もしくは間違っていると言われました。
 

box
記事: 2002
登録日時: 14年前

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#6

投稿記事 by box » 14年前

ペーペー さんが書きました: 解答ありがとうございます。このandは完全に私のミスです。"both of japan korea great "となればokでjapanとkoreaの間の文字列は完全に削除するということが目的です
ここと、
ペーペー さんが書きました: "japanese somesome korean" だと、"japankorean" になるのでしょうか。
こことで食い違いがあることに気づいていますか?

japanとkoreaの間の文字列を完全に削除する、という内容は、
japanとkoreaとの間に空白を付ける/付けないのどちらでしょうか?
ここが、まさに関数の「仕様(の一部)」です。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

ぺーぺー

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#7

投稿記事 by ぺーぺー » 14年前

box さんが書きました:
ペーペー さんが書きました: 解答ありがとうございます。このandは完全に私のミスです。"both of japan korea great "となればokでjapanとkoreaの間の文字列は完全に削除するということが目的です
ここと、
ペーペー さんが書きました: "japanese somesome korean" だと、"japankorean" になるのでしょうか。
こことで食い違いがあることに気づいていますか?

japanとkoreaの間の文字列を完全に削除する、という内容は、
japanとkoreaとの間に空白を付ける/付けないのどちらでしょうか?
ここが、まさに関数の「仕様(の一部)」です。
返信ありがとうございます。
なるほど・・・ そういう事ですか、了解です。japanとkoreaの間は空白はつけません。
なんだか色々と情報が足りなくて申し訳ないです・・・

non
記事: 1097
登録日時: 14年前

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#8

投稿記事 by non » 14年前

もしかしたら、想定が甘いかも知れませんが、こんなんではいかがでしょう。
変数をグローバルにするなら、引数を渡したり、値を返す必要はないのですが。

コード:

char* FindAndDeleteString(char* buf, char* head, char* tail)
{
	char *p,*q,*r;
	r=buf;
	while(1){
		p=strstr(r,head);
		q=strstr(p,tail);
		if(p==NULL || q==NULL)
			break;
		p+=strlen(head);
		r=p+strlen(tail);
		while(*q!='\0')
			*p++=*q++;
		*p='\0';
	}
	return buf;
}
non

ペーペー

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#9

投稿記事 by ペーペー » 14年前

non さんが書きました:もしかしたら、想定が甘いかも知れませんが、こんなんではいかがでしょう。
変数をグローバルにするなら、引数を渡したり、値を返す必要はないのですが。

コード:

char* FindAndDeleteString(char* buf, char* head, char* tail)
{
	char *p,*q,*r;
	r=buf;
	while(1){
		p=strstr(r,head);
		q=strstr(p,tail);
		if(p==NULL || q==NULL)
			break;
		p+=strlen(head);
		r=p+strlen(tail);
		while(*q!='\0')
			*p++=*q++;
		*p='\0';
	}
	return buf;
}
ハッカーさん返信ありがとうございます。実際にコードをこちらでコンパイルさせていただいたのですが、最初のjapanとkoreaの間の文字列は削除されているのですが、それ以降のjapanとkoreaの間の文字列の削除が行われていません・・・ ハッカーさんの環境ではちゃんと動作しているのでしょうか??

naohiro19
記事: 256
登録日時: 14年前
住所: 愛知県

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#10

投稿記事 by naohiro19 » 14年前

ぺーぺーさんがNo.4で満たすコードを.NET FrameworkのC#で書くと以下のようになります。

コード:

using System;
class RemoveTest
{
    public static void Main(string[] argv)
    {
        string str = "both of japan grrfrbsebs korea great";
        string str2 = "";
        Console.WriteLine("削除前の文字列: {0}", str);
        string removeText = "grrfrbsebs"; //削除する文字列
        
        //文字列を検索
        int cnt = str.IndexOf(removeText,removeText.Length);
        
        //文字列が見つからなかった
        if( cnt == -1)
        {
            Console.WriteLine("指定した文字列は見つかりませんでした");
        }

        //見つかったら削除
        str2 = str.Remove(cnt,removeText.Length);
        Console.WriteLine("削除後の文字列:{0}", str2);           
    }
}

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#11

投稿記事 by ISLe » 14年前

サンプルコード書いてみました。
バッファの文字列を書き換えます。

コード:

#include <stdio.h>
#include <string.h>
int main(void)
{
	char buf[] = "japan somesome korea friends japan somesomerr korea friends japan somesomerw korea friends japan";
	const char *ja = "japan";
	const char *kr = "korea";
	char *top, *end, *p;

	top = end = buf;
	while (top = strstr(top, ja)) {
		top += strlen(ja);

		end = strstr(top, kr);
		if (end == NULL) break;

		p = top;
		while (*(p++) = *(end++));
	}
	printf("%s\n", buf);
	return 0;
}

non
記事: 1097
登録日時: 14年前

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#12

投稿記事 by non » 14年前

ペーペー さんが書きました:ハッカーさん返信ありがとうございます。実際にコードをこちらでコンパイルさせていただいたのですが、最初のjapanとkoreaの間の文字列は削除されているのですが、それ以降のjapanとkoreaの間の文字列の削除が行われていません・・・ ハッカーさんの環境ではちゃんと動作しているのでしょうか??
ハンドルはハッカーさんではないのですが・・・・nonです。
私の環境ではうまくいきます。VC++2008です。環境に影響しないように作ったつもりでしたが。strcpyは環境に影響すると思ったので使ってないし。
参考までにmainを含めた、全文です。なお、出力はstdoutにしています。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void chop_crlf(char* buf);
char* FindAndDeleteString(char* buf, char* head, char* tail);
FILE *fp;
const char* ifile = "input.txt";
#define HEAD    "japan"
#define TAIL    "korea"
char *p,buf[5040]; 




int main(int argc, char* argv[])
{


	FILE *hp = fopen("output.txt","w");
	if ( hp == NULL ){
		fprintf(stderr,"cannot output to file.\n");}


	if ( ( fp = fopen(ifile,"r") ) == NULL ) {
		fprintf(stderr,"%s: no such file or directory.\n", ifile);
		return -1;
	}


	// 文字列の検索(文字列の置換)
	rewind(fp);
	while ( fgets(buf,5040,fp) ) {
		chop_crlf(buf);

		p = FindAndDeleteString(buf,(char*)HEAD,(char*)TAIL);

		fprintf(stdout,"%s\n",p);
	}

	fclose(fp);
	fclose(hp);  
	return 0;
}

char* FindAndDeleteString(char* buf, char* head, char* tail)
{
    char *p,*q,*r;
    r=buf;
    while(1){
        p=strstr(r,head);
        q=strstr(p,tail);
        if(p==NULL || q==NULL)
            break;
        p+=strlen(head);
        r=p+strlen(tail);
        while(*q!='\0')
            *p++=*q++;
        *p='\0';
    }
    return buf;
}
// 改行コードの除去
void chop_crlf(char* buf)
{
	for ( unsigned i=0; i<strlen(buf); i++ ) {
		if ( buf[i] == '\r' || buf[i] == '\n' ) buf[i] = 0;
	}
}
non

ぺーぺー

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#13

投稿記事 by ぺーぺー » 14年前

naohiro19 さんが書きました:ぺーぺーさんがNo.4で満たすコードを.NET FrameworkのC#で書くと以下のようになります。

コード:

using System;
class RemoveTest
{
    public static void Main(string[] argv)
    {
        string str = "both of japan grrfrbsebs korea great";
        string str2 = "";
        Console.WriteLine("削除前の文字列: {0}", str);
        string removeText = "grrfrbsebs"; //削除する文字列
        
        //文字列を検索
        int cnt = str.IndexOf(removeText,removeText.Length);
        
        //文字列が見つからなかった
        if( cnt == -1)
        {
            Console.WriteLine("指定した文字列は見つかりませんでした");
        }

        //見つかったら削除
        str2 = str.Remove(cnt,removeText.Length);
        Console.WriteLine("削除後の文字列:{0}", str2);           
    }
}
返信ありがとうございます。ペーペーです。当方初心者のため.NET FrameworkのC#というものがよくわかりません・・・
コードは保存させていただきました。ありがとうございました。

ぺーぺー

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#14

投稿記事 by ぺーぺー » 14年前

ISLe さんが書きました:サンプルコード書いてみました。
バッファの文字列を書き換えます。

コード:

#include <stdio.h>
#include <string.h>
int main(void)
{
	char buf[] = "japan somesome korea friends japan somesomerr korea friends japan somesomerw korea friends japan";
	const char *ja = "japan";
	const char *kr = "korea";
	char *top, *end, *p;

	top = end = buf;
	while (top = strstr(top, ja)) {
		top += strlen(ja);

		end = strstr(top, kr);
		if (end == NULL) break;

		p = top;
		while (*(p++) = *(end++));
	}
	printf("%s\n", buf);
	return 0;
}
ISLeさん、返信ありがとうございます。こちらの環境でもきちんと動き、目的にあった動作をしてくれました。まだコードの内容をよく理解できていないのですが、がんばって勉強したいと思います。ありがとうございました。

ぺーぺー

Re: 特定の文字列と特定の文字列間の文字列削除コードについて

#15

投稿記事 by ぺーぺー » 14年前

non さんが書きました:
ペーペー さんが書きました:ハッカーさん返信ありがとうございます。実際にコードをこちらでコンパイルさせていただいたのですが、最初のjapanとkoreaの間の文字列は削除されているのですが、それ以降のjapanとkoreaの間の文字列の削除が行われていません・・・ ハッカーさんの環境ではちゃんと動作しているのでしょうか??
ハンドルはハッカーさんではないのですが・・・・nonです。
私の環境ではうまくいきます。VC++2008です。環境に影響しないように作ったつもりでしたが。strcpyは環境に影響すると思ったので使ってないし。
参考までにmainを含めた、全文です。なお、出力はstdoutにしています。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void chop_crlf(char* buf);
char* FindAndDeleteString(char* buf, char* head, char* tail);
FILE *fp;
const char* ifile = "input.txt";
#define HEAD    "japan"
#define TAIL    "korea"
char *p,buf[5040]; 




int main(int argc, char* argv[])
{


	FILE *hp = fopen("output.txt","w");
	if ( hp == NULL ){
		fprintf(stderr,"cannot output to file.\n");}


	if ( ( fp = fopen(ifile,"r") ) == NULL ) {
		fprintf(stderr,"%s: no such file or directory.\n", ifile);
		return -1;
	}


	// 文字列の検索(文字列の置換)
	rewind(fp);
	while ( fgets(buf,5040,fp) ) {
		chop_crlf(buf);

		p = FindAndDeleteString(buf,(char*)HEAD,(char*)TAIL);

		fprintf(stdout,"%s\n",p);
	}

	fclose(fp);
	fclose(hp);  
	return 0;
}

char* FindAndDeleteString(char* buf, char* head, char* tail)
{
    char *p,*q,*r;
    r=buf;
    while(1){
        p=strstr(r,head);
        q=strstr(p,tail);
        if(p==NULL || q==NULL)
            break;
        p+=strlen(head);
        r=p+strlen(tail);
        while(*q!='\0')
            *p++=*q++;
        *p='\0';
    }
    return buf;
}
// 改行コードの除去
void chop_crlf(char* buf)
{
	for ( unsigned i=0; i<strlen(buf); i++ ) {
		if ( buf[i] == '\r' || buf[i] == '\n' ) buf[i] = 0;
	}
}
nonさん、返信ありがとうございます。申し訳ございません・・・名前欄でないところを見てしまっていました。こちらの環境で動かしたところ、今回はちゃんと目的にあった動作もしてくれてファイル出力もしてくれました。おそらく最初に教えていただいたコードを私がうまく使えてなかったと思われます。わざわざコード全文を載せていただき助かりました。これで問題解決となりました。本当にありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る