
C/C++歴4ヶ月の初心者プログラマーです。現在、
C/C++でのファイル入出力で大変困っております。
その内容というのはファイルをオープンし指定した
テキストファイルに書き込む時に制限をかけたいのです。
例えば、
ファイルに書き込む内容が50行を超えた場合
1番始めに書き込まれた1行目の内容を削除して、
2行目~50行目のデータを1行繰上げて、最新のデータを
50行目に書き込んでいく処理をしたいのですが僕一人では
全くわからず先に進めない状態です。どなたかわかる方
おられますか?よろしければご伝授してください。
途中までのソースを載せておきますので宜しくお願いいたします。
Cで書いていますがC++でも方法があればお願いいたします。
/******************************
サンプルソース
******************************/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp //ファイルポインタの宣言
char str[] = "テスト書き込み";
if((fp=("test.txt","w"))==NULL) //ファイルオープン
{
exit(1); //ファイルオープンエラー時
}
//ここの処理がわかりません。50行まできたら1行目を削除し
//2行目~50行目を1行繰上げ、最新データを50行目に書き込み
fprintf(fp,"%s\n", str);
fclose();
}
No.5ベストアンサー
- 回答日時:
BlueStonesです。
補足質問に対する回答です。----------------------------------------------------------------
// 一行毎に入力する場合
while(1)
{
// 一時保存用変数
char buf[ 256 ];
// 文字列の入力
gets( buf );
// 何も入力せずにEnterキーを押した場合は入力終了
if( strcmp( buf, "" ) == 0 )
break;
// Data変数に格納
strcpy( Data[ num ], buf );
num++;
}
----------------------------------------------------------------
// ファイルにすでに入っているデータを参照する場合
// 注)
// このプログラムは
// if( (fp = fopen("test.txt","w")) == NULL )
// の記述よりも前に宣言してください
// ファイルオープン(読み込み用)
if( (fp = fopen("test.txt","r")) == NULL )
{
exit(1);
}
// ファイルの終わりが来るまで読み込み
while( !feof( fp ) )
{
char *p;
// 一行の読み込み
fgets( Data[ num ], 256, fp );
// fgets()は末尾の改行も代入されるので、それを除去
p = strrchr( Data[ num ], '\n' );
if( p != NULL )
{
*p = '\0';
}
// 行数のカウント
num++;
}
// 最後の行が改行のみなら、それは無視する
if( strcmp( Data[ num - 1 ], "" ) == 0 )
{
num--;
}
// ファイルクローズ
fclose( fp );
----------------------------------------------------------------
こんなのを考えてみましたが
どうでしょうか(^_^)
早速の回答ありがとうございます。こんな難しい処理をスラスラと
記述できるなんて本当にすごいし、羨ましいです。まだこの素晴らしい
ソースを見て理解するには少々時間が掛かりそうですがゆっくり解析
していきたいと思います。BlueStones本当にこんな初心者の
悩みを聞いていただき感謝しています。ありがとうございました。
No.4
- 回答日時:
前提としてファイルのデータ内容が
変数に保存されているとした場合のプログラムを書いてみました。
----------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE *fp;
char str[] = "テスト書き込み";
char Data[ 64 ][ 256 ]; // 64行分の文字列が格納できる変数
int num = 0;
int i;
// ファイルオープン
if( (fp = fopen("test.txt","w")) == NULL )
{
exit(1);
}
/*
このコメント欄内には
Data変数に書き込み文字列を代入する処理
を記述する
*/
// 書き込み文字列が50行以上のときの処理
if( num >= 50 )
{
// 繰上げる行数の計算
int shift = (num - 50) + 1;
// 下から49行分を繰上げ
memcpy( Data[ 0 ], Data[ shift ], 256 * 49 );
// 最新データを50行目に代入
strcpy( Data[ 49 ], str );
num = 50;
}
// 通常のデータの代入
else
{
// 最新データを代入
strcpy( Data[ num ], str );
num++;
}
// ファイルにデータを書き込み
for( i=0; i<num; i++)
{
fprintf( fp, "%s\n", Data[ i ] );
}
fclose( fp );
}
----------------------------------------------------------------
理解できたでしょうか^_^;
わからない箇所は、追って質問してくださいね。
この回答への補足
返信遅くなり申し訳ございませんでした。
ご丁寧にソースまで記述していただきお手数お掛けしました。
このソースであれば4ヶ月の僕でも理解できました。
本当にありがとうございます。もう1つご質問があるのですが
よろしいでしょうか?
>/*
> このコメント欄内には
> Data変数に書き込み文字列を代入する処理
> を記述する
> */
このコメント内にも、もしよろしければBlueStonesさんの
サンプルソースで構いませんので処理ソースお願い
できますでしょうか?お手数お掛けしますがよろしくお願い
いたします。
No.3
- 回答日時:
1.もし、C言語で書きたいのなら、わたしなら、長さは不明ですが、
高々全部で50行しかないので、メモリにいったん読み込んでしまいます。
2.メモリに読み込む方法は、配列でも(固定エリア分メモリを食う方式)、malloc(OSにメモリくれーって頼んで、頼んだ分もらう方式。使い終わったらfreeで開放するのを忘れずに)でも状況によりけりですが、多分用途はログの処理かなんかでしょ。こだわるといくらでも長くなるので、
mallocで固定エリア確保して、それより読み込みが多ければエラーで十分だと思う。(もっといい方法は幾らもあるがその分プログラムが複雑になる、たとえばエラーにせずにさらにメモリをぶん取って処理をつづける方法もあるが、トータルでどんだけメモリをぶん取ったのか覚えておいてどこかでエラーにしないと駄目だぞ。メモリがなくなって死ぬぞ)
3.メモリに読み込む時に行数を数えておく、50行以下と51行以上では、まったく違う処理に振り分けて考えよう。
4.最後にメモリの内容をファイルに吐き出せば、良い。
5.二行目を読み込む時にすかさず、読み込んだメモリの位置を変数に覚えておいて、書き出すときはこの位置から書き出す方式もある。
6.プログラムが書いてないのは意地悪じゃなくって、こういう単純なプログラムは、用途によって、「使える・使えない」が、ううーーーんと、
違うんだ。あなたが何を重視するかによって、おのずと書くプログラムが、ひとつに決まるはず。
7.マニュアルを読むのならfseekの項も読んだ方が良い。あと、C言語ならあなたの書いたプログラムには、fopenを忘れているぞ。
8.fopenの同項目のアペンドは仕様を誤解しやすい処なので、使う必要があるのならば特に注意して使う必要がある。初心者ならば、知っていても避けた方が、無難。
9.もしWindows上のC言語ならば(Windows上で動作するDOSは関係ない)これらでも、動作はするものの独特の制限があるので、マニュアルを引く事。特にメモリ取得関係は変えないと駄目。今書いた全ての関数は別関数に移行している。Linuxとかならこの行は全く関係ないです。
お返事遅くなり申し訳ございません。大変貴重な回答を頂き
ありがとうございます。ずばりlogの処理です。
えっ!こういう処理って難易度てきに簡単な処理だったんですか?
自分では全く処理が浮かばず前に進めない状態でした・・・。
知識が全くないので、これからしっかり勉強したいと思います。
本当にアドバイスありがとうございます。nshooterさんの
貴重なアドバイスをメモしておきます。
No.2
- 回答日時:
C++の標準ライブラリ(STL)
dequeを用いれば簡単に実装できると思う。
//----------------------------------------------------------
#include <deque>
#include <string>
//----------------------------------------------------------
class My_Buffer
{
deque<string> buf;
public:
void add(string& text)
{
if(buf.size() >= 50)
buf.pop_front();
buf.push_back(text);
}
const deque<string>& GetBuffer() const
{
return buf;
}
};
//----------------------------------------------------------
int main()
{
My_Buffer buf;
string text = "ABC";
for(int k=0;k < 2;k++)
{
for(int i=0;i < 25;i++)
buf.add(text);
text = "DEF";
}
//const忘れないでね。
const deque<string> TEXT = buf.GetBuffer();
for(unsigned int i=0;i < TEXT.size();++i)
{
cout << TEXT[i] << endl;
}
}
//----------------------------------------------------------
何も考えずにMy_Buffer.add()に書き込む順番に文字列を渡していく。
そしてGetBufferで取得して取得した文字列配列からファイルに書き込む。
返事が遅くなり申し訳ございませんでした。
>C++の標準ライブラリ(STL)
>dequeを用いれば簡単に実装できると思う。
ご丁寧にソースまで記述していただきありがとうございます。
が、自分自身がC/C++の勉強不足で処理内容に理解しかねます。
本当にご丁寧に指導いただいているのに申し訳ございません。
印刷して理解できるまで目を通したいと思います。
貴重な回答ありがとうございました。
No.1
- 回答日時:
その操作は非常に厄介です。
やりたいことを簡潔に表すとファイルの最後の50行を書き込むだけなので、一度書いたファイルを操作するようなことをせずにファイルを読み込みながら最後の50行だけを保持し、ファイルを読み終わってから書き込んだほうがプログラムがすっきりすると思いますが、いかがでしょう?
この回答への補足
お返事遅くなり申し訳ございませんでした。
貴重なアドバイスありがとうございます。
が・・・、読み込みながら最後の行だけを保持して、
ファイルを読み終わってから書き込む処理が
どう処理すればよいか浮かんできません。
もしよろしければ、簡単なサンプルソースお願い
できますでしょうか?わがままな質問で申し訳
ございませんがよろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- その他(プログラミング・Web制作) python OpenPyXLを使って出力結果をエクセルに書き込み 2 2022/06/04 19:46
- その他(プログラミング・Web制作) Pythonで、データファイルと列名ファイルを1つのファイルにしたいです。 1 2023/07/27 20:29
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Excel(エクセル) 【VBA】指定フォルダに格納中のテキストファイルをエクセルで処理し結果のエクセルを新規フォルダに保存 1 2022/03/25 14:19
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Visual Basic(VBA) Excel-VBAでのファイルの開き方 4 2023/02/14 11:01
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ファイル内のデータを1行削除...
-
c言語 2つのファイルを行ご...
-
fgetsで2行目から文字化け
-
(UWSC)このような場合、解決策...
-
バイナリファイルをテキストフ...
-
C言語での採番について
-
winsock recvでの文字化け
-
改行までの一文字ずつのファイ...
-
EOF判定されない
-
VBSで指定行に挿入
-
0バイトファイルの作成
-
どんなプログラムを書いても指...
-
C言語初心者の質問失礼します。
-
バッファとは何ですか
-
Microsoft VBAで2GBを超えるフ...
-
Access クエリ実行が急に非常に...
-
VB.NETで他のプロジェクトで作...
-
webアプリケーションでの画像フ...
-
FTPでputすると空ファイルが出...
-
C言語で、エクセルの中身を読み...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テキストファイルの行数を取得...
-
ファイル内のデータを1行削除...
-
バイナリファイルをテキストフ...
-
fgetsで2行目から文字化け
-
c言語 2つのファイルを行ご...
-
ファイル読み込みについて
-
巨大なテキストファイル(可変...
-
改行までの一文字ずつのファイ...
-
0x00をファイル出力
-
複数テキストファイルを読み込...
-
EOF判定されない
-
【VB.Net】バイト型配列に読み...
-
変数内の文字列を空にできない
-
[動的配列]C言語の勉強で簡単な...
-
続・EOF判定されない
-
0バイトファイルの作成
-
ファイルサイズ指定し、ファイ...
-
winsock recvでの文字化け
-
int型の値をファイルに保存
-
UNIXシェルプログラム等からバ...
おすすめ情報