いつもお世話になります。
今、ファイル操作を勉強しています。
sample.txtに下記のデータが格納されています。
【sample.txt】
---------------------
yamada.txt | 29
suzuki.txt | 25
kitamura.txt | 30
endo.txt | 32
---------------------
char *name="suzuki.txt";
sample.txtのデータがchar nameと一致する、
ファイルの行を削除し、行を詰めたいのですが
どうしたらいいのでしょうか?
結果として、sample.txtが、
---------------------
yamada.txt | 29
kitamura.txt | 30
endo.txt | 32
---------------------
のように、一致したsuzuki.txtの行が削除され、
行が詰められている状態にしたいです。
どうぞよろしくお願い致します。
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
★アドバイス
・単純に『sample.txt』を読み込み、単純に一時ファイル『sample.tmp』に書き出す。
このときに『char name』と一致する行だけを書き出さないようにすれば良い。
その後に『sample.txt』を削除して『sample.tmp』のファイル名を『sample.txt』に
変更する方法もあります。ただし C 標準関数ではファイル名の変更する関数がなく
処理系によっては _rename() という関数があったりします。Windows 環境なら API
関数を使ってリネームできます。→MoveFile()
・今回は sample.txt のデータをメモリに一括で読み込み処理した方がいいのかも。
読み込む方法も回答者 No.1 さんのようにすべてのデータを1つのメモリ領域に
読み込む方法があります。こちらは No.1 さんのを参照。
私は行単位でメモリに格納して書き出す方を紹介します。
(1)ファイルをテキストでオープン(fopen)
(2)適当なサイズのメモリを確保(malloc)
(3)行単位で読み込む(fgets)
(4)『char name』と一致する行以外をメモリに格納(strstr)
(5)(4)でメモリが不足しているならメモリを拡張(realloc)
(6)ファイルが終わるまで(2)~(5)を繰り返す
(7)ファイルをクローズ(fclose)
こんな感じでどうですか?
今回はメモリの確保(malloc)、拡張(realloc)、解放(free)を使ってみます。
・下に実装例を載せます。これを参考にもっと良い方法を探して下さい。
サンプル:
size_t leng;
size_t size = (10 * 1024); // 最初は 10 KBのメモリ量
size_t free = size;
char *buff = (char*)malloc(size);
char *tail = buff;
char *stop = buff + size;
char *name = "suzuki.txt"; // 削除するファイル名
char *mp;
FILE *fp;
// 確保チェック
if ( buff == NULL ){
printf( "メモリが確保できません。\n" );
exit( 255 );
}
// 読み込み
if ( (fp = fopen("sample.txt","r")) != NULL ){
while ( fgets(tail,(int)free,fp) != NULL ){
if ( strstr(tail,name) != NULL ){
continue; // 削除ファイルなら次の読み込みへ
}
leng = strlen( tail );
tail += leng;
free -= leng;
if ( free < 1024 ){ // 空き領域が 1 KB 以下なら
leng = (10 * 1024); // メモリ量を 10 KB 増加(拡張)
size += leng;
free += leng;
if ( (mp = (char*)realloc(buff,size)) == NULL ){
printf( "メモリが足りませんでした。\n" );
free( buff ); // 安全なため
fclose( fp ); // 安全なため
exit( 255 );
}
// 再設定
leng = strlen( mp );
buff = mp;
tail = mp + leng;
stop = mp + size;
}
}
fclose( fp );
}
// 書き出し
if ( (fp = fopen("sample.txt","w")) != NULL ){
fputs( buff, fp );
fclose( fp );
}
最後に:
・ソースがちょっとがないですが読み取ってみて下さい。
また上記のサンプルを関数にして、ファイルから動的にメモリに読み込めるように
改良すれば今後いろいろと利用できます。今回は strstr() 部分で name に一致した
行はメモリには追加しない処理をしています。ここの処理をなくせば改良できます。
・あと書き出しの方はメモリに読み込んだ内容を単純にファイルに出力すれば良いだけ
なので fopen、fputs、fclose の簡単な処理になっています。
name のチェックと削除はメモリに読み込み時に処理しているからです。
・以上。realloc 関数については下の『参考URL』をどうぞ。
参考URL:http://www9.plala.or.jp/sgwr-t/lib/realloc.html
No.2
- 回答日時:
あっと、ミステイクです。
>メモリにすべて読み込んで概要行を
メモリにすべて読み込んで該当行を
それと(3)のstrncmpの方法ではメモリ保護エラーが出る可能性があるので、これも訂正します。なぜか分かりますか?
新しい(3)です。
(3)char nameの名前と一致する文字列がバッファにあるかを、1文字づつ比較して確認します。char name側が文字列終端(\0)に達したら一致したと判定します。途中で文字が違ったり、バッファ側が改行コード(0x0d,0x0a)だったり、バッファサイズ外に出そうになったら不一致として判定します。
No.1
- 回答日時:
ファイルの大きさが数十MB以下であれば、メモリにすべて読み込んで概要行を削除して書き出すのが一般的だと思います。
練習問題的な処理ではなく、実用レベルでプログラムを書くには次のような流れで処理します。
(1)ファイルサイズを調べて、読み込むバッファをmallocで確保します。読み込むサイズをバッファサイズとして記録します。
(2)ファイルをバイナリでオープンして、freadで一括バッファに読み込みます。処理ポインタにバッファの先頭アドレスを入れます。
(3)char nameの名前と一致する文字列がバッファにあるかを、strncmpでチェックします。strncmpを使う理由は、バッファ側の文字列終端(\0)が無いためです。
(4)一致したら、その行の終端である改行コード(0x0d,0x0a)をサーチします。これで、削除する行の先頭アドレスと終了アドレスが得られます。
(5)(4)の続きで、memcpy(先頭アドレス,終了アドレス+1,転送サイズ);で内容コピーをして間を詰めます。転送サイズは、バッファの終端アドレス-終了アドレスで求めます。転送後は、間を詰めたのでバッファサイズを修正します(方法は考えてみてください)。
(6)一致しなかったら、改行コード(0x0d,0x0a)をサーチして処理ポインタを次の行に移します。
(7)(3)~(6)までを処理ポインタがバッファの最後に達するまで繰り返します。
(8)読み込んだときと同じファイルをバイナリで出力オープンして、バッファの内容をバッファサイズ分ファイルに書き出します。
(注意)(4)と(6)で改行コードをサーチする場合に、バッファ終端が来るかも知れませんので、それを考慮する必要があります。
もっと高速な方法はありますが、とりあえず例として。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- UNIX・Linux Linuxについて質問です。 以下のhistoryの出力結果から、sedコマンドのファイル名tmp1 1 2023/02/03 20:11
- Excel(エクセル) 【VBA】指定フォルダに格納中のテキストファイルをエクセルで処理し結果のエクセルを新規フォルダに保存 1 2022/03/25 14:19
- その他(プログラミング・Web制作) ファイル名の一部をbatで変更したい batファイルを使って、以下のようにファイル名の一部を変更した 3 2023/02/21 20:09
- Visual Basic(VBA) エクセルのマクロについて教えてください。 4 2023/02/05 09:55
- Excel(エクセル) エクセルのマクロについて教えてください。 1 2023/02/03 13:18
- C言語・C++・C# 至急教えてください!プログラミングの問題です。 入力待ちをして、受け取った正の整数が表す行数だけ既存 4 2022/07/05 10:12
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Windows 10 windows10このPCをリセットするを選択し、すべて削除を選択した場合C以外のドライブも初期化? 2 2022/11/10 14:24
- その他(プログラミング・Web制作) テキストデータ変換(プログラミング、linux、python) 8 2023/08/08 16:39
- Visual Basic(VBA) VBAでエクセルをtxtに変換するとエクセルでカンマを含む文字数字がtxtでは「""」付にならないよ 1 2022/08/27 12:17
このQ&Aを見た人はこんなQ&Aも見ています
-
餃子を食べるとき、何をつけますか?
みんな大好き餃子。 ふと素朴な疑問ですが、餃子には何をつけて食べますか? 王道は醤油とお酢でしょうか。
-
人生最悪の忘れ物
今までの人生での「最悪の忘れ物」を教えてください。 私の「最悪の忘れ物」は「財布」です。
-
忘れられない激○○料理
これまでに食べたもののなかで、もっとも「激○○」だった料理を教えて下さい。 激辛、でも激甘でも。 激ウマ、でも激マズでも。
-
プリン+醤油=ウニみたいな組み合わせメニューを教えて!
プリンと醤油を一緒に食べると「ウニ」の味がする! というような意外な組み合わせから、新しい味になる食べ物って色々ありますよね。 あなたがこれまでに試した「組み合わせメニュー」を教えてください。
-
ギリギリ行けるお一人様のライン
おひとり様需要が増えているというニュースも耳にしますが、 あなたが「ギリギリ一人でも行ける!」という場所や行為を教えてください
-
ファイル書込みで一行もしくは部分的に上書きする
PHP
-
C言語---ファイルに出力したデータをすべて消去する方法
C言語・C++・C#
-
【C言語】テキストファイル内のデータを一行削除
C言語・C++・C#
-
-
4
CSVファイルの特定行の削除
Visual Basic(VBA)
-
5
fgetsなどのときのstdinのバッファを消すには?
C言語・C++・C#
-
6
Enterキーを押されたら次の処理に移るという事をしたい。
C言語・C++・C#
-
7
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
8
数字以外が入力されたらエラー文を出したい。
C言語・C++・C#
-
9
ファイルから読み取った改行文字を消す方法
C言語・C++・C#
-
10
ファイルの先頭行を全て削除したい
Windows Vista・XP
-
11
エディットボックスの入力制限について
C言語・C++・C#
-
12
バッファとは何ですか
C言語・C++・C#
-
13
ファイルから読みこむ方法
C言語・C++・C#
-
14
画面を強制的に再描画させる方法
C言語・C++・C#
-
15
DWORDの実際の型は何でしょうか
C言語・C++・C#
-
16
C言語・要素除去
C言語・C++・C#
-
17
C言語初心者の質問失礼します。
C言語・C++・C#
-
18
Winsockで接続待ちタイムアウトを設定する方法
C言語・C++・C#
-
19
関数から配列を返すには?
C言語・C++・C#
-
20
C言語 exitの使い方
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ハフマン符号のプログラム
-
fgetsで2行目から文字化け
-
fopen(書き込みモード)でファイ...
-
BCB 読み込み。
-
VBSで指定行に挿入
-
【VB.Net】バイト型配列に読み...
-
C言語 バイナリファイルの読み...
-
c言語 2つのファイルを行ご...
-
バイナリファイルをテキストフ...
-
C言語初心者の質問失礼します。
-
FTPでputすると空ファイルが出...
-
フルパスから最後のディレクト...
-
どんなプログラムを書いても指...
-
バッファとは何ですか
-
csvファイルを開かずに文字を検...
-
ファイル名の先頭にアンダース...
-
UTL_FILEにて既存のExcelに追加...
-
c/c++ ビルドしたにもかかわら...
-
VB.NETで他のプロジェクトで作...
-
ファイルの結合
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ファイル内のデータを1行削除...
-
テキストファイルの行数を取得...
-
バイナリファイルをテキストフ...
-
c言語 2つのファイルを行ご...
-
fgetsで2行目から文字化け
-
改行までの一文字ずつのファイ...
-
VBSで指定行に挿入
-
winsock recvでの文字化け
-
【VB.Net】バイト型配列に読み...
-
巨大なテキストファイル(可変...
-
C言語での改行コードの扱いにつ...
-
EOF判定されない
-
【C言語】テキスト読み込みの行...
-
続・EOF判定されない
-
freadでファイルを読み込んだ際...
-
fopenで開いたファイルのサイズ...
-
C言語 バイナリファイルの読み...
-
0x00をファイル出力
-
0バイトファイルの作成
-
ファイル読み込みについて
おすすめ情報