質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

Q&A

4回答

6788閲覧

C言語 ファイルからの文字列検索の後の文字列置換

soromon

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

0グッド

0クリップ

投稿2016/07/07 03:33

編集2022/01/12 10:55

###前提・実現したいこと
お世話になっています。
C言語でファイルを読み込んだ後、文字を検索後その文字を置換し新しいファイルを作るプログラムを作っています
現在3列目を検索し置換しようとしています。

###発生している問題・エラーメッセージ

ATOM 166 HO2' G 5 1.286 42.680 32.880 1.00 0.00 H ATOM 167 G34' G 5 2.363 44.078 32.398 1.00 0.00 H ```エラーメッセージ 置換されていない。

###C言語
#include <stdio.h>
#include <string.h>

const int BUFSIZE = 512;
const int PATH_MAX = 4016;
const char *permute_str(const char *source, const char *target, const char *replace, int column);

int main(void)
{
FILE *fp_in, *fp_out;
char fname_in[PATH_MAX], fname_out[PATH_MAX];
char buf[BUFSIZE], target[BUFSIZE], replace[BUFSIZE];
printf("検索されるファイル名 : ");
scanf("%s", fname_in);
printf("出力先のファイル名 : ");
scanf("%s", fname_out);
printf("置換前の文字列 : ");
scanf("%s", target);
printf("置換後の文字列 : ");
scanf("%s", replace);

if ((fp_in = fopen(fname_in, "r")) == NULL) { printf("ファイル %s が見つかりません\n", fname_in); return 0;

}

fp_out = fopen(fname_out, "w"); while (fgets(buf, BUFSIZE, fp_in) != NULL) { const char *res = permute_str(buf, target, replace, 3); fprintf(fp_out, "%s", res); } fclose(fp_in); fclose(fp_out); return 0;

const char *permute_str(const char *source, const char *target, const char *replace, int column)
{
char buf[1000];
char *str;
char *tok;
int count = 0;
strcpy(buf,source);
tok =strtok(buf," \t\r\n");
if(tok == NULL)
return 0;
while(tok !=NULL)
{
str = tok;
if(++count == column)
break;
tok = strtok(NULL," \t\r\n");
}
return source;
}

###補足情報 このプログラムは全てlinux上で作っています。 まだまだ至らないとこばかりですがご協力お願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

インデントや変数名を整理してみましたが、main関数自体はそこまでおかしくないので
問題になるのは文字列置換の処理ですね。

C

1#include <stdio.h> 2#include <string.h> 3 4const int BUFSIZE = 512; 5const int PATH_MAX = 4016; 6const char *permute_str(const char *source, const char *target, const char *replace, int column); 7 8int main(void) 9{ 10 FILE *fp_in, *fp_out; 11 char fname_in[PATH_MAX], fname_out[PATH_MAX]; 12 char buf[BUFSIZE], target[BUFSIZE], replace[BUFSIZE]; 13 14 // scanfをはじめ、unsafeな関数が多いけど初学者であればとりあえずOK 15 printf("検索されるファイル名 : "); 16 scanf("%s", fname_in); 17 printf("出力先のファイル名 : "); 18 scanf("%s", fname_out); 19 printf("置換前の文字列 : "); 20 scanf("%s", target); 21 printf("置換後の文字列 : "); 22 scanf("%s", replace); 23 24 // 入力ファイルをオープン 25 if ((fp_in = fopen(fname_in, "r")) == NULL) { 26 printf("ファイル %s が見つかりません\n", fname_in); 27 return 0; 28 } 29 30 // 出力ファイルをオープン(要エラーチェック) 31 fp_out = fopen(fname_out, "w"); 32 33 // 入力ファイルを1行ずつ読み込んで処理 34 while (fgets(buf, BUFSIZE, fp_in) != NULL) { 35 const char *res = permute_str(buf, target, replace, 3); 36 fprintf(fp_out, "%s", res); 37 } 38 fclose(fp_in); 39 fclose(fp_out); 40 41 return 0; 42} 43 44// 1行ずつ文字列を処理して返す。改行コードまで含める 45const char *permute_str(const char *source, const char *target, const char *replace, int column) 46{ 47 // 置換後の文字列を返す処理を実装する 48 // まずは置換前の文字列を返してファイルコピー部分(呼び出し元)が動いていることを確認 49 // それから文字列の置換部分を実装 50 // ファイル入出力と文字列の置換部分を分けて考える 51 // とはいえ、変数名を書き換えたぐらいで、main関数の流れ自体は問題なかったので余計なお世話かな? 52 return source; 53}

まずは文字列置換の関数部分だけじっくり取り組んだ方がいいでしょう。
ファイル入力は置いといて、固定の文字列を渡して変換するコードを作ってみてください。
置換対象文字と、置き換える文字の長さが違ったりすると、難易度が一気に上がります。

1文字ずつずらしながら一致する部分を探しては置換の繰り返しがお勧めです。

source = "abcdefgabcdefg"; target = "def"; replace = "beef"; abcdefgabcdefg def def def def 一致! 置換 abc + beef + gabcdefg abcbeefgabcdefg 文字列が1文字増えているのでバッファサイズと比較位置に注意 def def def def def 一致! 置換 abcbeefgabc + beef + g abcbeefgabcbeefg 文字列が1文字増えているのでバッファサイズと比較位置に注意 def

投稿2016/07/07 07:17

kopio

総合スコア487

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

soromon

2016/07/08 08:17

返信ありがとうございます。 置換部分のみもう一度試してみます。
guest

0

一つは、ファイルを読み取りモードでオープンした後、クローズせずに書き込みモードで開こうとしています。fp_o=fopen(fname2,"w"); の前にクローズしてください。

もう一つは、文字列のポインタを返すべき関数なのに数値を返しています。どこから取ってきたソースか知りませんが、理解してから使っていますか?
###追記
インデントがむちゃくちゃです。
読みにくいのはバグの元なので、きれいに書きましょう。
最後の中カッコも閉じていません。

permute_str の中で char *c は使われていません。
したがって置換もされません。

変数の命名はもう少し計画的に。
a とか b とか c とかでなく、意味のある名前をもたせましょう。
fname fname1 sstr cstr なども同じです。
検索されるファイル名なら inFileName や originalFileName など、出力先なら outFileName や newFileName など。補完のきくエディタを使って読みやすいソースを心がけてください。

自分さえ読めればいいというのではなく、他人に見せられるソースを書いてください。

投稿2016/07/07 05:35

編集2016/07/07 06:07
Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

soromon

2016/07/08 06:01

返答ありがとうございます。わかりずらいソースで申し訳ありません。 これからもっと勉強していくのでこれからもご教授お願いいたします。 一度書き直します。
soromon

2016/07/08 08:17

書き直してみました。 まだ置換部分がうまくいきません。どうしたらよろしいでしょうか?
Zuishin

2016/07/08 09:14 編集

修正お疲れ様です。かなり読みやすくなりました。 で、文字列のポインタを返すようになったのはいいのですが、置換前の文字列をそのまま返しています。 また、前回 char *c が使われていないと書きましたが、やはり target も replace も使われていません。これでは置換されません。 置換後の文字列を書き込むバッファをもう一つ用意して、それに書き込んでください。 この戻り値なら、呼び出し先で malloc でメモリを確保して返すのが自然ですが、それだと気を付けないとメモリリークを起こしますので、呼び出し元でバッファをもう一つ用意して、引数をもう一つ増やすのが簡単だと思います。 それと、これも前回書きましたが、ファイルを読み取りオープンした後、書き込みオープンする前に一度閉じてください。
kopio

2016/07/08 09:28

出力ファイルをオープンする前に入力ファイルを閉じる目的は何ですか?
Zuishin

2016/07/08 11:07

間違えました。閉じてはいけません。
Zuishin

2016/07/08 11:11

読み取りオープンするのが出力先のファイルだとなぜか思い込んでいました。
guest

0

こんにちは。

ざっとしか見ていないのですが。

permute_str()はchar*型で文字列を返却しようとしていると思います。
しかし、実際に返却している値は、整数の0か1ですね。整数の0や1は文字列として解釈できないので異常動作します。

permute_str()は指定列を置き換えた行全体の文字列を返却する必要があるのではないでしょうか?
トークン分解までは実装されているように見えますが、文字列へ再組み立てしつつ、指定列を置き換える処理が丸っと存在していないようです。

投稿2016/07/07 05:39

編集2016/07/07 07:16
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

soromon

2016/07/08 06:03

ご返答ありがとうございます。 まだまだ至らないとこが多く意味不明な点も多いと思いますが、少しずつ直していきます。
guest

0

C

1const char *permute_str(const char *source, const char *target, const char *replace, int column)

この置換の関数ですが、引数であるtargetとreplaceを使用している箇所がありません。
おそらく、sourceからtargetを探してあればreplaceに置き換えるという関数だと思うのですが、これでは置換されなくて当然です。

投稿2016/07/08 08:33

PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問