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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

Q&A

解決済

1回答

380閲覧

バイナリデータを関数に入れて連続処理

alles-durch

総合スコア3

C

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

0グッド

2クリップ

投稿2021/02/06 15:28

編集2021/02/07 13:01

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
ファイルをバイナリデータで読み込んで16バイト~32バイト単位で逐次変換をしていきたい。

変換する関数は作成して16バイト単位で逐次処理していきたいと思います。
読み込んで処理する方法がよくわかっていません。
今までは16バイトだけのファイルを読み込んで変換をしていましたが、これを写真とか大きなサイズにした場合どうすればいいのかわかりません。
配列を[1024*1024]のサイズを用意して配列に入れ込むか逐次処理するかという感じなのですが、
メモリやファイルサイズを考えないで実行したいと考えています。

下記は関数を作成したときの一部です。
aの16バイトをbと組み合わせてcの戻り値を得るという感じです。

#include <stdio.h> #include <stdlib.h> #include"aaa.h" int main(){ int i,j; FILE* fp1,*fp2,*fp3; unsigned char a[16]= {0}; unsigned char b[16]= {0}; unsigned char c[16]= {0}; unsigned char r[16]= {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; unsigned char output[16]; fp1 = fopen( "syashin.jpg", "rb" ); if( fp1 == NULL ){ printf( "ファイルオープンに失敗しました。\n" ); exit( 1 ); } fread( a, sizeof(char), sizeof(a), fp1 ); fclose(fp1); fp2 = fopen( "b.bin", "rb" ); if( fp2 == NULL ){ printf( "ファイルオープンに失敗しました。\n" ); exit( 1 ); } fread( b, sizeof(char), sizeof(b), fp2 ); fclose(fp2); fp3 = fopen( "output.bin", "wb" ); if( fp3 == NULL ){ printf( "ファイルオープンに失敗しました。\n" ); exit( 1 ); }  aa=a^r kansuu(a,b,c); c=output; fwrite( output, sizeof(char), sizeof(output), fp3 ); fclose(fp3); } ``` ### 試したこと 配列aを[1024*1024]と大きな配列を用意 サイズが分からないのでnと仮定 ここに言語を入力 ``` for(i=0;i<n;i++){ n= fread( a, 16 sizeof(a), fp1 ); kansuu(a,b,c); } ``` aの配列で16バイトずつ読み込んでcの配列に16バイトずつ変換してそのままファイルに書き込んでいくイメージです。 関数がkansuu(unsigned char *a,unsigned char *b,unsigned char c[16])としていましたが 16バイトずつになるのでkansuu(unsigned char a[16],unsigned char *b,unsigned char c[16])としていましたが になるのかといろいろ試行錯誤していますが、よくわかりませんのでご教授願います。 全部一度に読み込んで配列に入れ込む方法と逐次にやる方法等サンプルコードでもいいので概要が分かるものをわかるとありがたいです。よろしくお願いします。 ### 補足情報(FW/ツールのバージョンなど) C言語 VisualStudioCode

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsuya6502

2021/02/07 10:32 編集

質問に付けているタグ(「関数」「データ構造」など)ですが、「C」に変更してください。そうすることでC言語に詳しい人たちに質問が届くようになり、回答が得られる可能性が高まります。 「C」のタグを購読している人:7398人 https://teratail.com/tags/C 「関数」のタグを購読している人:149人 https://teratail.com/tags/%E9%96%A2%E6%95%B0 いま付けているタグは購読者が少ないので、全て外していいと思います。基本的にプログラミング言語のタグだけを付ければ大丈夫です。
alles-durch

2021/02/07 13:04

ありがとうございます。Cの部分抜けてました。該当しそうなでできてたタグつけてただけでした。修正してみました。
hidezzz

2021/02/07 13:44 編集

ファイルからデータを少しずつ読み込んで逐次処理するやり方でいけるのか、それともファイル全体を一括で読み込んでメモリ内に格納してから処理するべきなのかは、処理内容によってどちらがいいか変わると思うので、想定している課題が前者で済むかどうかをとりあえず決めると良いかと思いました。(前者では出来ない処理も想定しているなら必然的に後者になると思うので)
alles-durch

2021/02/07 15:44

回答ありがとうございます。 ファイルサイズ的には前者でいけると思っていますが試行錯誤中なのでなんとも言えませんが変換して書き込んでいくイメージなんですが標準入出力処理を勉強中です。後者の方法のほうも勉強中です。
hidezzz

2021/02/07 16:05

> ファイルサイズ的には前者でいけると思っていますが これはファイルサイズがどのぐらい大きいものか分からないので前者でやらざるを得ないのではないかという意味でしょうか? そうでないのなら前者でいけるかどうかの判断基準はファイルサイズではなく、少しずつ読み込んでいくデータを、その次のデータを読み込む際には捨てていかないといけないことになるがそれで目的の処理を行うことが出来るかどうかです。 捨てることが出来ないのなら最初から後者の処理でいくことを考えたほうが良いのではないでしょうか?
hidezzz

2021/02/07 16:21

捨てることが出来ないのなら、後者のメモリに全部読み込む方法以外に、ファイルからseekしてはreadするを繰り返して必要な情報をその都度読み込んで処理していくやり方もあります。処理は遅くなるとは思います。
alles-durch

2021/02/07 22:29

ありがとうございます。 〉 これはファイルサイズがどのぐらい大きいものか分からないので前者でやらざるを得ないのではないかという意味でしょうか? そうです。わからない場合を考慮してです。今は練習なのでファイルサイズは小さくメモリ的にもどちらでもいけると思ってます。 読み込んだあとは捨てる方向で考えております。 次の処理を行うことを考えればseekで探してそこから取ってくる方法になるのは調べててわかりました。どの処理も読み込みかたと読み込んだあと配列に入れて関数に型に合わせるというのがうまくいかずわからないです。 メモリで全て読み込んで[16]を何個も保持することを考えると[ i ][16]と二次元配列になるけどそうすると関数と合わなくなりエラーになってしまいます。
guest

回答1

0

ベストアンサー

以下Linux(Linux Mint 19.3)の環境で確認しています。Windows環境だとヘッダファイルを直す必要があるかもしれません。

(16バイトずつとか)固定バッファサイズ分ずつ読み込みながら逐一処理していくのなら一例としては以下のようになります。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <unistd.h> 4 5int main( void ) { 6 FILE* fp; 7 char buf[ 16 ]; 8 size_t count; 9 10 fp = fopen( "a.bin", "r" ); 11 if ( fp == NULL ) { 12 perror( "fopen" ); 13 return 1; 14 } 15 16 /* ファイルを1回につきbufサイズ分ずつ読み込んでいく */ 17 while ( ( count = fread( buf, sizeof(char), sizeof(buf), fp ) ) > 0 ) { 18 size_t i; 19 20 /* bufに読み込まれたcountバイト分の処理 */ 21 /* その例として16進数で出力 */ 22 for ( i = 0 ; i < count ; ++i ) { 23 24 printf( "%02X", buf[ i ] ); 25 } 26 } 27 if ( ferror( fp ) ) { 28 29 perror( "fread" ); 30 return 1; 31 } 32 33 printf( "\n" ); 34 35 return 0; 36}

ファイルサイズが実行時にしかわからないのであれば、fstat()でファイルサイズを調べて、malloc()でそのサイズ分のメモリ領域を確保し、一気に読み込むという感じにすれば良いと思います。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <sys/types.h> 4#include <sys/stat.h> 5#include <unistd.h> 6 7int main( void ) { 8 FILE* fp; 9 struct stat st; 10 char* buf; 11 size_t i; 12 13 fp = fopen( "a.bin", "r" ); 14 if ( fp == NULL ) { 15 perror( "fopen" ); 16 return 1; 17 } 18 19 /* オープンしたファイルのファイルサイズ(st.st_size)を求める */ 20 if ( fstat( fileno( fp ), &st ) < 0 ) { 21 perror( "fstat" ); 22 return 1; 23 } 24 25 /* ファイルサイズと同じ大きさのメモリを確保する */ 26 buf = malloc( st.st_size ); 27 if ( buf == NULL ) { 28 perror( "malloc" ); 29 return 1; 30 } 31 32 /* ファイル全体をバッファへ一気に読み込む */ 33 if ( fread( buf, sizeof(char), st.st_size, fp ) != st.st_size ) { 34 35 if ( ferror( fp ) ) { 36 perror( "fread" ); 37 return 1; 38 } 39 else { 40 fprintf( stderr, "何故かfreadで全部読み込むのに失敗した\n" ); 41 return 1; 42 } 43 } 44 45 /* bufに読み込まれた領域に対する処理 */ 46 /* その例として16進数で出力 */ 47 for ( i = 0 ; i < st.st_size ; ++i ) { 48 49 printf( "%02X", buf[ i ] ); 50 } 51 printf( "\n" ); 52 53 return 0; 54}

投稿2021/02/08 03:32

hidezzz

総合スコア1248

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

alles-durch

2021/02/08 14:20

回答ありがとうございます。 大変参考になりました。 ちなみに下記についてですが、この場合は全部読み込んで16バイトずつ処理しているという理解であってますでしょうか? 小さい64バイトのファイルだと仮定して   unsigned char a[64]= {0}; unsigned char b[16]= {0}; unsigned char c[64]= {0}; fread( a, sizeof(unsigned char), sizeof(a), fp ); for (i = 0; i < sizeof(a); i=i+16){ kansuu(&a[i],b,&c[i]); } }
hidezzz

2021/02/08 17:19

質問の趣旨がいまいち分からなかったので外しているかもしれませんが…、 「for (i = 0; i < sizeof(a); i=i+16){」のiがループごとに16刻みで増えているので16バイトずつ処理されているのではないでしょうか? 「kansuu(&a[i],b,&c[i]);」でちゃんと処理しているのが前提ですが。
alles-durch

2021/02/12 08:40

回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問