• ベストアンサー

2次元配列

課題で、氏名をローマ字で入力し、2次元配列に格納するプログラムを作成するというのがでました。条件として、氏名の長さは10文字以下、最大件数は10件。1エントリ入力ごとに累計件数を表示し、10件目の入力が完了するか、氏名の一文字目に'0'が入力されたら入力を終了しデータを表示する。11文字以上入力されたら、先頭から10文字までを有効とし、11文字目以降を無視する。 改行のみの入力の場合、エラーメッセージを表示し、再入力させる。 初心者の私には、データの表示と、条件の処理の仕方がわかりません。 下記プログラムを上記の条件を満たすようにするには、どこを直したらよいか教えてください。 お願いします。 #include <stdio.h> #include <string.h> #define BUFFERSIZE 1024 main() { char str[10][BUFFERSIZE]; char c; int count = 0; int i; int j; int l[10]; /*氏名の入力*/ for (i = 0; i < 10; i++) { printf("氏名人力 : "); while ( (c = getchar()) != '\n' ) { if( count < BUFFERSIZE - 1 ){ str[i][count++] = c; } } str[i][count] = '\0'; printf("累計 : %d \n", i+1); } for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { printf("%c",str[i][j]); } putchar('\n'); } return 0; }

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

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

★アドバイス ・『getchar』関数は改行が入力されるまで制御が戻りません。 ・よって『fgets』関数で文字列として入力(取得)します。 ・改行のみの入力は、文字列の最初が '\n' になるのでエラーメッセージを表示します。 ・文字列で取得したら str[i] の領域に最大 10 文字までをコピーします。 ・あと、getchar 関数は -1 を返しますので int 型で c を宣言します。 ・文字列の最初が '0' ならば入力を終了します。→『break』命令で while 文を抜けます。 ・表示部分は大体あっていますね。→printf を使えばもっと楽です。 ●サンプル int main() {  char tmp[BUFFERSIZE]; ←追加  char str[10][11]; ←11で十分  int count = 0;  int i;  int j;  int l[10]; ←いらないよ    for ( i = 0 ; i < 10 ; i++ ){   printf("氏名入力 : "); ←タイプ・ミス!      while ( fgets(tmp,sizeof(tmp),stdin) != NULL ){ ←文字列で入力    if ( tmp[0] == '\n' ){ ←改行のみの入力     printf( "エラーメッセージを表示\n" );     continue; ←再入力    }    if ( tmp[0] == '0' ){ ←入力を終了     goto input_end;    }    for ( count = 0 ; count < 10 ; count++ ){ ←先頭から10文字までを有効     if ( tmp[count] == '\n' ){ ←なぜか分かりますか?      break;     }     str[ i ][ count ] = tmp[ count ];    }    str[ i ][ count ] = '\0';    break;   }   printf("累計 : %d \n", (i + 1) );  } input_end:  for ( j = 0 ; j < i ; j++ ){ ←入力数のみ表示   printf( "%s\n", str[j] );  }  return( 0 ); } 最後に: ・データ入力部分、データ表示部分を分けて考えましょう。 ・getchar、printf、fgets 関数の動作をきちんとお勉強しましょう。

その他の回答 (1)

  • nerosuke
  • ベストアンサー率33% (39/115)
回答No.1

課題のまる振りはこのサイト駄目だと思いますよ。 まるふりじゃないみたいですけど。 なので一応ヒントです。 とりあえず スタック使い過ぎです! char str[10][BUFFERSIZE]; これは外に出す、そもそも10文字指定があるなら1024も要らない。 そして初期化してください。 printf("氏名人力 : "); -> printf("氏名入力 : ");に直す! 11文字目を判断するには、 countで条件分岐。 countをどこかで初期化してください。 '0'の判断はgetchar()で受け取った値で条件分岐。 for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { printf("%c",str[i][j]); } putchar('\n'); } これは一文字ずつ出力しないで、%sを使用したほうが良い。

関連するQ&A

  • 構造体

    下記プログラムの2次元配列を構造体の配列に作り変え,構造体を利用して生年月日の項目を追加し,形式は日を除いたYYYY/MMで持ち,生年月日の入出力は,YYYY/MM形式で行い,西暦が数字4桁で,西暦と月の間に'/'があり,月が01~12の範囲の数字の2桁になっている7文字の入力のみ受け付け,正しく入力されるまでそれ以外は再入力させたい。あとdo-while文をつかっている箇所をwhile文に直したいです.自力でやったのですが,わかりませんでした. どのようにしたらよいか教えてください. お願いします. include <stdio.h> #define BUFFERSIZE 11 #define MAX_PERSON 10 #define MAX_CHARS 10 int main(void) { char name[10][BUFFERSIZE]; int c; int count = 0; int i; int j; for (i = 0; i < MAX_PERSON; i++) { printf("氏名入力 : "); j = 0; /* 氏名の1文字目が'0'なら入力を終了 */ if ((c= getchar()) == '0'){ break; } if (c == '\n') { /* 改行のみの入力は再入力 */ do { printf( "再入力\n" ); /*再入力*/ printf("氏名入力 : "); } while ((c = getchar()) == '\n'); } name[i][j++] = c; /*1文字目を格納*/ if (name[i][0] == '0') { break; } while ((c = getchar()) != '\n' && c != EOF) { if (j < BUFFERSIZE - 1) { name[i][j++] = c; } } name[i][j] = '\0'; count++; /* 実際に入力した人数を記録*/ printf("累計 : %d \n", count); } /* 氏名と生年月日を出力したいです */ for (i = 0; i < count; i++) { for (j = 0; j < MAX_CHARS; j++) { if (name[i][j] == '\0'){ break; } putchar(name[i][j]); } putchar('\n'); } return 0; }

  • 動的なメモリ管理(複数の使用済みのメモリブロックの解放)

    氏名をmalloc()した配列に格納後,氏名アドレスと生年月日を組み合わせた構造体をさらにmallocし,そのアドレスをポインタ配列に登録していく。生年月日は,YYYYMMDD形式でキーボード入力されたデータを数値変換してlong型の構造体メンバーに格納する。 下記のプログラムでどこで使用済みのメモリブロックを解放すればよいか教えてください。お願いします。 #include <stdio.h> #include <string.h> #include <stdlib.h> #define DEBUG 0 /* debug mode 0:off 1:on */ #define BUFFERSIZE 11 #define MAX_PERSON 10 #define MAX_CHARS 10 #define BBUFFERSIZE 8 // YYYYMMDD typedef struct { char *name; //氏名 long birth; // 生年月日 YYYYMMDD }PERSON; int main(void){ char str[BUFFERSIZE]; /*氏名一時保存の配列,*/ char *st; //氏名保存配列 PERSON *person[MAX_PERSON]; /*構造体のアドレスを保存する配列*/ PERSON per[MAX_PERSON];//構造体保存配列 char bir[BBUFFERSIZE]; int count; int i; int j; int l; //文字列の長さ int top_index = 0; int bot_index; int day; int mon; int num ; int ch; char *tmp; printf("*** 入力された氏名をソートし、表示します ***\n"); printf("*** 最大入力件数10件(1文字目'0'で入力終了) ***\n"); putchar('\n'); for (i = 0; i < MAX_PERSON ; i++) { printf("氏名入力(10文字まで有効) > "); //氏名をmalloc()した配列に格納 fgets(str, BUFFERSIZE, stdin); l = strlen(str); if (str[l-1] == '\n'){ str[l-1] = '\0'; } else { while ( getchar() != '\n'){ } } if (str[0] == '0'){ break; } st = (char*)malloc(sizeof(char) * (strlen(str)+1)); strcpy(st,str);//\0も含まれてコピー printf("累計 : %d\n", i+1); //氏名アドレスと生年月日を組み合わせた構造体をmalloc() //そのアドレスをポインタ配列に登録 per[i].name = st; //生年月日入力 printf( "生年月日入力(YYYYMMDD) > " ); while(1){ l = 0; while ((ch = getchar()) != '\n' && ch != EOF) { if (l < 8) { bir[l] = ch; } l++; } num = 0; //数値に変換してlong型の構造体のメンバに保存 for ( j = 0; j < 8; j++){ num = num * 10 + (bir[j] - '0'); } printf("num : %d\n",num); per[i].birth = num; break; } person[i] = (PERSON*)malloc(sizeof(per[i])); person[i] = &per[i]; } count = i; printf("データ表示\n"); for (i = 0 ;i < count ; i++ ){ printf("%d : %s\n", i+1, person[i]->name); printf("%08d\n", person[i]->birth); } return 0; }

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

    二次元配列による文字列の配列の受渡しについての質問です。 #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が多数発生します。 これはどうしてでしょうか? また、上のプログラムを配列のポインタを使って変更することは可能でしょうか? 以上、よろしくお願いします。

  • C言語 文字列の操作

    文字Cが含まれる個数を求めたいです #include <stdio.h> int str_chnum(const char str[],int c) { int i; int count=0; for(i=0;str[i]!="\0";i++) if (str[i]==c) count++; return(count); } int main(void) { char st[100]; printf("検索文字列を入力してください:"); scanf("%s",st) ; printf("検索文字列数は%uです。\n",st,int str_chnum(const str[],int c)); return(0); } コンパイルできません。なぜですか?printfの行がたぶん間違っていると思うんですが。。。

  • 配列の中身が変わってしまいます

    英単語中のアルファベットの数を数えるプログラムをCで作っています。 ------------------------------------------------ #include<stdio.h> #include<stdlib.h> #include<string.h> #define NS 69964 /* 入力の最大数 */ #define WC 64 /* 入力の1行の文字数 */ int main(int argc, char *argv[]) { FILE *fp; char str[NS][WC]; int al[NS][26] = {0}; int i, j, k; //コマンドライン引数でテキストファイルを読み込む fp = fopen(argv[1],"r"); //テキストファイル内の単語を1行ごとにstr[]に格納 //改行文字は除き,大文字は小文字にする for(i = 0; i < NS; i++){ fgets(str[i], WC, fp); strtok(str[i], "\n"); for(j = 0; j < WC; j++) str[i][j] = tolower(str[i][j]); } printf("File reading completed.\n"); //カウントする //'a'~'z'の数がal[][0]~al[][25]の値に対応 //例えば'a'が2個,'z'が3個ならal[][0]=2,al[][25]=3 for(i = 0; i < 5; i++) for(j = 0; j < 20; j++) al[i][str[i][j] - 'a']++; //al[][]の中身を表示 for(i = 0; i < 5; i++) for(j = 0; j < 26; j++) printf("al[%d][%d]:%d\n", i, j, al[i][j]); fclose(fp); return 0; } -------------------------------------------------- for(i = 0; i < 5; i++) for(j = 0; j < 20; j++) al[i][str[i][j] - 'a']++; の処理を終えた後、al[][]の中身を見てると al[][7]の値だけがおかしいのです。'h'の数を数えているはずなのですが・・・ for文中でprintfしてみたのですがこのときは正しく数えられています。 ですがfor文を抜けた途端al[][7]の値が変わってしまいます。 これはどういうことなのでしょうか? 修正もしくは別の方法があれば教えてください。

  • 配列の練習問題

    #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; } こんにちは。 この問題の解答のプログラムの意味がイマイチ解らないので良かったら教えて下さい。 確認がてらに質問します。 よろしくお願いします。

  • 二次元配列とポインタについてよくわかりません2

    先ほどもしつもんして自分なりに改良をくわえたのですが 上手くいきません。 int main( void ) {  int i, j;  /*4 x 4 行列 A*/  double a[4][4];  double *pa;  /*4 x 4 行列 B*/  double b[4];  double (*pb)[4];  /*4 x 4 行列 C*/  double c[4];  double (*pc)[4];  pa = a;  pb = b;  pc = c;  printf("4 x 4 行列 Aの要素を入力してください>\n");  for(i = 0; i < 4; i++){   for(j = 0; j < 4; j++){    printf("A[%d,%d]=", i + 1, j + 1 );    scanf("%lf", (*(pa + i) + j)); }} printf("4 x 4 行列 Bの要素を入力してください>\n"); for(i = 0; i < 4; i++){  for(j = 0; j < 4; j++){   printf("B[%d,%d]=", i + 1, j + 1 );   scanf("%lf", &pb[i][j]); }} としたところ(途中までを表記してます)  pa = a;  pb = b;  pc = c; のところでコンパイル時に 警告で問題のあるポインタの変換とでます なぜおかしいのかまったくわからないので よければ教えてください

  • 2次元配列にポインタを格納

    http://www.okweb.ne.jp/kotaeru.php3?q=505241の訂正版の質問です。 VC++6.0を使っております。 下のようなプログラムを作ってみました。 #include <stdio.h> #include <vector> using namespace std; class c{ public: c(); virtual ~c(); int get(){return j;}; void set(int i){j=i;}; private: c(const c &right); const c &operator=(const c &right); int j; }; void main(){ vector <vector<c*> > a; c *b; for(int n=0;n<10;n++){ for(int i=0;i<10;i++){ b=new c; a[n].push_back(b); } } for(int j=0;j<10;j++){ for(int i=0;i<9;i++){ a[i][j] -> set(i+j); } } for(j=0;j<10;j++){ for(int i=0;i<9;i++){ printf("%d ",a[i][j] -> get()); } printf("%d\n",a[9][j] -> get()); } for(int i=0;i<10;i++){ for(int j=0;j<10;j++){ delete a[i][j]; } } } すると、コンパイルには成功するのですが、実行は出来ません。 その理由は、「外部参照1が未解決」だそうです。 アドバイスをお願いいたします。

  • c言語のmalloc関数と2次元配列について

    ・mallocとreallocのAPPを作成しています、下記は単純化しました。 「質問-1」 ・while(1){...以下を無効にした場合、正常に終了します。 ・有効にして、最初に999を入力した場合、エラー表示されます。 ・この理由が分かりません。 「質問-2」 ・有効にして、初期数値(例えば11)を入力の場合、正常表示されます ・続けて数値(例えば15)を入力した場合、エラー表示されます。 ・この理由が分かりません。 ***************************************************************  #include <stdio.h>  #include <stdlib.h>  void MylnOut(void);  int **map;  int X=10,Y=10,i,j; //************************************************************** // MAIN //************************************************************** int main() {  char str[64]={""};  char *s="変更数値を入力(999で終了).... "; /* 2次元配列確保と初期表示 */  map=(int **)malloc(sizeof(int *)*X);  for(i=0;i<X;i++)   map[i]=(int *)malloc(sizeof(int)*Y);  MylnOut(); /* 変更数値入力 */ // while(1){ //  printf(s); //  gets(str); //  X=atoi(str); //  if(X==999) break; /* 領域変更と表示 */ //  map=(int **)realloc(map,sizeof(int *)*X); //  for(i=0;i<X;i++) //   map[i]=(int *)realloc(map[i],sizeof(Y)); //  MylnOut(); // } /* 領域開放 */   for(i=0;i<X;i++) free(map[i]);   free(map);   return 0; } //************************************************************** // 入力・表示 //************************************************************** void MylnOut(void) {  for(j=0;j<Y;j++)   for(i=0;i<X;i++) map[i][j]=55;   for(j=0;j<Y;j++){    for(i=0;i<X;i++) printf("%3d",map[i][j]);    printf("\n");   } }

  • 2次元配列

    大学の課題なのですが 10×10の2次元配列に、平面のビットパターンが入っているとする(0と1の整数が入っているとする)。左右反転して出力しなさい。 という問題で、自分は以下のプログラムを作ったのですが、うまくうごいてくれません。だれか間違いを指摘していただけないでしょうか。 よろしくお願いします。 #include<stdio.h> int main(void) { int i,j; int data[10][10]={0,1}; for(i=0;i<10;i++){ for(j=0;j<10;j++){ printf("%3d",data[10-i][10-j]); } printf("\n"); } return(0); }

専門家に質問してみよう