指定した行に値を書き込む関数

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
シオン

指定した行に値を書き込む関数

#1

投稿記事 by シオン » 15年前

指定した行に値を書き込む関数を作っております
DXライブラリを使っております。

// 第一引数 書き込む行、第二以降 書き込む文字列
FileDataSave(int index, ???? );

// ~処理~
num = 3;
FileDataSave( 1, "あああ%d", num);
とするとtest.txtの1行目に
"あああ3"と保存する関数を作りたいです。

ファイルに書き込む処理だけならかけるのですが・・・。
FILE *fp;
fp = fopen( "MapData.txt", "w");
fprintf( fp, "書き込みたい文字列 ");
fclose(fp);

たいちう

Re:指定した行に値を書き込む関数

#2

投稿記事 by たいちう » 15年前

> とするとtest.txtの1行目に
> "あああ3"と保存する関数を作りたいです。

ファイルを先頭から最後まで全て新しく書き直すのが一番簡単です。

http://www.kouno.jp/home/c_faq/c19.html#0

通りすがり

Re:指定した行に値を書き込む関数

#3

投稿記事 by 通りすがり » 15年前

fopenには様々なモードがあります
ちなみにwの場合は書き込み専用で
指定した名前のファイルがない場合には自動で作成し
既に存在した場合にもそのファイルの内容を全て破棄して
新しく上から書き込むモードです

書き込みたいファイルを一旦読み込んでその中身を保持しておき
新たに書き込みたい内容と保持しておいた内容を続けて書き込めば
1行目に付け足した形になると思います

たとえばファイルの中身が

かきくけこ
さしすせそ
たちつてと

だったとして
1行目にあいうえおを書き込みたい場合

かきくけこ
さしすせそ
たちつてとを一旦保存しておき

あいうえおを書き込んだ後
かきくけこ
さしすせそ
たちつてとを書き込みます

あとはコード化してみましょう


※ちなみに1行目ではなく最後の行に足したいのであれば
fopenのモードをaにすることで達成できます

シオン

Re:指定した行に値を書き込む関数

#4

投稿記事 by シオン » 15年前

アドバイスありがとうございます。

書き込む行にすでに文字列があった場合
行をずらすのではなく置きかえる仕様にしたいです。

文字列を読み込み特定の行のみの物を変更すると言ったことがわかりません・・・。
教えては頂けないでしょうか?

シオン

Re:指定した行に値を書き込む関数

#5

投稿記事 by シオン » 15年前

何度もすみません。
読み込みは何とかできたみたいなのですが
指定した行の文字列を別の文字に変更する方法がわかりません。

又、自作の関数に"%s"等と設定の仕方がわかりません・・・。
どうか教えては頂けないでしょうか?
char  buffer[256];

    FILE *fp;
    fp = fopen("test.txt", "r");

    // ファイルオープン失敗か?
    if ( !fp ){
        //printf("ファイルオープンエラー\n");
        //return;
    }

    // 1行ずつ読み込んで表示する
    while( fgets(buffer, 256, fp) ){
        printfDx("%s", buffer);
    }

    // ファイルクローズ
    fclose(fp);

シオン

Re:指定した行に値を書き込む関数

#6

投稿記事 by シオン » 15年前

自分なりに色々やってみたのですがイマイチわかりません・・・。
void FileSaveX( int index, char string[256] ){
    
    char  buffer[10][256];
    //int index = 0;

    FILE *r_fp;
    r_fp = fopen("test.txt", "r");

    // ファイルオープン失敗か?
    if ( !r_fp ){
    //printf("ファイルオープンエラー\n");
    //return;
    }

    // 1行ずつ読み込んで表示する
    while( fgets(buffer[index], 256, r_fp) ){
    index++;
    //printfDx("%s", buffer);
    }

    // ファイルクローズ
    fclose(r_fp);
    printfDx("%s", buffer[1]);

    FILE    *w_fp; 
    w_fp = fopen( "MapData.txt", "w"); 
//    fprintf( fp, "書き込みたい文字列 "); 
    fclose(w_fp);
}

Ma

Re:指定した行に値を書き込む関数

#7

投稿記事 by Ma » 15年前

全部読み込んだら、各行を順番に書きこみます。(追記モードではなく、全消しして新しく書くモードで。)
行がindexと一致したとき、読み込んだ行を書き込むのではなく、関数に引数としてわたらせた文字列をかきこみます。

これは、for文で作ると一番簡単かと思います。
ちょっと考えてコードを作ってみてください。


*追記
今後、他のファイルで使う事も考えて関数の引数にファイル名も渡すといいと思います。
それから、今は10行までしか格納できませんが、書き込まれている行数が不定で10行以上も考えられる場合は
std::vector 等の、可変長リストを使用するといいと思います。 画像

シオン

Re:指定した行に値を書き込む関数

#8

投稿記事 by シオン » 15年前

連絡が遅くなってしまい申し訳御座いませんでした。
ご回答ありがとうございます。

std::vectorを調べてみたのですが使い方がイマイチわかりません。

mila

Re:指定した行に値を書き込む関数

#9

投稿記事 by mila » 15年前

vectorは使用していませんが、ご参考にどうぞ。
#include <stdio.h>
#include <stdarg.h>
    
int FileSaveX(int index, const char *format, ...)
{
    FILE *rfp, *wfp;
    int i;
    char buf[256];
    va_list arg;

    if ((rfp = fopen("test.txt", "r")) == NULL) {
        return 1;
    }
    if ((wfp = fopen("MapData.txt", "w")) == NULL) {
        fclose(rfp);
        return 2;
    }
    va_start(arg, format);
    for (i = 1;; i++) {
        if (fgets(buf, sizeof(buf), rfp) == NULL) {
            break;
        }
        if (i == index) {
            vfprintf(wfp, format, arg);
            fputc('\n', wfp);
        } else {
            fputs(buf, wfp);
        }
    }
    va_end(arg);
    fclose(wfp);
    fclose(rfp);
    return 0;
}

int main(void)
{
    int num = 3;
    FileSaveX(1, "あああ%d", num);
    return 0;
}

バグ

Re:指定した行に値を書き込む関数

#10

投稿記事 by バグ » 15年前

久しぶりにC++で書いてみました。
std::vectorではなく、std::listを使ってみました。

#include <string>
#include <list>
#include <fstream>

////////////////////////////////////////////////////////////////////////////////
// 任意の行に文字列を挿入する
//
// 引数
// unsigned int    index    = 挿入される行(1以上の数値)
// const char*    item    = 挿入する文字列
// const char*    path    = ファイルの場所を示すパス
//
// 戻り値
//                true    = 正常終了
//                false    = 以上終了
////////////////////////////////////////////////////////////////////////////////
bool insert_write(unsigned int index, const char* item, const char* path)
{
    // インデックスが1未満の場合はfalseを返す
    if (index < 1)
    {
        return false;
    }

    // 読み込み用ファイルをオープンする
    std::ifstream fin;
    fin.open(path);

    // ファイルオープンに失敗したらfalseを返す
    if (fin.is_open() == false)
    {
        return false;
    }

    // ファイルの終端まで読み込みつつ、リストへ格納していく
    std::string str;
    std::list<std::string> lst;
    while (fin.eof() == false)
    {
        str.clear();
        fin >> str;
        lst.push_back(str);
    }

    // ファイルのクローズ
    fin.close();

    // ファイルの最大行数よりも、指定されたインデックスが大きい場合は末尾へ挿入
    if (index > lst.size())
    {
        index = (unsigned int)(lst.size());
    }

    // イテレータを任意の位置へ進める
    std::list<std::string>::iterator it = lst.begin();
    for (unsigned int i = 1; i < index; ++i, ++it);

    // 文字列を挿入
    lst.insert(it, item);

    // 書き込み用ファイルをオープン
    std::ofstream fout;
    fout.open(path);

    // ファイルオープンに失敗したらfalseを返す
    if (fout.is_open() == false)
    {
        return false;
    }

    // リストの内容をファイルへ書き込む
    for (it = lst.begin(); it != lst.end(); ++it)
    {
        if (it->length() > 0)
        {
            fout << *it << std::endl;
        }
    }

    // ファイルのクローズ
    fout.close();

    // 正常に終了したのでtrueを返す
    return true;
}

Justy

Re:指定した行に値を書き込む関数

#11

投稿記事 by Justy » 15年前

 どうしてわざわざ C++で書き直したのかは意図はよくわかりませんが、それ正常に動いていないですよ。

 fin >> strでは空白類の情報がそげ落ちます。
 置き換えるなら getlineでしょう。


>for (unsigned int i = 1; i < index; ++i, ++it);
 おかしくはないですが、普通こういう時って標準関数の advanceを使いませんか?


>if (it->length() > 0)
 これは変です。オリジナルの行が空行だった場合、その行が出力されなくなります。

閉鎖

“C言語何でも質問掲示板” へ戻る