ページ 1 / 1
特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月01日(日) 02:17
by ぺーぺー
はじめてこのサイトを利用させていただきます。今特定の文字列と特定の文字列間の文字列削除コードを作っています。例えば" 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: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月01日(日) 04:13
by フリオ
とりあえず、気なったことだけを、
>例えば" both of japan grrfrbsebs korea great "という文章だったら"both of japan and korea great "
この、" and " は何処から出てきたのでしょうか。
>削除するのはjapanからkoreaの間の文字列のみで
ということは、"japanese somesome korean" だと、"japankorean" になるのでしょうか。
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月01日(日) 04:28
by フリオ
それから、FindAndDeleteString 関数は、
calloc を使うことも含めて、仕様が決まっているのでしょうか。
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月01日(日) 10:39
by ペーペー
フリオ さんが書きました:
とりあえず、気なったことだけを、
>例えば" 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: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月01日(日) 10:42
by ぺーぺー
フリオ さんが書きました:
それから、FindAndDeleteString 関数は、
calloc を使うことも含めて、仕様が決まっているのでしょうか。
当方C言語ペーペーのものですので、「関数の仕様がきまる」という事がどういう事かわからないのですが、ある友達からは、このcallocの部分はいらない、もしくは間違っていると言われました。
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月01日(日) 18:15
by box
ペーペー さんが書きました:
解答ありがとうございます。このandは完全に私のミスです。"both of japan korea great "となればokでjapanとkoreaの間の文字列は完全に削除するということが目的です
ここと、
ペーペー さんが書きました:
"japanese somesome korean" だと、"japankorean" になるのでしょうか。
こことで食い違いがあることに気づいていますか?
japanとkoreaの間の文字列を完全に削除する、という内容は、
japanとkoreaとの間に空白を付ける/付けないのどちらでしょうか?
ここが、まさに関数の「仕様(の一部)」です。
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月02日(月) 11:02
by ぺーぺー
box さんが書きました:ペーペー さんが書きました:
解答ありがとうございます。このandは完全に私のミスです。"both of japan korea great "となればokでjapanとkoreaの間の文字列は完全に削除するということが目的です
ここと、
ペーペー さんが書きました:
"japanese somesome korean" だと、"japankorean" になるのでしょうか。
こことで食い違いがあることに気づいていますか?
japanとkoreaの間の文字列を完全に削除する、という内容は、
japanとkoreaとの間に空白を付ける/付けないのどちらでしょうか?
ここが、まさに関数の「仕様(の一部)」です。
返信ありがとうございます。
なるほど・・・ そういう事ですか、了解です。japanとkoreaの間は空白はつけません。
なんだか色々と情報が足りなくて申し訳ないです・・・
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月02日(月) 15:16
by 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;
}
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月03日(火) 12:15
by ペーペー
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の間の文字列の削除が行われていません・・・ ハッカーさんの環境ではちゃんと動作しているのでしょうか??
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月03日(火) 15:05
by 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);
}
}
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月03日(火) 17:14
by 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;
}
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月04日(水) 19:52
by 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;
}
}
Re: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月04日(水) 23:35
by ぺーぺー
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: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月04日(水) 23:39
by ぺーぺー
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: 特定の文字列と特定の文字列間の文字列削除コードについて
Posted: 2011年5月04日(水) 23:43
by ぺーぺー
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さん、返信ありがとうございます。申し訳ございません・・・名前欄でないところを見てしまっていました。こちらの環境で動かしたところ、今回はちゃんと目的にあった動作もしてくれてファイル出力もしてくれました。おそらく最初に教えていただいたコードを私がうまく使えてなかったと思われます。わざわざコード全文を載せていただき助かりました。これで問題解決となりました。本当にありがとうございました。