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

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

ただいまの
回答率

90.03%

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

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,497

soromon

score 13

前提・実現したいこと

お世話になっています。
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上で作っています。
まだまだ至らないとこばかりですがご協力お願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

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

もう一つは、文字列のポインタを返すべき関数なのに数値を返しています。どこから取ってきたソースか知りませんが、理解してから使っていますか?

追記

インデントがむちゃくちゃです。
読みにくいのはバグの元なので、きれいに書きましょう。
最後の中カッコも閉じていません。

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/08 18:28

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

    キャンセル

  • 2016/07/08 20:07

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

    キャンセル

  • 2016/07/08 20:11

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

    キャンセル

+1

こんにちは。

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/08 15:03

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

    キャンセル

+1

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

#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];

    // scanfをはじめ、unsafeな関数が多いけど初学者であればとりあえずOK
    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");

    // 入力ファイルを1行ずつ読み込んで処理
    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;
}

// 1行ずつ文字列を処理して返す。改行コードまで含める
const char *permute_str(const char *source, const char *target, const char *replace, int column)
{
    // 置換後の文字列を返す処理を実装する
    // まずは置換前の文字列を返してファイルコピー部分(呼び出し元)が動いていることを確認
    // それから文字列の置換部分を実装
    // ファイル入出力と文字列の置換部分を分けて考える
    // とはいえ、変数名を書き換えたぐらいで、main関数の流れ自体は問題なかったので余計なお世話かな?
    return source;
}

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

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/08 17:17

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

    キャンセル

0

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


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる