• ベストアンサー

配列を返す

ファイルから読み込んだ一行の文字列を読み込みカンマごとに区切って 返すというプログラムを関数化することで効率を図りたいと思います。 int main() { char buf[1000]; char *str; char *bufG; //ファイルを読み込む  while(fgets(buf,1000,fp) != NULL){//一行ずつ読む str = buf;//先頭アドレスを指す     bufG = //文字列を返す関数  ・  ・  ・ } } //文字列を返す関数 {    for(i = 0; *str != ',' && *str != '\0'; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return bufG; } 前の質問で自動変数でこの関数を抜けたら廃棄になるというのは わかったんですが(そういう警告がでました) ここからどのようにすれば求めるプログラムになりますか? 引数とかちょとわからないので関数定義を書きませんでした。 (1)ファイルをよみこむ (2)一行ずつ読み込み文字列をbufにいれる (3)ポインタstrをbufの先頭アドレスにする (4)get_word関数にてポインタをずらしていき カンマがあればそこまでの文字列を返す (5)main関数に戻り変数に代入する (6)終端文字があるまで(4)ー(5)を繰り返す。 (7)さらに行数分繰り返す これらの一連の流れをやりたいのですが わかりません。

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

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.6

bufGとstrをパラメータで渡す方法です。 get(char bufG[],char **p_str)の bufGの定義は理解できるかと思います。 strは関数側でも、参照し、更新するために、strのアドレス(ポインタのポインタ)を渡す必要があります。 以下、実装例です。 ------------------------------------ #include <ctype.h> #include <string.h> #include <stdio.h> //Linuxなので追加 #include <stdlib.h> void swap(char p[], char q[]); void get(char bufG[],char **p_str); //ここを変更 typedef struct { int number; char *class_type; char* name; char *subject; } my; my *data; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000]; char bufG[1111]; //こちらに戻し char *str; //同上 int m; int line2 = 0; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); printf("%d\n", line2); if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ str = buf; while(*str != '\0'){ get(bufG,&str); //ここを変更 switch(field){ case 0: data[line].number = atoi(bufG); break; case 1: data[line].class_type = (char *)malloc(strlen(bufG) +1); strcpy(data[line].class_type, bufG); break; case 2: data[line].name = (char *)malloc(strlen(bufG) + 1); strcpy(data[line].name, bufG); break; case 3: data[line].subject =(char *)malloc(strlen(bufG) + 1); strcpy(data[line].subject, bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); for(m = 0; m < line; m++){ //ここを変更 printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); } return 0; } void get(char bufG[],char **p_str) //ここを変更 { int i; char *str; //追加 str = *p_str; //追加 for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; *p_str = str; //追加 return ; } -------------------------- centos5.3 gcc4.1.2で動作確認済みです。 不明点があれば、補足して下さい。

rooding
質問者

補足

現在、関数はvoid型ですが char*型で文字列を返すようにはできませんか?

その他の回答 (12)

noname#113783
noname#113783
回答No.13

4度目ですが失礼します。char*型で文字列を返す、ですね?それなら 1.サブルーチンでstatic(プログラム終了まで生きる)をつけたchar配列を宣言 2.戻り値の型は char * 3.受け取る変数の方もchar * 《ソ-ス》 #include <stdio.h> char* test(){ static char hai[20]={"あいうえお"}; return hai; } void main(){ printf("%s",test()); } 《結果》 あいうえお こんな感じです。詳しい情報は↓のサイトにあります。

参考URL:
http://www.geocities.jp/ky_webid/c/030.html
noname#113783
noname#113783
回答No.12

前回の回答ですが、ソースコードの最後のreturnがretuenになっていました。修正してください。

noname#113783
noname#113783
回答No.11

前の回答の続きです。 読解力ないのであってるかわかりませんが、 1.main関数内でbuf[1000]を宣言。サブル-チンにポインタとして渡す。 2.ファイルの内容を調べていき、 ',' があるまで文字列をbufに入れていき、 ',' があったらbufに '\0' を追加して終了。ファイルの文字が "\0"(終端) だった場合はもう自分(サブル-チン)を呼び出さないようにする。 3.main関数でbufの情報を使い(例としてprintfに出力します)、またサブル-チンを呼び出す。サブル-チンは前回あった ',' の次からファイルを調べ、2.を繰り返す。 このプログラムだとファイルの内容から ',' を抜いたものが画面に出力されます。 《ソ-ス》 #include <stdio.h> int FileRead(FILE *fp,char *bufS){ int i=0; //カウンタ while( (bufS[i]=fgetc(fp))!=','){ if(bufS[i++]==EOF){ //ファイルの終端なら bufS[--i]='\0'; return 1; } } bufS[i]='\0'; return 0; } int main(){ char buf[1000]={0}; //0はFileRead()内のル-プの為 FILE *fp=fopen("rrr.txt","r"); while(1){ if(1==FileRead(fp,buf)){ //配列名の指定でbufの先頭ア //ドレスが渡される(配列はただのポインタ) printf("%s",buf); return 0; } else{ //ファイルの終端なら↑のif実行、それ以外ならelse printf("%s",buf); } } retuen 0; } 《ソ-スここまで》 fgetcを使いました。main関数にある配列bufの先頭アドレスをサブル-チンFileReadに渡してFileRead内でポインタ参照しています。何度も言います配列はただのポインタ、正確には「アドレス定数」というものです。要するに、値の変えられない(定数)ポインタです。下の配列を例にします。 char buf[10]; これが内部ではこうなります。 1.char型かける10のメモリが確保される。 2.const char *buf=[1.]で確保したメモリの先頭アドレス; ←このようなアドレス定数(constのついたポインタそれがアドレス定数であり配列である)が用意される。 関数にbufを渡すとbufの中身(buf[]の先頭アドレス)が渡されます。受け取る側でポインタ型(char *型)で受け取れば、もう自由にFileRead関数内からbufを扱えます。ちなみに配列についてる[]はアドレス計算の演算子です。配列はアドレス定数なので(*hairetsu)+2といった参照の仕方や確保している要素以上の要素数を指定してもコンパイラは何も言いません(少なくともVC++では)。詳しくはポインタについて解説しているサイトを見てみてください。 説明へたでゴメンネ。

noname#113783
noname#113783
回答No.10

配列を戻り値として利用する方法を教えるのでいいですか?まず結論から言います、構造体に配列を入れてその構造体を戻り地にします。 配列を戻り値にできない理由を説明します。構造体を参照する時に構造体名のみを示すと、その構造体全体があるメモリを示していることになります。ここが配列との違いです。配列は要素の型が同じなので、要素1つの型の情報を持っていれば個々の要素にアクセスできます。なので配列はポインタで実装され、配列全体の大きさが分かる情報は持っていません。しかし、構造体は個々の要素の型の情報を持っていないと要素に正しくアクセスできません。なのでポインタでは現せないので、個々の要素の情報を持っています。その情報を使えば構造体全体がどれだけの大きさなのかが分かります。よって構造体には構造体全体を参照できる機能が付いているのです。また最近のコンパイラは最適化が行われるので,変数より構造体のほうが遅いということは少なくなっています。構造体の使用ををためらうことはありません。配列を以下のように struct A{ char buf[1000]; },bufS とサブルーチンで宣言し、関数の戻り値の型を struct A にし、返す時は return bufS; として返すとができます。受け取るほうの変数はstruct A型の構造体でもいいし、char bufmain[1000]でもいいと思います。後者は検証してないので分かりませんが。つまり配列1つだけがメンバの構造体は、配列全体の大きさの情報を持っている配列、といえます。でもこんなことをするより配列名(配列名はただのポインタ)を渡して配列の先頭アドレスを渡し、ポインタとしてサブルーチンからmainにあるbuf[1000]を遠隔操作したほうが高速だと多分思いますよ。わからんけど。その方法は次の回答で

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.9

ちょっと間違ってました。以下2ケ所を修正します。 p = (char **) malloc(sizeof(char*) * (n + 2)); // +1 → +2 p[n] = NULL; // *p[n] → p[n] メインのほうね・・・ while(fgets(buf,1000,fp) != NULL){//一行ずつ読む   char *p[] = bufG(buf);   for ( int i = 0 ; p[i] ; i++ ) { //1ブロックずつの処理     //p[i]←ブロックへのポインタ     printf("%d\n",p[i]); //表示例   }   free((void *)p);//ポインタ領域を解放 } ポインタのポインタなんて、日常茶飯事ですよ。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.8

え~と, 「現在、関数はvoid型ですが char*型で文字列を返すようにはできませんか?」 「つまりはchar*型で関数を宣言してフィールドの値を返すようにすることですね」 と書かれてますけど, もっときちんと仕様を出してくれないことにはこの辺のリクエストには答えようがありません. ・関数の引数は何ですか? ・関数の返り値は何ですか? ・この関数はどのような機能を持っているのですか? でも「フィールド」ってなんだろう.

rooding
質問者

補足

いや引数や返り値がわからないので関数を作れないんですよ。 今まで作っていたプログラムの一部をvoid型の関数に押し込むってのは できます。フィールドはCSVファイルのことを知らない人はわからないかもしれません。関数の機能はさんざんでているとおもいます。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.7

>現在、関数はvoid型ですが >char*型で文字列を返すようにはできませんか? void get(char bufG[],char **p_str) の char bufG[]のパラメータが、その主旨になっています。 つまり、このバッファに文字列が返ります。 どうしても、バッファのアドレスをreturnで戻したいのであれば 以下のようにします。(そうする意味がないのでやりたくないのですが・・・) char *get(char **p_str)として、 static bufG[1111];をこの関数内に確保します。 戻るときに、このバッファのアドレスで戻ります。 return bufG;とします。 呼び出し側は、 char *bufG;として bufG = get(&str); とします。

rooding
質問者

お礼

やりたくないことさせてしまって申し訳ないです。 でもありがとう。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.5

関数化する時に、最も簡単なのは、パラメータを持たせず、呼び出し側(main)と関数側(get)の両方から参照/更新できる領域を使用する方法です。 以下にその方法で実装したコードを書きます。(前の質問のソースを使用) ---------------------------------- #include <ctype.h> #include <string.h> #include <stdio.h> //Linuxなので追加 #include <stdlib.h> void swap(char p[], char q[]); void get(void ); //ここを変更 typedef struct { int number; char *class_type; char* name; char *subject; } my; my *data; char bufG[1111]; //ここで定義する(mainとgetの両方で参照/更新可能となる) char *str; //ここで定義する(同上) int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000]; //ここを変更 //char *bufG; //削除 int m; //ここを追加 int line2 = 0; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); printf("%d\n", line2); if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ str = buf; while(*str != '\0'){ get(); //ここを変更 switch(field){ case 0: data[line].number = atoi(bufG); break; case 1: data[line].class_type = (char *)malloc(strlen(bufG) +1); strcpy(data[line].class_type, bufG); break; case 2: data[line].name = (char *)malloc(strlen(bufG) + 1); strcpy(data[line].name, bufG); break; case 3: data[line].subject =(char *)malloc(strlen(bufG) + 1); strcpy(data[line].subject, bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); for(m = 0; m < line; m++){ //ここを変更 printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); } return 0; } void get(void) //ここを変更 { int i; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return ; //ここを変更 } ------------------------------------------ linux(centos5.3 gcc4.1.2)で動作確認済みです。 但し、この方法は、今回の質問の趣旨に沿わないかも知れませんが、このようなやり方もあるということを覚えておいて損はありません。 実際に、関数の引数の数が多すぎて、関数の呼び出しのオーバーヘッドが大きい場合は、処理の高速化の為に、パラメータを一切渡さず、両方で、参照更新できる変数を設ける方法をとります。 しかしながら、そうはいっても、パラメータを使用する方法が知りたいと言うのが、質問の趣旨かと思いますので、次の回答で、その方法を書きます。(要はstrとbufG)がパラメータになれば良いわけです。

rooding
質問者

補足

目的は他の人にもこの関数を応用できるようにするということなので ファイルから読み込んだ一行の文字列の各フィールドを格納する関数にしたいのです。つまりはchar*型で関数を宣言してフィールドの値を返すようにすることですね。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

あなたは「なぜそこでエラーになるのか」を考えたのですか? ヒント: *p[n] の型は?

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.3

こんなソースコードを書いたところ、これこれこういうエラーが出ました。どこがおかしいのでしょうか? という質問とともにソースコード全文を載せてくださると、 もしかしたらお力になれたかもしれません。 しかし、今回はそういう状況ではなく単に答えをほしがっているだけのようです。 その場合、残念ですが私は力不足です。お役に立てそうもありません。 大変申し訳ありません。

関連するQ&A

  • 配列のコピー

    配列bufの内容をstrにコピーしてgetsを使い 表示させたいのですが、うまくいかず 余計な文字まで出力されます、どのようにすれば うまくいくでしょうか? どなたかアドバイスよろしくお願いしますm(_ _)m #include <stdio.h> void main(){ char buf[256]="message"; char str[256]; int i = 0; while(buf[i] != NULL){ str[i] = buf[i]; i++; } printf(str); }

  • ポインタ

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> typedef struct { char number[6]; char class_type[20]; char name[8]; char subject[5]; } my; my data[100]; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i; if((fp=fopen("test.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; // printf("%s", bufG); switch(field){ case 0: strcpy(data[line].number, bufG); break; case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; } field++; } else{ str++; } } line++; field = 0; } printf("%s", data[2].subject); fclose(fp); return 0; } このプログラムをベースにしてメモリの無駄を省けるような プログラムに修正したいのですが、 ポインタほんとできなくて困ってます。 教えていただいてメモリを取る位置とかは大体わかりました。 まず構造体のメモリをとります。しかしこのままでは固定長になってるので 構造体を少しいじくりますよね。 構造体の中身なのですが typedef struct{ int number; char *class_type; char *name; char *subject; } my; my *data; にして data = malloc(100); このような形でとります。 文字列の型ですがchar *class_typeのようにポインタで宣言しないと bufGを代入して値を入れるときに型が合いませんので 配列にしないのであればポインタ型宣言でいいと思います。 しかしポインタで宣言してstrcpy(・・)の所を data[line].class_type = bufG にするとエラーはでませんが*strの値が変わる度に data[line].class_typeの値が変動するのでdata[line].class_typeが 国語 とかになったりします。 なんかもうさっぱりわからないんですが どうすればいいのでしょうか? 変換したソースがほしいです。

  • メモリ

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> int check(int a[100], int n); typedef struct { char number[6]; char class_type[20]; char name[8]; char subject[5]; } my; my data[100]; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; switch(field){ case 0: strcpy(data[line].number, bufG); break; case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; } field++; } else{ str++; } } line++; field = 0; } int p, q; int a[100]; int u = 0; for(p = 0; p < line; p++){ for(q = 0; q < line; q++){ if(strcmp(data[p].class_type, data[q].class_type) == 0 && strcmp(data[p].subject, data[q].subject) == 0 && p != q ){ //処理 } } } } fclose(fp); return 0; } 先日文字列入れ替えについてご質問したものですが メモリの取り方についてご質問します。 先日このプログラムにおいて my data[100]と固定してるのはいけないという意見をもらったので メモリを取得しようと思ってるのですが できればdata[i].○○の形でアクセスしたいのでこのままの形は あまりかえたくないです。この場合 while(fgets(buf,1000,fp) !=NULL){ str=buf;     int len = strlen(buf); my *o; o = (my *)calloc( len + 1, sizeof(my *)) while(*str != '\0'){ としてみたのですがこれは実際どうなのでしょうか? NULLは帰ってきてないみたいなので割り当ては出来てるとは思うんですが この一行の文字列の大きさにぴったり合うメモリを割り当てたいのですが ちゃんとなっているか調べる方法を教えて下さい。

  • switchとメモリ取得位置

    #include <stdlib.h> #include <string.h> #include <ctype.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE -1 char* get(char **p_str); char *get_line(char buf[]); int comp_rtn(const void *p1, const void *p2); typedef struct { int number; char class_type[10]; char name[15]; char subject[10]; int ten; } my; my *data; void myswap(my *p, my *q); int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufFormat; char *bufG; bufG = (char *)malloc(1000); if(bufG == NULL){ printf("メモリ不足"); free(bufG); } int line2 = 0; if((fp=fopen("jjj.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); if((fp=fopen("jjj.txt","r"))==NULL){   printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); if(data == NULL){ printf("メモリ不足"); free(data); } while(fgets(buf,1000,fp) != NULL){ bufFormat =(char *)malloc(strlen(buf) + 1); if(bufFormat == NULL){ printf("メモリ不足"); free(data); } bufFormat = get_line(buf); str = bufFormat; while(*str != '\0'){ bufG = get(&str); switch(field){      case 0: data[line].number = atoi(bufG); break case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; case 4: data[line].ten = atoi(bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); qsort(data,line,sizeof(my),comp_rtn); for(int m = 0; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); printf("%d\n", data[m].ten); printf("\n"); } free(data); return 0; } void myswap(my *p, my *q) { my temp; temp = *p; *p = *q; *q = temp; } char *get(char **p_str) { int i; char *str; str = *p_str; static char bufG[1000]; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else if(*str == '\\'){ str++; if(*str == 'c'){ bufG[i] = ','; } else if(*str == '"'){ bufG[i] = '"'; } } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; *p_str = str; return bufG; } char *get_line(char buf[]) { int in_quotation = FALSE, i = 0; char* str = buf; static char bufG[1000]; while(*str != '\0'){ if(*str=='"'){ if(in_quotation == TRUE){ str++; if(*str == '"'){ bufG[i] = '\\'; i++; bufG[i] = '"'; i++; } else{ in_quotation = FALSE; bufG[i] = *str; i++; } } else{ in_quotation = TRUE; } } else{ switch(*str){ case '\n': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'n'; i++; } else{ bufG[i] = *str; i++; } break; case ',': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'c'; i++; } else{ bufG[i] = *str; i++; } break; default: bufG[i] = *str; i++; } } str++; } bufG[i] = '\0'; return bufG; } 構造体メンバをポインタで宣言する方法はもうできていて 配列の方も組んでいるのですが 比較関数など所々省いてますがこのプログラムに対し以下のことをいわれました 1,switch文のfieldの値を数字じゃなく分かりやすいのに変えよ 2,mainのすぐしたの bufG = (char * )malloc(1000)が なかなか使用されないのにここでメモリを取るのはおかしい 3,これを使うまでの間にエラーが発生したときのfreeがない と言われました。 1ですが確かCではswitch文のcase式は整数型定数でなければならない とあるので無理な気もするのですが、方法ありますか? 2に関してはよくわかりません。効率がよくないのでしょうか? どの場所がいいのでしょうか 3に関してはどういうことなのかもわかりません。 この3点について教えて下さい。

  • 二次元配列による文字列の配列の受渡しについての質問です。

    二次元配列による文字列の配列の受渡しについての質問です。 #include <stdio.h> void print_pname(char str[][5], int n) { int i, j; for (i = 0; i < n; i++) { printf("str[%d] = \"", i); for (j = 0; str[i][j] != '\0'; j++) putchar(str[i][j]); printf("\"\n"); } } int main(void) { char ary[][5] = {"Lisp", "C", "Ada"}; print_pname(ary, sizeof(ary) / sizeof(ary[0])); return 0; } 上のプログラム中の関数print_pnameの引数char str[][5]についてですが char (*str)[5](配列のポインタ)と変更した場合にwarningが多数発生します。 これはどうしてでしょうか? また、上のプログラムを配列のポインタを使って変更することは可能でしょうか? 以上、よろしくお願いします。

  • 配列の練習問題

    #include<iostream> using namespace std; //count関数の宣言 int count(char str[], char ch); int main() { char str[100]; char ch; cout << "文字列を入力して下さい。\n"; cin >> str; cout << "文字列から探す文字を入力して下さい。\n"; cin >> ch; int c = count(str, ch); cout << str << "の中に" << ch << "は" << c << "個あります。\n"; return 0; } //count関数の定義 int count(char str[], char ch) { int i = 0; int c = 0; while (str[i]) { if (str[i] == ch) c++; i++; } return c; } こんにちは。 この問題の解答のプログラムの意味がイマイチ解らないので良かったら教えて下さい。 確認がてらに質問します。 よろしくお願いします。

  • CArray

    #include <ctype.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE -1 char* get(char **p_str); char *get_line(char buf[]); int comp_rtn(const void *p1, const void *p2); typedef struct { int number; char class_type[10]; char name[15]; char subject[10]; int ten; } my; my *data; void myswap(my *p, my *q); int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufFormat; char *bufG; int line2 = 0; if((fp=fopen("jjj.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); if((fp=fopen("jjj.txt","r"))==NULL){   printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ bufFormat = get_line(buf); str = bufFormat; while(*str != '\0'){ bufG = get(&str); switch(field){      case 0: data[line].number = atoi(bufG); break case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; case 4: data[line].ten = atoi(bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); qsort(data,line,sizeof(my),comp_rtn); for(int m = 0; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); printf("%d\n", data[m].ten); printf("\n"); } free(data); return 0; } void myswap(my *p, my *q) { my temp; temp = *p; *p = *q; *q = temp; } char *get(char **p_str) { int i; char *str; str = *p_str; static char bufG[1000]; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else if(*str == '\\'){ str++; if(*str == 'c'){ bufG[i] = ','; } else if(*str == '"'){ bufG[i] = '"'; } } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; *p_str = str; return bufG; } char *get_line(char buf[]) { int in_quotation = FALSE, i = 0; char* str = buf; static char bufG[1000]; while(*str != '\0'){ if(*str=='"'){ if(in_quotation == TRUE){ str++; if(*str == '"'){ bufG[i] = '\\'; i++; bufG[i] = '"'; i++; } else{ in_quotation = FALSE; bufG[i] = *str; i++; } } else{ in_quotation = TRUE; } } else{ switch(*str){ case '\n': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'n'; i++; } else{ bufG[i] = *str; i++; } break; case ',': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'c'; i++; } else{ bufG[i] = *str; i++; } break; default: bufG[i] = *str; i++; } } str++; } bufG[i] = '\0'; return bufG; } 以前上記のソースになるプログラムの質問をいくつかしました。 これはCで組んでますがC++で組みなおすに当たり 今mallocを使っていますがCArrayを使用するように薦められました どういう感じになるのかさっぱりわかりません。

  • 一番大きい奇数を表示する

    scanf関数を使用して、文字列を10回入力し一番大きい文字列を表示するプログラムを作ったのですが、 一番大きい「奇数」を表示するように条件を加えた場合どうすればよいのでしょうか? 偶数=割り切れる 奇数=割り切れない ということまでは分かるのですがその先が分かりません。 一応一番大きい文字列を表示するプログラムを貼っておきます。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } if (strcmp(buf, str) > 0) { strcpy(str, buf); } printf("output>\n%s\n" , str); getchar(); }

  • 配列の参照渡し

    以下のC言語のプログラムを教えてください。 お願いします。 (1)標準入力から文字列(2 文字以上)を入力し,文字数を計上すると共に,入力された文 字列の逆順に入れ替える処理を実現せよ.なお,以下の要件を満たしたプログラムを作 成すること. ・ 入力された文字列は,char 型の配列(要素数50)で受け取ること ・ 文字数を計上するcount 関数(引数:配列のアドレス,戻り値:文字数)を定義 し,main 関数より呼び出すこと ・ 文字列を逆順に入れ替えるreverse 関数(引数:配列のアドレス,戻り値:無し) を定義し,main 関数より呼び出すこと ・ 標準出力の処理は,main 関数で記述すること 【プロトタイプ宣言】 int count(char *str); void reverse(char *str); 【実行結果】 文字列を入力してください(2 文字以上) apple 文字数 = 5 入れ換え前 apple 入れ換え後 elppa $ ---------------------------------------------------------------------------- (2)char 型の配列(要素数50)を2 つ宣言し,標準入力から2 つの文字列を入力せよ. そして,格納した字列を入れ替える関数(swapstr 関数)を作成し,入れ替え前と入れ替 え後の配列内の値(文字列)を配列名とともに標準出力するプログラムを作成せよ. 【プロトタイプ宣言】 void swapstr(char *str1, char *str2); 【実行結果】 2 つの文字列を入力してください apple strawberry 入れ換え前 配列str1 = apple 配列str2 = strawberry 入れ換え後 配列str1 = strawberry 配列str2 = apple

  • 一番大きい奇数を表示する

    scanf関数を使って数字を10回入力して一番大きなものを表示させるプログラムをつくったのですが、 さらに一番大きな奇数を表示するにはどうすればいいのでしょうか? 偶数=割り切れる 奇数=割り切れない というところまでは分かるのですが、以下のプログラムに奇数を判別するソースを追加するのにはどうすればいいのでしょうか。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; int w; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } for (i = 0; i < 10; i++) { if ((buf[i] & 1) == 1) /* 奇数であるか */ { if (strcmp(buf, str) > 0) { strcpy(str, buf); } } } printf("output>\n%s\n" , str); getchar(); }