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

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

ただいまの
回答率

90.47%

  • C

    3821questions

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

ファイルに16個ごとに改行を書き込みたい。C言語。

解決済

回答 5

投稿

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

ファイルのバイナリを読み込んで、そのバイナリをファイルに16個書き込んだら改行を書き込みたいのですが、うまい方法が見つかりません。

C言語でvisual stdioです。
分かる方いましたら、よろしくお願いします!

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void BinaryMake(FILE *ifp, FILE *ofp)
{
    fseek(ifp, 0L, SEEK_END);
    long fsize = ftell(ifp);
    fseek(ifp, 0L, SEEK_SET);

    unsigned char *BinaryText = malloc(fsize);

    fread(BinaryText, sizeof(*BinaryText), fsize, ifp);

    int i = 0;
    fprintf(ofp, "Binary Out.\n\n");

    // Make BinOut.
    fprintf(ofp, "unsigned char BinOut[] = {\n");
    for (i = 0; i < fsize; i++) {
        fprintf(ofp, "0x%X, ", BinaryText[i]);
        // 16の倍数で改行をファイルに書き込みたい。
        if (i != 0) {
            if (i > 16) {
                if (i % 16 == 0) {
                    fprintf(ofp, "\n");
                }
            } else if (i % 15 == 0) {
                fprintf(ofp, "\n");
            }
        }

    }
    fprintf(ofp, "\n};\n\n");

    // BinOutLen.
    fprintf(ofp, "unsigned int BinOutLen = ");
    fprintf(ofp, "%d", i);
    fprintf(ofp, ";\n");

    free(BinaryText);
}

int main(int argc, char *argv[])
{
    FILE *fIN;
    FILE *fOUT;
    errno_t error;
    char buf[255 + 1];

    if ((error = fopen_s(&fIN, "C://Projects/test_curl/Debug/StinkyShitInDaMazafaka.txt", "rb")) != 0) {
        strerror_s(buf, 255, error);
        printf("fopen_s error one \n%s\n", buf);
        return 0;
    }
    if ((error = fopen_s(&fOUT, "C://Projects/test_curl/Debug/MazafakaInDaBinSource.txt", "w+")) != 0) {
        strerror_s(buf, 255, error);
        printf("fopen_s error two \n%s\n", buf);
        return 0;
    }
    BinaryMake(fIN, fOUT);
    fclose(fIN);
    fclose(fOUT);

    return 0;
}

上のソースでファイルに書き込んだ内容の一部です。
2行目が17個目で改行が書き込まれています。
よろしくお願いします!

unsigned char BinOut[] = {
0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F,
0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F,
0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F,
0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F,
0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F,
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

+1

こんな手もある。

// Make BinOut.
    fprintf(ofp, "unsigned char BinOut[] = {");

    for (i = 0; i < fsize; i++) {
        if (i % 16 == 0) {
            fprintf(ofp, "\n");
        }
        fprintf(ofp, "0x%X, ", BinaryText[i]);
    }

    fprintf(ofp, "\n};\n\n");

追記:誰かが「余計なカンマは出さない」と言うので

// Make BinOut.
    fprintf(ofp, "unsigned char BinOut[] = {");
    char[2] delim = "";
    for (i = 0; i < fsize; i++) {
        fprintf(ofp, delim);
        if (i % 16 == 0) {
            fprintf(ofp, "\n");
        }
        fprintf(ofp, "0x%X", BinaryText[i]);
        strcopy(delim, ", ");
    }
    fprintf(ofp, "\n};\n\n");

以上、行頭判断形式。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/07 18:46

    strcopyのオーバーヘッドがわからんけど「無駄な出力しない」版も追記してみました。

    キャンセル

checkベストアンサー

0

こんにちは。

テストしてませんが、たぶん下記でいけると思います。

// Make BinOut.
fprintf(ofp, "unsigned char BinOut[] = {\n");
for (i = 0; i < fsize; i++) {
    fprintf(ofp, "0x%X, ", BinaryText[i]);
    // 16の倍数で改行をファイルに書き込みたい。
    if ((i % 16) == 15)
    {
        fprintf(ofp, "\n");
    }
}
fprintf(ofp, "\n};\n\n");

【追記】
catsforepawさんの回答を見て気が付きました。,が最後についてしまいますね。
もし、生成されたファイルをコンパイルするようでしたら、コンパイラ(例えばVisual strudio)によっては適切にコンパイルしてくれないことがあります。

フラグが必要になることが難点ですが、このような','等を省略したい時、結構使えます。

// Make BinOut.
fprintf(ofp, "unsigned char BinOut[] = {\n");
bool first=true;
for (i = 0; i < fsize; i++) {
    if (first) {
        first=false;
    } else {
        // 16の倍数で改行をファイルに書き込みたい。
        if ((i % 16) == 0) {
            fprintf(ofp, "\n");
        }
        fprintf(ofp, ", ");
    }
    fprintf(ofp, "0x%X", BinaryText[i]);
}
fprintf(ofp, "\n};\n\n");

tkturbotさんとcatsforepawさんの回答を見ても感じるかと思いますが、「継続処理」は「本処理」の後で実行するのではなく、「本処理」の前で実行した方が「綺麗」に書けることが多いようです。
そして、最初だけは「継続処理」が不要になるので、それを運良くごまかせない場合は、フラグを使って分岐するのが良さそうです。


理想は、フラグを使わないでループ先頭の処理を分けることができると良いのです。
どなたか良い方法をご存知でしたら是非教えて下さい。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/07 10:48

    できました!ありがとうございました!!!

    キャンセル

  • 2016/04/07 10:53

    あっと、追記が間に合いませんでした。
    もし,','でハマったら参考にされて下さい。

    キャンセル

  • 2016/04/07 10:59

    分かりました!ありがとうございました!!!

    キャンセル

0

この辺り、「16個かいたら1回改行」に対して条件判定が多すぎます。

// Make BinOut.
    fprintf(ofp, "unsigned char BinOut[] = {\n");
    for (i = 0; i < fsize; i++) {
        fprintf(ofp, "0x%X, ", BinaryText[i]);
        // 16の倍数で改行をファイルに書き込みたい。
        if (i != 0) {
            if (i > 16) {
                if (i % 16 == 0) {
                    fprintf(ofp, "\n");
                }
            } else if (i % 15 == 0) {
                fprintf(ofp, "\n");
            }
        }

    }
    fprintf(ofp, "\n};\n\n");


if (i % 16 == 0) 改行 は心情として正しいです。

if (i != 0)  は、0 % 16 == 0 になってしまうのを防ぐためだと思いますが、
ここにガードを入れるよりも、最初からi==0 にならないようにする、つまりiを1から
始めるほうが効果的です。if文が1つ減ります。

if (i % 15 == 0)も、0から初めて16回書いたら改行、のために入っているのかな?と
思いますが、iが1から始まれば不要です。

ということで、こういうのはいかがでしょうか。

for (i = 1; i <= fsize; i++) {
    fprintf(ofp, "0x%X, ", BinaryText[i-1]);
    if (i % 16 == 0) {
        fprintf(ofp, "\n");
    }
}

テストはしていません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/07 10:49

    気持ちを汲んだ回答ありがとうございました!!!

    キャンセル

0

あまり難しく考えずに「16個毎に改行する」というのをそのままコードにすれば良いです。

ただ、単純に16個出力したら改行すると、データの数がちょうど16の倍数の時に空行が出力されるので、見栄えを考えてこんな感じでしょうでしょうか。

fprintf(ofp, "unsigned char BinOut[] = {\n");
for (i = 0; i < fsize; i++) {
    fprintf(ofp, "0x%X, ", BinaryText[i]);
    if(i % 16 == 15 || i == fsize - 1)    // 16個出力するか最後のデータを出力したら改行
        fprintf(ofp, "\n");
}
fprintf(ofp, "};\n\n");        // 先頭の改行は不要

あるいは、改行の位置を工夫するとif文が簡単になります。

fprintf(ofp, "unsigned char BinOut[] = {");    // 最初の行では改行しない
for (i = 0; i < fsize; i++) {
    if(i % 16 == 0)            // 改行してから16個並べる感じ
        fprintf(ofp, "\n");
    fprintf(ofp, "0x%X, ", BinaryText[i]);
}
fprintf(ofp, "\n};\n\n");

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/07 10:35

    2番目はすでに tkturbo さんが回答したのと同じでしたね。

    キャンセル

0

余分なスペースとか改行は許しません。

fprintf(ofp, "unsigned char BinOut[] = {\n");
for (i = 0; i < fsize; i++)
{
    //16個目と最後は改行
    fprintf(ofp, "0x%02X,%c", BinaryText[i], (i%16==15||i==fsize-1)?'\n':'\0');
}
fprintf(ofp, "};\n\n");

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/07 11:13

    僕がやりたかったことができてます!!!回答ありがとうございました!勉強します!

    キャンセル

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

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

関連した質問

  • 解決済

    cp -r コマンドのC言語による実装

    前提・実現したいこと ls -r コマンドのC言語のソースコードを参考にして cp -r コマンドを実装しているのですが どこを変えていいのかわかりません… 該当のソー

  • 解決済

    C言語における画像処理について

    プログラミング初心者です 今、学校でC言語を習っている途中の初心者です。今回、C言語における画像処理の基礎的なことを学んだのですが、その後自分で試してみようとしたらうまくいきませ

  • 解決済

    4個×3行の数字のファイル入出力がうまくいきません

    #include <stdio.h> #include <stdlib.h> #include <math.h> void Read(); void Output(); FILE

  • 受付中

    c言語の課題に悩んでいます

    前提・実現したいこと 出力したファイル(a.txt)を読み込み、各行の合計値をファイル(b.txt)へ出力するプログラムを作成したいのですが上手くいきません。どなたか下記のプログ

  • 解決済

    C言語のポインタ渡しなど

    fpaの参照しているfnameaファイルから500行2列の数字列を受け取り、posに保存してからそれをexpansionメソッドに代入して数値を変換してfnamebファイルに出力す

  • 解決済

    C言語 行列の乗算 ポインタの扱い

    大学の課題です。コードを書いていて止まってしまったので助けてください。 3行2列の行列が格納されている.csvファイルと、2行4列の行列が格納されている.csvファイルがあり

  • 解決済

    メモ帳などの記録をプログラムで取り込み表示する方法

    表計算で作成したデータを、画面上に表形式で表示するプログラムを作成したいのですが データを読み込むのはどうすればよいのでしょうか?  例など教えてもらえると助かります。 inc

  • 解決済

    あと少しなんですがうまくいきません、、、

    C C言語で 各学生の学籍番号・物理の点数・化学の点数の組がスペース区切りで一行に記述されたファイルを読み込み,全学生の物理の平均点・最高点・最低点,および化学の平均点・最高点・最

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

  • C

    3821questions

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