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

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

ただいまの
回答率

90.32%

  • C

    3997questions

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

ファイルを削除する関数で行き詰まっています。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 398

sanchu52

score 142

できました。皆さんありがとございます。
次にdata_tel.txtにdata_tmpをコピーしてこのdelete()
関数を完成したいと思います。また
ご教授ください。よろしくお願いいたします。
data_tel.txt
sachiko    ,090-0809
naka       ,090-7777
kiyoko     ,090-9999
satou      ,090-3214
kinosita   ,090-8769
yamada     ,090-4325
itou       ,080-6354
sudou      ,090-3333
kitou      ,080-13424

コード
// data_kirikae8.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>             //for exit 
#include <sys\stat.h>

#define Max 100   

char dtfile[]="data_tel.txt";
char dtfile2[]="data_tmp.txt";

int main(void)
{
      FILE *fp1,*fp2 ;
    char line[Max]={0}; // 検索対象文字列を読み込む配列
    char line2[Max]={0};
    char buff[256];            //検索文字列
    int count=0;
    char *ptr;

    if(!(fp1 = fopen(dtfile, "r"))){
        printf("ファイルを開くことができません\n");
        return -1;
      }
      if ((fp2 = fopen(dtfile2, "r+")) == NULL) {
            fprintf(stderr, "ファイルのオープンに失敗しました.\n");
            return -1;
    }
      printf("削除する名前を検索します。検索する名前を入力して下さい。\n");

      scanf("%s",buff);

      //linesから1行ずつ取り出す。
      while(fgets(line, 256, fp1) != NULL){ 
        printf( "line=%s" ,line );

        ptr=strstr(line,buff);
        if(ptr){
            continue;
        }else{    
            // 書き込み 
            fputs(line,fp2);
            count++;
            if ( count < 0 ) {
                count=fprintf(stderr, "ファイルの書込みに失敗しました.\n");
                return -1;
            }
        }
        fclose(fp2);
    }
    fp2 = fopen(dtfile2, "r");
    printf("\n\n");
    while(fgets(line2, 256, fp2) != NULL){ 
        printf( "line2=%s",line2);
    }
    // ファイルクローズ 
    fclose(fp2);
    fclose(fp1);    

}

/*【実行結果例】
naka@naka ~/kadai/kadai9-8
$ gcc -o data_kakikae8 data_kakikae8.c -Wall

naka@naka ~/kadai/kadai9-8
$  data_kakikae8
削除する名前を検索します。検索する名前を入力して下さい。
naka
line=sachiko    ,090-0809
line=naka       ,090-7777
line=kiyoko     ,090-9999
line=satou      ,090-3214
line=kinosita   ,090-8769
line=yamada     ,090-4325
line=itou       ,080-6354
line=sudou      ,090-3333
line=kitou      ,080-1342

line2=sachiko    ,090-0809
line2=kiyoko     ,090-9999
line2=satou      ,090-3214
line2=kinosita   ,090-8769
line2=yamada     ,090-4325
line2=itou       ,080-6354
line2=sudou      ,090-3333
line2=kitou      ,080-1342

naka@naka ~/kadai/kadai9-8
$

naka@naka ~/kadai/kadai9-8
$
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • otn

    2018/01/05 00:16

    ①ファイルの編集の仕方、②削除とリネームの仕方、の2つの質問と言うことですか?

    キャンセル

  • sanchu52

    2018/01/05 00:22

    分かりにくい質問ですみません。5.のような仕様で、コードを書きたいのですが、ファイルの編集の仕方がわかりません。指針でもいいのでお願いいたします。

    キャンセル

  • Zuishin

    2018/01/05 00:27

    余計な事かもしれませんが、C は車で言えばマニュアル車に似ています。ハンドルもアクセルもブレーキもクラッチも人に任せてウィンカーだけ操作するくらいならオートマ車を練習した方が上達します。

    キャンセル

回答 3

checkベストアンサー

0

まず、元ファイルから1行読み込んで、別ファイルに1行書き出す処理を考えましょう。
これを元ファイルから読み込めなくなるまで回せばファイルのコピーができますね。
あとは1行書き出す直前に行に削除する名前が含まれているかチェックする処理を挟むだけです。

追記3
以下の行をループの外に出して下さい。クローズするのは書き込みが全部終わった後です。

fclose(fp2);

以下の部分ですが、先にi++してしまうと、line[i]には値が入っていません。
そもそも、マッチする値が見つかった場合は、fp2に出力する必要はありません。

i++;
fputs(line[i],fp2);

また、1行ずつ読み込んで処理しているので、line[i],line2[i]は毎回使い捨てになります。
Max個用意する必要はありません。ここを整理すると変数iも必要なくなるのでソースがかなりスッキリします。

char line[Max][40]={0};
char line2[Max][40]={0};

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/05 12:08

    ありがとうございます。ファイルから読みかきを勉強しなおしています。

    キャンセル

  • 2018/01/06 13:39

    追記しました。

    キャンセル

  • 2018/01/06 13:45 編集

    ごちゃごちゃしてきたので、追記3にまとめました。

    キャンセル

  • 2018/01/06 14:51

    hichonさん出来ました。ありがとございます。これからもよろしくお願いいたします。

    キャンセル

  • 2018/01/06 15:01

    質問を書き直しちゃダメだ。流れが掴めんじゃないか。

    キャンセル

0

https://teratail.com/questions/105239
の続きですかね・・・。

strstrで削除したい文字列の位置を探せると思うんですが、削除したい文字列の先頭の一つ前の位置をfwriteに渡せば、削除する文字列の直前までを別ファイルに書き出せますよね?そして再び削除したい文字列の直後からstrstrで探す。

イメージとしては

const char* input_str = /*ファイルから読み込んだ全文字列の先頭へのポインタ*/;
const char* search_str = /*検索文字列*/;
const size_t search_str_len = strlen(search_str);
const File* tmp_file_handle = fopen(/*なんか*/, "wb");
//頑張る
const char* delete_str_front = NULL;
for(
    const char* p = input_str;
    NULL != (delete_str_front = strstr(input_str, search_str));
    p = delete_str_front + search_str_len
){
    fwrite(tmp_file_handle, p, delete_str_front - p);
}

こんな感じ?(もっとちゃんとエラー対策して)

ところで元の回答作っておいてなんだけれども、removeしたファイルと同名のファイル名にrenameできる保証ってあるのかな・・・

やっぱりこういうプログラムって書くべきじゃないなと思う。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/05 12:44

    私もそういう気がしてきました。しかしc言語のことが大分勉強になりました。途中で諦めるとc言語の勉強も諦めそうで怖いです。趣味が無くなりそうで。ボケ防止です。色々教えて頂いて感謝いたします。それでは頑張ってみます。

    キャンセル

0

こんにちは。

かなり混乱しているように見えます。
char lines[MAX}[40];のような変数を定義して、そこへ1行ずつfgetsで全部読み込み、次にlinesから1行ずつ取り出しながら、指定文字列が含まれていないならファイルへ書き込めば良いのではないでしょうか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/06 09:43

    久しぶりです。ご助言ありがとうございます。ヨタヨタしながらここまでできました、やってみます。

    キャンセル

  • 2018/01/06 12:38

    あれっ、そういえばこれ改行の保証ある入力を仮定していいのかな

    キャンセル

  • 2018/01/06 13:31

    yumetodoさんおはようございます。1個だけコピーされていて、そこでとまるみたいです。
    1回正常にnakaが削除されてdata_tmp.txtにほかのデータがコピーされたのですが、端末にdata_tmp.txtが表示されないので、修正するうち肝心のdata_tmp.txtにうまくコピー出来なくなりました。
    コードのしたの方のfp2 = fopen(dtfile2, "r");からしたをあちこちに挿入してそうなったと思うのですが、よろしくお願いいたします。

    キャンセル

  • 2018/01/06 14:53

    Chironianさん出来ました。ありがとございます。これからもよろしくお願いいたします。

    キャンセル

同じタグがついた質問を見る

  • C

    3997questions

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