• ベストアンサー

どこかおかしいのでしょうか?

大学の授業で以下のような問題を出されました。  ■I have a ball.   と入力したら   1 : 1 I   2 : 4 have   3 : 1 a   4 : 5 ball.   と出力されるようなプログラムを作りなさい。 自分なりに以下のようなプログラムを書きました。 #include <stdio.h> #define MAX 1000 struct A { int vol; char x[MAX]; }; main() { int p; struct A a[100]; void readcalcprint(struct A []); for(p=0; p<100; p++) a[p].vol = 0; readcalcprint(a); } void readcalcprint(struct A a[100]) { int p, q; for(p=0; p<100; p++) { q=0; while((a[p].x[q]=getchar()) != '\0') q++; a[p].vol = q; if(a[p].vol==0) break; } for(p=0; a[p].vol>0; p++) printf("%d : %d %s\n", (p+1), a[p].vol, a[p].x); } コンパイルは出来るのですが、実行すると入力文の最後にスペースを何回入力しても、プロセスが終わりません。どこがおかしいのでしょうか。ずっと考えていて分からなかったので、書き込ませてもらいました。 回答よろしくお願いします。

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

  • ベストアンサー
  • ko_kinta
  • ベストアンサー率39% (43/109)
回答No.3

入力された文字を以下の3種類に区別しなければいけません。 (1) 文字列の終了を表す改行('\n') (2) 文字列内の語の区切りを表す空白(' '==0x20) (3) カウント対象の文字 このコードでは(1)と(2)の区別がありません。 また、ループ終了の判定に'\0'を使っていますが、これはコード上の文字列終端記号であり、標準入力は出来ないので、whileは無限ループに陥ってます。 それとmainで変数の初期化を中途半端に行っています。memset()を使って一気にやっつけた方がいいでしょう。 memset(a, 0, sizeof(a)); readcalcprint()の修正としては、こんなところでしょうか。 1. forのループ条件は、語数が100以下であること、および、'\n'が入力されていないこととします。 2. whileのループは語の長さがMAX-1以下であることを条件とすること。 3. getchar()した文字は一度char型変数に格納し、(3)の文字である場合のみa[p].x[q]に格納すること。 4. 入力文字が(1)だった場合はwhileループを終了すること。 5. 入力文字が(2)で語の長さが1以上であればwhileループを終了すること。 6. 入力文字が(2)で語の長さが0であれば入力文字を無視してwhile先頭に戻ること。(文字列区切りに空白が2個以上連続して入力された場合の対応処理)

abcdefgfedcba
質問者

お礼

丁寧な回答ありがとうございます。 たった今、ようやく自分のプログラムを修正することで正しく動作するものが書けました。 本当に細かいところから懇切丁寧に説明していただきありがとうございます。 実は(24時過ぎたんで)今日プログラミングの試験があり、この単語帳のところでちょうどつまずいていたところだったんです。 単位とれるように頑張ります!

その他の回答 (2)

  • funaho
  • ベストアンサー率58% (43/74)
回答No.2

ぱっと見たところ、 >while((a[p].x[q]=getchar()) != '\0') getchar()で入力をしていますが、スペースが入力されたにpの値が増える処理が無いと今の出力部で正しく出力されません。 また、 >for(p=0; p<100; p++) >{ >q=0; >while((a[p].x[q]=getchar()) != '\0') >q++; >a[p].vol = q; >if(a[p].vol==0) break; >} 無限ループになっています。 私が、似たようなプログラムを書いたので参考にしてみてください。 #include <stdio.h> #include <string.h> #include <ctype.h> void main() { char str[51],str2[20][51],*pst[20]; int i,j,l,n; l=0; n=0; printf("文->"); gets(str); for(i=0;str[i]!='\0';i++){ if(isgraph(str[i])){ str2[l][n]=str[i]; n++; }else{ str2[l][n]='\0'; pst[l]=str2[l]; n=0; l++; } } if(isgraph(str[i-1])){ str2[l][n]='\0'; pst[l]=str2[l]; l++; } for(i=0;i<l;i++){ printf("%d : %d %s\n", i+1, strlen(pst[i]), pst[i]); } }

abcdefgfedcba
質問者

お礼

回答ありがとうございます。 わざわざプログラムを書いて頂きとても役に立ちました。 プログラム参考にさせてもらい、自分なりにアレンジもできました。ありがとうございます。

回答No.1

問題に対するgetchar()の使い方が間違っています。 getchar()の仕様をよく読んでください。 問題の解き方もちょっと変わっていて、恐らく「I have a ball.」の'.'の直後は改行なんですよね?その改行判断はいらないと思われているのでしょうか?(ちょっとだけ先述のヒント)

abcdefgfedcba
質問者

お礼

回答ありがとうございます。 getchar()について復習します。

関連するQ&A

  • ポインタの扱い

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の処理がうまくいきません。。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list { char keyword[MAX_KW_LEN]; struct list *next; }; struct list *hashtable[HASHSIZE]; static char kw[NUM_KW][MAX_KW_LEN] = { "auto", "break", "double", "enum", "char", "continue", "extern", "float", "for", "int", "long", "register", "short", "signed", "static", "struct", "typedef", "union", "unsigned", "return", "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) { int hashval = 0; while (*key != '\0') hashval += *key++; return (hashval % HASHSIZE); } void InitHTable(void) { int i; struct list *p, *q; int hashval; for (i = 0; i < NUM_KW; i++) { printf("%d\n",i); if ((FindKeyWord(kw[i])) == FALSE) { if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) { fprintf(stderr, "メモリ不足です。\n"); exit(2); } strcpy((*p).keyword, kw[i]); hashval = Hash(kw[i]); if (hashtable[hashval] == NULL) { hashtable[hashval] = p; p->next = NULL; } else { q = hashtable[hashval]; while (q->next != NULL) { q = q->next; } q->next = p; p->next = NULL; } } } } int FindKeyWord(char *key) { struct list *p; for (p = hashtable[Hash(key)]; p != NULL; p = p->next) if (!strcmp(key, (*p).keyword)) return (TRUE); return (FALSE); } void ListKeyWord(void) { int i; struct list *p; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; p = p->next) printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } void FreeKeyWord(void) { int i; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; ) { q = p->next; free(p); p = q; } } int main(void) { char word[MAX_KW_LEN]; int i; InitHTable( ); ListKeyWord( ); for (i = 0; i < 4; i++) { printf("Cの予約語を入力して下さい "); fgets(word, 128, stdin); if ((FindKeyWord(word)) == TRUE) printf("%s は登録済みです。\n", word); else printf("%s は未登録です。\n", word); } FreeKeyWord( ); }

  • C++ なのですがエラーが消えません

    課題のC++プログラムのエラーが消えません,教えてください. 10個の数値を入力し並び替えるプログラムなのですが並び替え部分以外は先生作成のプログラムです. どうかお願いいたします. #include <stdio.h> #define MAX 10 #define OK 0 void inputnum(int num[]); void sortnum(int num[]); void outputnum(int num[]); main(){ int num[MAX]; printf("番号 氏名\n"); inputnum(num); sortnum(num); outputnum(num); return(OK); } void inputnum(int num[]){ int i; for(i=0;i<MAX;i++,num[i]){ printf("数値%d = ", i+1); scanf("%d",&num[i]); } printf("数値入力完了\n"); } void sortnum(int num[]){ int tmp,p,q; for(p = 0; p < 9; p++){ for(q = p + 1; q < 10; q++){ if(num[p] > num[q]){ tmp = num[p]; num[p] = num[q]; num[q] = tmp; } } } printf("並び替え完了\n"); void outputnum(int num[]){ int i; for(i=0;i<MAX;i++){ printf("数値%d = %d\n",i+1,num[i]); } printf("数値出力完了\n"); }; [エラー  Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland 1142122.c: エラー E2140 1142122.c 46: ここでは宣言はできない(関数 sortnum ) エラー E2141 1142122.c 46: 宣言の構文エラー(関数 sortnum ) エラー E2134 1142122.c 54: 複合文に } がない(関数 sortnum ) *** 3 errors in Compile ***]

  • 初心者です。 配列のエラーがどうしても解決できません。 誰か助けてください・・・

    魔方陣のプログラムを考えて書いてみましたが、 エラーが出てしまい実行することができません。 class mahoujin{ public static void main(String args[]){ int n=3; int a[][] = new int[3][3]; int x=0; int y=1; for(int p=0;p<=3;p++){ for(int q=0;q<=3;q++){ a[p][q]=0;} } for(int i=1;i<=n*n;i++){ if((i%n)==1){x++; }else{x--; y++;} if(x==0){x=3;} if(y==3){y=0;} a[x][y]=i;} } } 空の配列や配列を外れるものがあるかをよく考えてみましたが、どうしても解決できません。助けてください・・・

  • C言語のプログラム

    以下のプログラムはハッシュテーブルを用いて文字列を探すプログラムなのですが、コンパイル時にセグメントエラーとなってしまいます。プログラム中に誤った箇所があれば教えて頂きたいです。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 10 #define MAX_LEN 64 #define N_WORDS 4 struct list { char word [MAX_LEN]; struct list *next; }; struct list *hash_table[HASHSIZE]; char colors[N_WORDS][MAX_LEN] = {"red", "blue", "green", "yellow"}; void my_strcpy(char* a, const char* b) { int i = 0; while(*b != '\0'){ *(a+i) = *(b+i); i++; } *(a+i) = '\0'; } int hash(char *key) { int hashval = 0; while (*key != '\0') { hashval += *key; key++; } return (hashval % HASHSIZE); } int find_word (char *key) { struct list *p; for (p = hash_table[hash(key)]; p != NULL; p++) if (strcmp(key, p->word) == 0) return 1; return 0; } void init_hash_table() { int i, hashvalue; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) { hash_table[i] = NULL; } for (i = 0; i < N_WORDS; i++) { if ((find_word(colors[i])) == 0){ p = (struct list *)malloc(sizeof(struct list)); my_strcpy(p->word, colors[i]); hashvalue = hash(colors[i]); if (hash_table[hashvalue] = NULL) { hash_table[hashvalue] = p; p->next=NULL; } else { q = hash_table[hashvalue]; while (q->next != NULL) q = q->next; q->next = p; p->next=NULL; } } } } void main(void) { init_hash_table(); printf("result = %d\n", find_word("red")); }

  • できているとは、思うのですが。ポインタの配列を

    コンパイラではちゃんと動いてます。 1 2 3 0 1 2 3 という具合です。 気になるのは、printarrayの部分が正しいのか、ちょっと悩んでいます 問題としては main関数では0の値を読み込むまで最大99(MAX-1)個の値を配列 xに読み込んでいる。引数のポインタからの値を、値が0になるまで すべて1行に1つづつ画面に出力する関数printarray()を作成し、 プログラムを完成せよ。 引数はアドレスとして受け取る事。(配列としてでなく) フォーマットは、 "%d¥n" とする。(余計な出力はしない事。) (0は出力しない。) main内部を変更してはならない。 以下がソースです。 ご指摘よろしくお願いします。 #include <stdio.h> #define MAX 5 void printarray(int *); int main() { int x[MAX], i; int *p; x[MAX-1] = 0; for (i = 0, p = x; i < MAX-1; ++i, ++p) { scanf("%d", p); if (*p == 0) { break; } } printarray(x); return 0; } void printarray(int *a) { int i,*p; for(i = 0, p = a; i < MAX-1; ++i,++p) { if(*p == 0){ // continue; break; }else{ printf("%d\n", *(a+i)); } } }

  • 構造体へのポインタ

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の 他の関数内での使用の仕方が全くわかりません。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list {  char keyword[MAX_KW_LEN];  struct list *next;   /* 次の list へのポインタ */ }; struct list *hashtable[HASHSIZE]; /* ハッシュテーブル */ /* キーワード ( Cの予約語 ) */ static char kw[NUM_KW][MAX_KW_LEN] = {   "auto", "break", "double",   "enum", "char", "continue", "extern", "float", "for", "int",   "long", "register", "short", "signed", "static",   "struct", "typedef", "union", "unsigned", "return",   "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) {  int hashval = 0;  while (*key != '\0')   hashval += *key++;  return (hashval % HASHSIZE); } void InitHTable(void) {  int i;  struct list *p, *q;  int hashval;  for (i = 0; i < NUM_KW; i++) {   printf("%d\n",i);   if ((FindKeyWord(kw[i])) == FALSE) { /* 登録されていなかったら */             /* メモリを割り付ける */    if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) {     fprintf(stderr, "メモリ不足です。\n");     exit(2);    }    strcpy((*p).keyword, kw[i]);    hashval = Hash(kw[i]);    /* ハッシュ値を求めて */        if (hashtable[hashval] == NULL) { /* 未登録なら */     hashtable[hashval] = p;  /* p の指すアドレスを登録 */     p->next = NULL;    /* リストの末尾に NULL を追加 */    }    else {        /* 既に登録していたら */     q = hashtable[hashval];     while (q->next != NULL) {  /* データがなくなるまで */      q = q->next;    /* リストをたどる */     }     q->next = p;     /* リストの末尾に p の指すアドレスを登録 */     p->next = NULL;    /* その末尾に NULL を追加 */    }   }  } } int FindKeyWord(char *key) {  struct list *p;  for (p = hashtable[Hash(key)]; p != NULL; p = p->next)   if (!strcmp(key, (*p).keyword))  /* 登録済みなら */    return (TRUE);     /* TRUE を返す */   return (FALSE);      /* 未登録ならFALSE を返す */ } void ListKeyWord(void) {  int i;  struct list *p;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; p = p->next) /* p が NULL でなければ */               /* ハッシュ値とキーワードを表示 */    printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } /* malloc( ) で割り付けたメモリを解放 */ void FreeKeyWord(void) {  int i;  struct list *p, *q;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; ) { /* p が NULL でなければ */    q = p->next;      /* p->next を保存 */    free(p);       /* メモリを解放 */    p = q;        /* p->next を p に代入 */   } } int main(void) {  char word[MAX_KW_LEN];  int i;  InitHTable( );  ListKeyWord( );  for (i = 0; i < 4; i++) {   printf("Cの予約語を入力して下さい ");   fgets(word, 128, stdin);   if ((FindKeyWord(word)) == TRUE)    printf("%s は登録済みです。\n", word);   else    printf("%s は未登録です。\n", word);  }  FreeKeyWord( ); }

  • ばばぬきプログラムについて

     下記のようなプログラムで4人のコンピュータにババヌキをさせるプログラムを組んでる最中なんです。  decklistまでは表示できてもshufflelistではコンパイルは通っても実行するとデバックが起きてしまって困っています。while文をなくすとちゃんと返り値を持って表示はできるんですがwhile分で繰り返したとたんデバックが起きるんですがその理由がわかりません。どうして無理でしょうか?ご教授願います。 decklistは整列されリストに保存した山札の関数。 shufflelistはランダムで保存していく関数。 personの関数はdecklistのほうで試したところコンパイルは通るんですがこちらもデバックが起きてしまいます。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define N 53 //デッキのカードの構造体 struct card{ int t; struct card *next; }*deck; //カードを配った後のそれぞれのプレイヤーの情報(仮 struct player{ int card; struct player *nextcard; struct player *nextturn; }; //関数定義 struct card *talloc(void); struct player *lalloc(void); struct card *decklist(void); struct card *shufflelist(void); struct player *person(struct player *P); void displist(void); int main(void){ struct player *A,*B,*C,*D; struct player *p; p=person(A); while(p!=NULL){ printf("%d ",p->card); p=p->nextcard; } return 0; } //card構造体のセルの確保 struct card *talloc(void){ return (struct card *)malloc(sizeof(struct card)); } //player構造体のセルの確保 struct player *lalloc(void){ return (struct player *)malloc(sizeof(struct player)); } //カードを切る前の整列された山札の関数 struct card *decklist(void){ int i,add=1,count=0; struct card *p; deck=NULL; for(i=0;i<53;i++){ if(count==4){ add+=1; count=0; } p=talloc(); p->t=add; p->next=p; count++; p->next=deck; deck=p; } return deck; } //山札をシャッフルした後の山札の関数 struct card *shufflelist(void){ int i,a,count=0,r; struct card *d,*p,*q,*shuffle; p=decklist(); shuffle=NULL; while(p!=NULL){ srand(time(NULL)); r=(int)rand()%(N-count); for(i=0;i<r;i++){ p=p->next; } q=talloc(); q->t=p->t; d=p->next; p->next=d->next; q->next=shuffle; shuffle=q; count++; p->next=p; } return shuffle; } //プレイヤーへカードを配るための関数 struct player *person(struct player *PERSON){ struct player *a; struct card *library; int i; PERSON=NULL; library=decklist(); a=lalloc(); while(a!=NULL){ a->card=library->t; for(i=0;i<4;i++){ library=library->next; } a->nextcard=a; a=PERSON; } a->nextcard=NULL; while(a!=NULL){ printf("%d ",a->card); } return PERSON; }

  • 引数のみで出力

    問題として main内部を変更してはならない。 関数sub()でmainのループと同じ出力するようにせよ。 ただし、関数subで引数以外の変数を宣言してはならない。 また、広域変数を追加してはならない。 となっていて、色々とforループで出力させようと 配列にしたりポインタにしたりしたのですが forのiに比例する配列をどう組めばいいのか、わからないです。。。 mainの出力は 1 8 15 22 29 36 となっています。 これをsubでもできるように設定するみたいです。 #include <stdio.h> #define MAX 7 void sub(int [MAX]); int main() { int i; int x[MAX]; for (i = 0; i < MAX-1; ++i) { x[i] = 7*i+1; } x[MAX-1] = 0; for (i = 0; x[i] > 0; ++i) { printf("x = %d\n", x[i]); } printf("print again\n"); sub(x); return 0; } void sub(int a[MAX]) { // a[6]=0 // MAX 7 a[MAX-1]=0; for(a[MAX-1];a[MAX-7]<=MAX-1;++a[MAX-1]){ //a[MAX-1] = 7*a[MAX-1]+1; printf("a[%d] = %d\n",a[MAX-1],a[MAX-7]); } }

  • Cのソースコードについて

    以下のソースコードをかきました。 #include<stdio.h> #include<string.h> #define MAX 100005 typedef struct PP { int t; char name[100]; }P; P Q[MAX]; int head, tail, n; void enqueue(P u) { Q[tail] = u; tail = (tail + 1) % MAX; } P dequeue() { P x = Q[head]; head = (head + 1) % MAX; return x; } int min(int a, int b) { return a > b ? a : b; } int main() { int q, sum = 0 , w; scanf("%d %d", &n,&q); for (int i = 1; i <= n; i++){ scanf("%s", Q[i].name); scanf("%d", &Q[i].t); } head = 1; tail = n + 1; P u; while (head != tail) { u = dequeue(); w = min(q, u.t); sum += w; u.t -= w; if (u.t > 0)enqueue(u); else { printf("%s %d", u.name, sum); } } return 0; } これでVisual C++ でコンパイルしたところ特にエラーも起きず問題なく動作しました しかしAOJに提出してみたところコンパイルエラーになってしまい詰んでしまいました どこかダメそうなところがあれば教えてください

  • プログラムがちゃんと動きません

    C言語です まず人数を入力した後に 名前と身長と体重を入力する関数get_psと それらの情報を人数分出力する関数print_psを使い mainで実行するというプログラムを作ったのですが 思うように動きません どのようにすればいいでしょうか? #include<stdio.h> struct ps_data{ char name[20]; double hgt; double wgt; }; void get_ps(struct ps_data *p,int a) { int i=0; printf("name height weight:"); scanf("%s %lf %lf",(p+i)->name,&(p+i)->hgt),&(p+i)->wgt); i++; } void print_ps(struct ps_data *p,int a) { int i; for(i=0;i<a;i++) printf("%s :height=%lf weight=%lf \n",(p+i)->name,(p+i)->hgt,(p+i)->wgt); } int main(void) { int n,i; struct ps_data ps_dat[20]; printf("Number:"); scanf("%d",&n); for(i=0;i<n;i++) { get_ps(ps_dat,i); } print_ps(ps_dat,n); return 0; }

専門家に質問してみよう