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

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

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

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

Q&A

解決済

3回答

2586閲覧

C言語 画像をバイナリファイルで読み込んで、メッセージの送受信をする

nekoatsume

総合スコア7

C

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

0グッド

0クリップ

投稿2020/05/12 12:26

編集2020/05/13 04:41

前提・実現したいこと

C言語初心者で勉強している者です。できれば今日中に解決したいです。
画像データをバイナリファイルで読み込んで、メッセージの送受信を行いたいです。
(別プログラムでのメッセージの送受信)

発生している問題・エラーメッセージ

送信側、受信側ともにsend_sizeがundeclated(first use this function)となり
機能していないようですが原因がわかりません。
他にもプログラム上に問題があれば、ソースコードで教えていただけますと幸いです。

C言語(メッセージ送信側)

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <sys/types.h> 5#include <sys/ipc.h> 6#include <sys/msg.h> 7#include <errno.h> 8 9#define KEY 2020 10 11typedef struct{ 12 long mtype; 13 int send_size; 14 char image[1024]; 15 }DATA; 16 17 int main() 18 { 19 DATA data; 20 data.mtype=1; 21 data.send_size=0; 22 char mtext[256]; 23 24 int msgid; 25 FILE *fp; 26 extern int errno; 27 28 29 if((msgid=msgget(KEY,0666|IPC_CREAT))==-1){ 30 printf("MsgGet Error=%d\n",errno); 31 exit(EXIT_FAILURE); 32 } 33 34 if((fp=fopen("gazou.png","rb"))==NULL){ 35 printf("ファイルが開けませんでした"); 36 exit(EXIT_FAILURE); 37 } 38 39 40 41 while(feof(fp)==0){ 42 data.send_size=fread(&data.image,1,1024,fp); 43 printf("%d\n",data.send_size); 44 printf("%ld\n",sizeof(data)-sizeof(long)); 45 printf("msgid:%d\n",msgid); 46 if(msgsnd(msgid,&data,data.send_size+sizeof(int),0)==-1){ 47 printf("errno=%d\n",errno); 48 perror(mtext); 49 fputs(mtext,stdout); 50 exit(EXIT_FAILURE); 51 } 52 53 } 54 fclose(fp); 55 exit(EXIT_FAILURE); 56 57 } 58

C言語(メッセージ受信側)

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <sys/types.h> 5#include <sys/ipc.h> 6#include <sys/msg.h> 7#include <errno.h> 8 9#define KEY 2020 10 11typedef struct{ 12 long mtype; 13 int send_size; 14 char image[1024]; 15 }DATA; 16 17 18 int main(int argc,char* argv[]) 19 { 20 int status=EXIT_FAILURE; 21 int msgid; 22 extern int errno; 23 24 DATA data; 25 26 FILE *fp; 27 char mmtext[256]; 28 29 30 31 data.send_size=0; 32 33 if((fp=fopen("gazou2.png","wb"))==NULL){ 34 printf("ファイルが開けませんでした"); 35 exit(EXIT_FAILURE); 36 } 37 38 39 if((msgid=msgget(KEY,0666|IPC_CREAT))==-1){ 40 printf("MsgGet Error=%d\n",errno); 41 exit(status); 42 } 43 44 45 while(1){ 46 if(msgrcv(msgid,&data,sizeof(data)-sizeof(long),0,0)==-1){ 47 printf("recieve error=%d\n",errno); 48 perror(mmtext); 49 exit(EXIT_FAILURE); 50 } 51 fwrite(&data.image,1,data.send_size,fp); 52 printf("data.send_size=%d\n",data.send_size); 53 54 if(data.send_size<1024){ 55 break; 56 } 57 } 58 printf("書込み終了\n"); 59 fclose(fp); 60  exit(EXIT_SUCCESS); 61 } 62

Linuxのubuntu上で開発しています。

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

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

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

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

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

etsuhisa

2020/05/12 14:20

1つ目でgazouというファイルを1024バイトずつ読み取ってメッセージキューで2つ目に送り、2つ目でキューから読み取ったデータをgazouというファイルに書き込む、ということが実現したいことですか?
nekoatsume

2020/05/12 14:50

コメントありがとうございます。 実現したいことはほぼご認識のとおりなのですが、 本文に記載漏れしていたところを追記します。 1バイトを1024個ずつ読み込んで、 データが1024より小さいことを確認して終了するような状態にしたいです。 (送信側も1バイトずつ送信して受信側が0になったときにfcloseする) また、書き込んだファイル名は別名にしようと思っています。 本文に書いておらず申し訳ございません。 実行結果の確認方法についてもよくわかっていないので教えていただけたら幸いです、、。 質問が多く申し訳ございませんがよろしくお願いいたします。
guest

回答3

0

ベストアンサー

2つ目のソースコードから、今回の実装とは直接関係のない処理を削除してスリム化したほうがよいです。

直接関係ないので削除。

C

1   struct msgbuff{ 2 long mtype; 3 char mtext[80]; 4 }b; 5

コマンドの第1引数は処理に影響を与えるものではない。他の「printf("Recieve~」もすべて削除。

C

1 if(argc<2){ 2 printf("Argument required.\n"); 3 exit(status); 4 } 5 6 printf("Recieve %d Start.\n",no=atoi(argv[1]));

直接関係ないので削除。

C

1 printf("Receive%2d:",no); 2 fputs(b.mtext,stdout);

追加位置が違う。whileの閉じ括弧(})の直前。

C

1 data.send_size=fwrite(&data,1,data.send_size,fp);

1024バイト未満で処理を終了する要件なら、whileではなくdo~whileのほうがよいと思う。

C

1 do { 23 } while(data.send_size < 1024);

他にも、fopenエラー時のfcloseは不要、どちらのソースコードもmainの終了前にfcloseをいれる、
などの修正が必要です。

投稿2020/05/12 23:37

etsuhisa

総合スコア416

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

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

nekoatsume

2020/05/13 04:55

上記、ご教授いただきありがとうございました。 ご指摘いただいた点をもとにコードを完成させることができました。(更新しました) 私の理解が甘く、不躾な質問してしまい申し訳ございませんでした。 今後は質問したい内容を整理して記載するよう努めたいと思います。
etsuhisa

2020/05/13 10:16

完成できてなによりです。こちらも十分に対応できなかったにも関わらずBAに選んでいただきありがとうございました。今後ともよろしくお願いします。
guest

0

1つ目のほうは、構造体dataに関する点の修正が必要だと思います。

C

1 DATA data; 2 data.mtype=0; //構造体dataのメンバ 3    //data send_size; //不要な宣言

C

1 while(feof(fp)==0){ 2 data.send_size=fread(&data.data,1,1024,fp); //send_sizeはdataのメンバにする 3 if(msgsnd(msgid,&data,data.send_size+sizeof(int),0)==-1){ //構造体のメンバからsizeof(int)では?

2つ目は、msgrcvの後に、fwriteだと思います。
その他にも不要な定義を取り除いたりと、だいぶ直さないとならないと思います。

投稿2020/05/12 14:33

etsuhisa

総合スコア416

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

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

0

コンパイラのエラーの通りsend_size(とmtype)が宣言されていません。
data.mtypedata.send_sizeの誤りでしょう。
あといくつか全角スペースが入っています。


Recieve 0: (ここにバイナリの文字が3文字ランダムで表示されている状態です)

fputs(b.mtext,stdout);
で初期化されていないb.mtextを出力しているためです。


  • 受信側

etsuhisaさんも指摘されているようにデータを受け取る前にfwriteを呼んでしまっています。
ほかにぱっと見で気づいた点。
data.send_sizeに修正したとしても、初期化されていないままwhileの条件式に使用している。
(追記)コードが更新されましたが、0初期化した後1024と比較しているため一度もループ実行されません。
fwriteの書き込みサイズが受信したdata.send_sizeを使用せず1024固定になっている。
・条件式が代入文になっています。

diff

1-if(errno=ENOMSG) 2+if(errno==ENOMSG)

投稿2020/05/12 12:41

編集2020/05/12 16:11
SHOMI

総合スコア4079

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

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

nekoatsume

2020/05/12 14:19

コメントありがとうございます。 上記の対応でエラーは消えたのですが、 実行結果がどのようになっていれば正解かを 理解できておらず、、プログラムが正常かどうか確認の方法がわかっておりません。 ちなみに受信側の結果は以下のように表示されます。 結果の確認方法について教えていただけないでしょうか。 Recieve 0 Start. Recieve 0: (ここにバイナリの文字が3文字ランダムで表示されている状態です) また、何回か実行していたらMsgsnd Error=22となってしまい ipcrmでキューを削除しみましたが上記の表示が消えません。。
jimbe

2020/05/12 19:14

> 実行結果がどのようになっていれば正解かを理解できておらず それでは「自分が何を作っているのか分からない」ということです. なぜこのプログラムを書いているのでしょうか.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問