C言語の構造体参照について

このQ&Aのポイント
  • C言語で構造体の中のchar型のメンバを参照する方法について教えてください。
  • 入力ファイルを読み込み、構造体に格納している中で、char型の変数kumiai_kubunの値が'0'または'1'かどうかを判定する方法を教えてください。
  • 指定したファイルの特定の部分の数字を組合区分として参照する方法を教えてください。
回答を見る
  • ベストアンサー

C言語の構造体参照について

入力ファイルを読み込み、構造体に格納しています。 構造体の中の、char kumiai_kubun[1]が、'0'および'1'になっているかの参照方法を教えてください。 ファイル011100920001000001の部分の最後の数字(1)が組合区分になります。 ・入力ファイル 000000003820050507200504 011100920001000001 エス事業(協)     9999999999999999 ・プログラム #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <errno.h> void print(char* buf, int size); /* 組合情報構造体 */ typedef union kumiaiin_jyouhou { char rawdata[80]; struct hdr { char sikibetu_code[2]; char kensu[8]; char koushin_date[8]; char data_date_year[4]; char data_date_month[2]; char dummy[56]; } header; struct dat { char sikibetu_code[2]; char daicyo_bango[10]; char kumiaiin_bango[5]; char kumiai_kubun[1]; char kaisyamei[46]; char dattai_kaiyaku_ymd[8]; char sakujyo_ymd[8]; } data; } KUMIAIIN_JYOUHOU; int main(int argc, char* argv[]) { KUMIAIIN_JYOUHOU *bufp; FILE *fp; int sts, rtncd; /* 初期化 */ rtncd=0; /* 区切り文字設定 */ strncpy(fs, FS, sizeof(fs)); /* データファイルオープン */ fp = fopen(argv[1], "rb"); /* 組合員情報共用体領域読み込み用メモリの確保 */ bufp = malloc(sizeof(KUMIAIIN_JYOUHOU)); /* ファイル読込 */ while( 1 ) { /* 組合員情報読み込み */ memset(bufp, NULL, sizeof(KUMIAIIN_JYOUHOU)); sts = fread(bufp, sizeof(KUMIAIIN_JYOUHOU), 1, fp); ~組合区分の判定処理~ } fclose(fp); }

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★回答者 No.1 です。 ・最初に『記述ミス』してしまい、ごめんなさい。→回答者 No.2 さんのご指摘どおりです。 本題: ・それで『組合区分の判定処理』ですが、構造体メンバの kumiai_kubun[0] と  『011100920001000001』部分の最後の1つが同じかどうかを判定したいのですか? ・それならば、次のようにします。 ●組合区分の判定処理 if ( bufp->data.kumiai_kubun[0] == bufp->rawdata[42] ){ // 同じの場合 } else{ // 違うの場合 } ・これで、良いのですかね。 ・なお、前回のソースでは『全角空白』があるため、コピー&ペーストするとエラーになります。  今回は、『半角空白』で記述しましたのでエラーにはなりません。 ・最後に、『記述ミス』してしまい、ごめんなさいです。 ・以上。おわり。

yano-kouichi
質問者

補足

判定処理は成功しました。 ありがとうございます。 あとは、エラーレコードの台帳番号と組合員番号を表示させたいのですが、bufpが全て表示され、うまくいきません。 よろしくおねがいします。 fprintf(stderr, "台帳番号:%s 組合員番号: %s の組合区分が不正です\n", bufp->data.daicyo_bango, bufp->data.kumiaiin_bango); 正式メッセージ 台帳番号:1100920001 組合員番号: 00000の組合区分が不正です」

その他の回答 (4)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★追記 ・『%.10s』、『%.5s』には『%』の後ろに『ピリオド』が付いています。見づらいため、注意。 ・以上。おわり。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★最初に ・『%s』は文字列を表示させる書式指定ですよね。 ・文字列は、必ず最後にNULL文字が来ます。でも、構造体『data』にはバッファ領域のサイズを指定  しているだけで、文字列として記録されていません。よって、全て表示されてしまうのですよ。 ・では、どうすればよいか?→通常は、1レコードを『台帳番号』、『組合員番号』の数値に変換して  管理します。その他も、分かりやすい構造体メンバに代入し直すわけです。処理ルーチンの将来性を  考えると『構造体』のデータ管理から見直す必要がありますよ。→助言! ★回答 ・今回はもっと楽な方法で、問題が解決できます。 ・『%s』の部分を『%.10s』または、『%.5s』と変更するだけで文字列を丸めることができます。 ・つまり、書式指定の文字列を  "台帳番号:%.10s 組合員番号: %.5s の組合区分が不正です\n" ・とします。 最後に: ・『%.?s』の『?』には数字を指定しますが、この数字は最大出力させる『精度』になります。 ・『%10s』の『10』は、最低でも10桁の空白で埋めて表示させますよね。これと併用すれば、簡単に  出力幅、最大出力桁数などを制御できます。 ・詳しくは、『printf』関数の書式指定のマニュアルをよく読みましょう。 ・ただし、実装例で解説していないため、多くの人(初心者)が理解できずに使いこなせません。 ・また、中級者でもその存在を知らない場合があるため、『知名度』が低いようですね。 ・参考。http://www.bohyoh.com/CandCPP/C/Library/fprintf.html→『(c) 精度(precision)』の項目。 余談: ・Win32 APIの『wsprintf』系には、上記の『ピリオド指定』ができません。すごく不便です。 ・C言語の関数 『sprintf』系には、上記の『ピリオド指定』ができる為、すごく便利ですね。 ・以上。おわり。→『書式指定』をもう一度、お勉強しましょう。

参考URL:
http://www.bohyoh.com/CandCPP/C/Library/index.html
  • yonfa
  • ベストアンサー率52% (22/42)
回答No.2

char kumiai_kubun[1] に格納されている値を判定したいのであれば、 添え字は0ですね。 if ( bufp->data.kumiai_kubun[0] == '1' ){  // '1'の場合 } else{  // '0'の場合 } コンパイルエラーが発生したのなら、そのエラー内容も書いてもらえるとより詳しい回答が得られると思いますよ。

yano-kouichi
質問者

補足

判定処理は成功しました。 ありがとうございます。 あとは、エラーレコードの台帳番号と組合員番号を表示させたいのですが、bufpが全て表示され、うまくいきません。 よろしくおねがいします。 fprintf(stderr, "台帳番号:%s 組合員番号: %s の組合区分が不正です\n", bufp->data.daicyo_bango, bufp->data.kumiaiin_bango); 正式メッセージ 台帳番号:1100920001 組合員番号: 00000の組合区分が不正です」

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

●構造体の中の、char kumiai_kubun[1]が、'0'および'1'になっているかの参照方法。 if ( bufp->data.kumiai_kubun[1] == '1' ){  // '1'の場合 } else{  // '0'の場合 } ●組合区分の判定処理 if ( bufp->rawdata[42] == '1' ){  // '1'の場合 } else{  // '0'の場合 } ・この質問の回答は、上記の事で良いのですか?

yano-kouichi
質問者

補足

そのとおりになります。 よろしくお願いします。 ちなみに、回答のやり方でコンパイルすると エラーになりました。

関連するQ&A

  • C言語のソートについて

    C言語で下記のファイルの中身を昇順と降順で出力しようとしているのですが、ソートが上手くいっていない状況です。 どなたか修正点を教えて頂けないでしょうか? 「ファイルの中身」 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 2022/11/15 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/18 16:20:18 8+8,16.000000 2022/11/17 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 「ソースコード」 #include <stdio.h> #include <string.h> #include <stdlib.h> int cmp_u(const void* a, const void* d) { return *(char*)a - *(char*)d; } int cmp_d(const void* a, const void* d) { return *(char*)d - *(char*)a; } int main() { int r,i,n; FILE* fp; char sin[9][1000]; fp = fopen("log.txt", "r"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } for (i = 0; i < 9; i++) { fscanf(fp, "%s", &(sin[i])); } fclose(fp); printf("ASC or DESC: "); scanf(" %s", &ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, 9, sizeof(char), cmp_u); } else { qsort(sin, 9, sizeof(char), cmp_d); } for (i = 0; i < 9; i++) { printf("%s\n", sin[i]); } return 0; }

  • C言語 構造体(2)

    ご質問です。 構造体で、あらかじめメンバ数を固定したものではなく、 テキストファイルを読み込んだときにメンバ数を変えて読み込みたいのです。 (カンマできりたい) aaa.txt ------------------------ あああ,いいい ------------------------ となっているときは、 tmp.nm[0]=あああ tmp.nm[1]=いいい となり、 kamoku.nm[0] kamoku.nm[1] をprintf。 aaa.txt --------------------------- あああ,いいい,ううう,えええ --------------------------- の場合は tmp.nm[0]=あああ tmp.nm[1]=いいい tmp.nm[2]=ううう tmp.nm[3]=えええ kamoku.nm[0] kamoku.nm[1] kamoku.nm[2] kamoku.nm[3] をprintf。 下記は動きません。。 よろしくお願いいたします。 #include <stdio.h> struct kamokumei { char nm[10]; }kamoku; int main(void) { int i,P,t; FILE *fp; struct kamokumei kamoku[20]; char buf[1024]; fp = fopen("aaa.txt", "r"); P=3; t=0; while( fgets(buf, sizeof(buf), fp) ){ struct kamokumei tmp; sscanf(buf, "%s", tmp.nm[t]); nm[t++] = tmp; } for(i = 0; i < P; i++) { printf("%s\n", kamoku.nm[i]); } return 0; }

  • C言語の構造体のファイルへの書き込みについて

    C言語を勉強しているものです。構造体を指定した番号の場所にファイルへ書き出し、その指定した番号の場所の構造体をファイルから読み込み表示というプログラムを作成したいのですが、うまくいかずどうしたらいいのかわかりません。説明不足ですがご教授お願いします。 ソフトはVisual C++ 2008 Express Editionを使ってます。 ↓↓↓作成ソースコード↓↓↓ #include<stdio.h> #include<stdlib.h> struct S_data{ char Name[10+1];/*名前*/ int Sex;/*性別*/ int Height;/*身長*/ float Weight;/*体重*/ }; void main(){ FILE *Fp; int pos; int Ret; struct S_data tag; memset(&tag,'\0',sizeof(tag)); Fp=fopen("aaa.dat","r+b"); if(Fp==NULL){ Fp=fopen("aaa.dat","w+b"); if(Fp==NULL){ printf("File not open\n"); exit(2); } } while(1){ scanf("%d",&pos); /*番号の入力*/ if (pos==0) break; scanf("%s",tag.Name);/*名前*/ scanf("%d",&tag.Sex);/*性別*/ scanf("%d",&tag.Height);/*身長*/ scanf("%d",&tag.Weight);/*体重*/ fseek(Fp,sizeof(tag)*(pos),SEEK_SET); fwrite(&tag,sizeof(tag),1,Fp); memset(&tag,'\0',sizeof(tag)); } while(1){ scanf("%d",&pos); if (pos==0) break; fseek(Fp,sizeof(tag)*(pos),SEEK_SET); fread(&tag,sizeof(tag),1,Fp); printf("%s\n",tag.Name); printf("%d\n",&tag.Sex); printf("%d\n",&tag.Height); printf("%d\n",&tag.Weight); memset(&tag,'\0',sizeof(tag)); } Ret=fclose(Fp); if (Ret!=0){ exit(2); } }

  • C言語の使い方を教えてください。-C言語入門者

    C言語のプログラムの処理の対象となるファイルはどこに保存したらよいのでしょうか?たとえば下記のプログラムで #include <stdio.h> #include <stdlib.h> #include <string.h> void main(void) { char *line[100], *buf; int i = 0, len, lines; FILE *fp; fp = fopen("textfile.txt", "r"); buf = calloc(128, sizeof(char)); while (i < 100 && fgets(buf, 128, fp) != NULL) { len = strlen(buf); line[i] = calloc(len + 1, sizeof(char)); strcpy(line[i], buf); i++; } fclose(fp); lines = ((i <= 100) ? i :100); free(buf); for(i = 0; i < lines; i++) printf("%s", line[i]); for(i = 0; i < lines; i++) free(line[i]); } で [textfile.txt]という名のファイルをマイドキュメントやコンパイラーを保存しているのと同じ領域に保存してコンパイラーを実行しても所要の結果が得られません。テキストにはプログラムの作り方しか書いてありません。

  • c言語でcsvファイルの処理で、処理速度が速いプログラムを書こうと思っ

    c言語でcsvファイルの処理で、処理速度が速いプログラムを書こうと思っています。 以下のようなcsvファイル、件数は約10000000件以上あるものを使います shop,ymd,gend,age,area,amt 20,2008-05-01,3,5,014,128 22,2008-05-01,2,4,015,350 : 二列目の日別、つまりymd別に最後列のamdの小計を出したいんですが、組んだプログラムを実行してみると、セグメンテーション違反ですと出てしまうんです。以下のようなプログラムを組んだんですが #include <stdio.h> #include <string.h> #include <time.h> #define MM 256 int main() { FILE *fp; char str[MM],*p1, *p2,*ymd; int num, sum; clock_t start,end; start = clock(); fp = fopen("csv.csv","r"); if(fp == NULL){ printf("ファイルが開けませんでした。\n"); return(0); } sum = 0; fgets(str, sizeof(str), fp); while(fgets(str, sizeof(str), fp) != NULL){ p1 = strtok(str, ","); p1 = strtok( NULL,","); ymd = p1; p2 = strrchr(str,','); sum[ymd] = atoi(p2+1); break; } while( fgets(str, sizeof(str), fp) != NULL && p1 != NULL){ p1 = strtok(str, ","); p1 = strtok( NULL,","); p2 = strrchr(str,','); if ( p2 != NULL ) { if(ymd == p1){ sum[ymd] += atoi(p2+1); }else{ printf("%s ,%d \n",ymd,sum[ymd]); strcpy(ymd,p1); } } } printf("%s ,%d \n",p1,sum); fclose(fp); end=clock(); printf("%.2f秒\n",(double)(end-start)/CLOCKS_PER_SEC); return(0); } うまくいきません。大体、処理速度は3秒以内を目指しています。 どなたかご教授御願いいたします。

  • c言語 iconv

    msys環境で実行して,指定されたファイルの文字コードをShift-JISに変換して表示するコードを作成しているのですがうまく表示されません.何がいけないのでしょうか.第1引数に変換対象のファイル名,第2引数にファイルの文字コードを指定しています. #include <stdio.h> #include <string.h> #include <iconv.h> int main(int argc, char *argv[]) { iconv_t conv; char src[10000]; char dst[10000]; int src_len = strlen(src); int dst_len = sizeof(dst) - 1; char *buf_in; char *buf_out; FILE *fp; fp = fopen(argv[1], "r"); if(NULL == fp) { printf("ファイルを開けません\n"); } else { while(fgets(src, 10000, fp) != NULL) { buf_in = src; buf_out = dst; /* 変換器を作成 */ conv = iconv_open("Shift-JIS", argv[2]); /* 変換 */ iconv(conv, &buf_in, &src_len, &buf_out, &dst_len); *buf_out = '\0'; /* 終末処理 */ /* 文字コード後の文字列を表示 */ printf("%s\n", dst); } /* 変換器を終了 */ iconv_close(conv); /*ファイルを閉じる*/ fclose(fp); } return 0; }

  • C言語でファイル読み書きを早くしたい。

    いつも利用させてもらって助かっています。 あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。 たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。 読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか? 下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。 なお、前提として, (1)データはスタック領域だと不足するので、ヒープ領域に確保 (2)データファイルは改行無しの一連のデータ とします。 ちなみに、環境は OS   : CentOS5.3 memory   : 6GB コンパイラ : gcc です。 よろしくお願いします。 //----------------------------------------------------- //通常バージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; FILE *fp; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } fp = fopen("filein.dat", "rb"); fread( data, sizeof( unsigned char), (int)SIZE, fp ); fclose(fp); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; } //----------------------------------------------------- //readシステムコールを使ったバージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } int fd; fd = open( "filein.dat" ); read( fd, data, sizeof(unsigned char)*SIZE); close(fd); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ FILE *fp; fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; }

  • C言語のプログラムについて

    リスト処理による挿入法で得点の降順に整列して表示する。また、整列する際に要素どうしを比較した回数も表示する。 このプログラムを作成したいのですが、ファイルを開いてからこの先どのように書けばいいのかわからなくなりました。分かる方教えてください。 実行例 番号 氏名      得点 1021 Machida Msao 100 1017 Nonaka Fujio 98 1011 Suzuki Kaoru 93 1006 kato Ichiro 91 1002 Inoue Yasuo 85 整列のための比較回数=○○回 ファイルを開くのはこのように書きました。 #include<stdio.h> #include<stdlib.h> int main(void) { struct GDATA{ int bango; char sei[11],mei[11]; int tokuten; }; struct GDATA seiseki; FILE *fp; if((fp=fopen("data-a.dat","r"))==NULL) { printf("data-a.dat OPEN ERROR!\n"); exit(1); }

  • C言語で、ファイルを読み込んで数字と名前に分けて配列に格納に関する質問

    C言語で、ファイルを読み込んで数字と名前に分けて配列に格納に関する質問です! ファイルを開いた後でエラーとなるのですが、何が足りないのでしょうか? ファイル内容 20 田中 10 鈴木 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc,char *argv[]) { FILE *fp; char str[256]; char *tp; int k,i=0; int num[10]; char na[10][20]; fp=fopen(argv[1],"r"); if(fp==NULL){ printf("ファイルを開けません\n"); return 1; }else{ printf("開けた\n"); } while(fgets(str,sizeof str,fp)!=NULL){ tp=strtok(str," "); num[i]=atoi(tp); tp=strtok(NULL," "); strcpy(na[i],tp); i++; } printf("%d\n%s\n",num[0],na[0]); printf("%d\n%s\n",num[1],na[1]); fclose(fp); return 0; }

  • 構造体の動的メモリについて

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUM 10 /*生徒数*/ typedef struct data { int num; /*従業員番号*/ char name[16]; /*名前*/ int jap; /*国語の点数*/ int math; /*数学の点数*/ }data; int main(void) { data test[NUM]; /*生徒のデータ*/ FILE *fp; /*ファイル操作用*/ int i; /*配列インデックス*/ int count; /*データ分割用*/ char s[100]; /*データ読み込み用*/ char *token; /*データ分割用*/ char *data[6]; /*分割データ保存用*/ fp = fopen ("data1.txt","r");        for (i=0; i<NUM; i++){ fgets (s, sizeof(s), fp); /*dataファイルから1行読み込み*/ token = strtok(s, ","); /*読み込んだデータを","で分割する*/ count=0; while (token != NULL){ data[count] = token; /*分割したデータを配列へ入れる*/ token = strtok(NULL,","); count++; } test[i].num = atoi(data[0]);       strcpy (test[i].name, data[1]); test[i].jap = atoi(data[2]); test[i].math = atoi(data[3]); } fclose(fp);       } このプログラムを構造体へのポインタの配列で管理するように変えたいのですが、どのように変更すればいいのでしょうか。 条件として、個人データを格納するメモリ領域とポインタの配列のメモリ領域は動的に確保します。 初心者でよくわからないので詳しく教えていただけると助かります。よろしくお願いします。

専門家に質問してみよう