C言語を趣味で勉強しているものです。
半角英数のテキストファイルhogeから文字列を検索して削除したいのですが、どのように記述してよいか分かりません。参考になるサイト等ありましたら教えていただけないでしょうか?
例えば
テキストファイル
1
2
3
からiitennkiを検索・削除して
テキストファイル hoge
1
2
3
と変更したいと思っております。
コメント

- 3:ゲスト ((質問者))
- 2008/07/10 19:13
>1:mikeda様
回答ありがとうございます。
具体的なコードを示していただき、初心者としては大変ありがたいです。
いろいろいじってみて目的の処理ができるように頑張りたいと思います!
参考サイトも教えていただきありがとうございました。
>2:ゲスト様
回答ありがとうございます。
質問が不十分でした、複数回見つかる可能性も考えなければなりません・・・
検索してみたところ、以下のようなサイトが参考になりそうです。
http://www.sip.eee.yamaguchi-u.ac.jp/kou/regex.html
http://sometime.minidns.net/~ccgi/posix_reglib.html
自分にとってはかなり難しいですが、なんとか頑張って理解しようと思います。

- 4:mikeda
- 2008/07/10 21:32
>
あw
そのへんふまえてループなり再帰なりで関数外出しすればけっこうすっきり書けそうですね。
Cの正規表現って使ったことないです。思ったほどはめんどくさくなさそう。また試してみます!
>
入出力はファイル、ってのも無視だし、変数名とか関数の使い方とか、テキトーで申し訳ないです。
それにポインタ演算とかちょっと理解しずらいかもです。もう少し簡単に書ければいいんですが。
紹介サイト、参考になりました。困ったことがあればなんでも。がんばってください。

- 6:ゲスト
- 2008/07/11 04:39
5>substrとindexofでやれば、と思ったけどC言語にはなかったんだっけ・・・
C言語にはないですね。
こういう処理をするなら、特にC言語にこだわりがないなら、
Perl
(C++でもいいけど)

- 7:ゲスト (質問者)
- 2008/07/11 20:43
すみません、一応いろいろやってはみたのですが、入門書を終えただけの私にはどうしても解決できませんでした。
テキストファイルhoge.txtは以下のようになっています
kyouhaiitennki
ashitahaiitennkiiitennki
sonouthihareruyo
iitennki
sorenisshitemoiitennki
KKKKKKKKKKKK
iitennki
これを、最終的には
kyouha
ashitaha
sonouthihareruyo
sorenisshitemo
KKKKKKKKKKKK
としたいと思っています。
[code]
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
intmain(){
FILE *fp;
char str[256]; // ファイルの1行分
char *temp;
int i=0;
char *fname = "hoge.txt";
char *del_string = "iitennki";
if((fp = fopen(fname,"r+")) == NULL){ // 開いて、結果のチェック
printf("file open error!!\n");
exit(EXIT_FAILURE); // 開けないなら異常終了
}else{
while(fgets(str,256,fp) != NULL){
char *s = strstr(str, del_string);
/* 見つからなかったら一行出力して次の行へ */
if(s == NULL){
fputs(str,fp);
continue;
}
/* 一文字ずつファイルに書き込む */
while(str != s){
fputc(str,fp);
}
/* 消す文字の分だけsを進める */
s += strlen(del_string);
fprintf(fp,"%s\n",s);
}
}
fclose(fp);
return(0);
}
[/code]
本当に幼稚なレベルで申し訳ないのですが、何かアドバイスをいただけないでしょうかm(_

- 9:mikeda
- 2008/07/11 23:57
プログラムは一気に書かずにちょっとずつ動作を確認しながら書きましょう。そっちのほうが絶対早いですよ。
まず読込みファイルと書き込みファイルは別にしましょう。FILEにはファイル中での現在の位置等含まれています。読み書き同時は厳しいです。
あと文字列からファイルに1文字ずつ書き込む処理では、文字列の中を1つずつ進んでいかなくてはいけません。私のプログラムでputchar(*c++);となっている++の部分です。
それにからめて、(ちょっと難しいので無理に理解しようとしないでください。説明もいい加減です。絶対だれかに怒られる・・・)
char
ではpはcharへのポインタになるのですが
char
ではstrは配列になるので1を足す意味が違ってしまいます。
1文字ずつ進めるにはcharのポインタじゃないといけないのでstrではなくchar

- 10:mikeda
- 2008/07/12 00:05
で、自分で書いておいてなんですが、1文字ずつ進めるより以下の方が簡単かもしれません。
//strに1行読み込み
fgets(str,256,in_fp);
//検索して見つかった先頭位置をsに
char*s = strstr(str, del_string);
//sの部分を¥0にする。
*s='\0';
//¥0は文字列の終わりと見なされるのでとりあえずそこまで出力
fprintf(out_fp,"%s", str);
//sを削除文字の文字数ぶん進めて
s+= strlen(del_string);
//残りの部分を出力
fputs(s,out_fp);
どっちもどっちでしょうか。

- 11:ゲスト (暇人)
- 2008/07/12 02:43
>prog
#include
<stdio.h>
#include<stdlib.h>
#include<string.h>
//指定された位置から指定サイズを取り除く
char*strdel(char *s, size_t len){
size_t i=0;
while(s[i]=s[i+len])
i++;
return (s);
}
intmain(){
FILE *fi,*fo;
char str[256]; //1行分
char *temp;
int del_size;
//const char *fname = "hoge.txt";
const char *del_string = "iitennki";
del_size=strlen(del_string);
fi=stdin;
fo=stdout;
while(fgets(str, 256, fi) != NULL){
char *s=str;
while(s=strstr(s, del_string)){
strdel(s, del_size);
}
if(strlen(str)>1){//改行だけになってしまったら削除する(入力ファイルに改行のみのデータは無いと仮定)
fputs(str, fo);
}
}
return 0;
}

- 12:ゲスト (質問者)
- 2008/07/12 20:04
>9:mikeda様
回答ありがとうございます。
ポインタについて、詳しく書いてある本を買ってきて少し勉強しました。これからしっかり理解できるよう努力します。それと、mikeda様のアドバイスを参考に、何とかhoge.txtから指定文字列を取り除くプログラムが出来ました!
と言っても、正直試行錯誤していたら、たまたまうまくいったという感じなのですが・・・
これから複数回を取り除く処理を考えて、すっきりとしたコードになるように頑張ります。
大変親切に回答していただき、本当にありがとうございました!!
>11:ゲスト(暇人)様
回答ありがとうございます。
なるほど、そのように関数を作ればすっきり書けるのですね!
まずは今の方針で、なんとかきれいなソースになるようにしてみようと思います。その後で、ゲスト(暇人)様が書いてくださったものと比べてどこがどう違うのか見てみたいと思います。
とてもいい勉強になりましたm(_

- 14:ゲスト (暇人)
- 2008/07/14 03:48
12>まずは今の方針で
一文字ずつ出力する方針だと、
指定した文字を削除(出力をスキップ)したために改行だけになった場合、
改行を出力しない、というのが面倒な気がします。

- 15:kumazo
- 2008/07/14 22:16
もう終わってますが・・・
バッファ操作の課題ではありませんか?
せっかくC言語を勉強しているのだから、
メモリ上を"歩く"経験も積んでおいたほうがいいですよ。
コンピュータへの理解が深まります。
今のうちに、時間がかかっても、ちゃんとフローチャートや状態遷移図をかいて、
自分のアタマで考えることをお勧めします。
ということでポインタを使ったアタマの体操。
char
* strremove(char *strbuff, char *ngword) {
char *read_pos = strbuff; /* read */
char *write_pos = strbuff; /* write */
char *comp_pos = ngword; /* compare */
char *anch_pos = NULL; /* anchor */
while ( *read_pos != '\0' ) {
if (anch_pos == NULL) {
if ( *read_pos == *comp_pos ) {
anch_pos = write_pos;
comp_pos ++;
}
}
else {
if ( *comp_pos == '\0' ) {
write_pos = anch_pos;
anch_pos = NULL:
comp_pos = ngword;
}
else if ( *read_pos != *comp_pos ) {
anch_pos = NULL:
comp_pos = ngword;
}
else {
comp_pos ++;
}
}
*write_pos = *read_pos;
write_pos ++ ;
read_pos ++;
}
write_pos = '\0';
return strbuff;
}
コンパイラに通してないので、動かなかったらごめんなさい。

- 16:ゲスト (暇人)
- 2008/07/19 07:08
VB系のReplace
書き直してみた。
//delstr.exe <hoge.txt >result.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
int replace(被置換文字列を含む文字列, 検索文字列, 置換文字列, 検索開始位置, 置換回数, 大文字小文字を同一視, 出力領域)
返値は、置き換えた回数
*/
int replace(const char *s, const char *find, const char *rep, size_t pos, int count, int ignore, char *buff){
size_t i, len_f, len_r;
int rep_count=0;
int (*cmp)(const char*, const char*, size_t);
cmp = (ignore) ? strnicmp : strncmp;
len_f = strlen(find);
len_r = strlen(rep);
for(i=0;i<pos;i++)//検索開始位置まで出力
*buff++ = *s++;
while(rep_count != count){
if(cmp(s, find, len_f)){ //一致しない
*buff++ = *s++;
} else { //一致した
// strncpy(buff, rep, len_r);
// buff += len_r;
for(i=0;i<len_r;i++)
*buff++ = rep[i];
s += len_f;
rep_count++;
}
if(*s=='\0')//文字列終了
break;
}
while(*s){ //文字列が残っている場合出力
*buff++ = *s++;
}
*buff = '\0';
return rep_count;
}
int main(){
FILE *fi,*fo;
char str[256]; //1行分
char buf[256]; //出力作業用領域
const char *del_string = "iitennki";
const char *rep_string = "";
fi=stdin;
fo=stdout;
while(fgets(str, 256, fi) != NULL){
if(replace(str, del_string, rep_string, 0, -1, 0, buf)){ //一致したものを全部削除する
if(*buf!='\n'){ //改行だけになってしまったら削除する
fputs(buf, fo);
}
} else {//置き換えがなかったらそのまま出力
fputs(str, fo);
}
}
return 0;
}

- 17:ゲスト
- 2008/07/28 22:01
#include<stdio.h>
#include<string.h>
#define
#define
void
int
{
}
void
{
}
前へ 1 次へ![]()
コメントする
[block]から[/block]までの範囲はブロック表示されます。
部分的に目立たせたい時や、引用などにお使いください。
[code]から[/code]までの範囲は等幅表示されます。
ソースコードや設定ファイルの記述などにお使いください。




















いきなりコード乗せちゃうのもなんですが調べがてらつい・・・
参考にしたサイトはこちらです。
http://www9.plala.or.jp/sgwr-t/lib/lib.html
かなりムリヤリ><
もっときれいなのだれかお願い。