• 締切済み

教えてください!!

テキストファイル aesop.txt には、イソップ寓話の一つが英語で書かれている。このファイルを読み込み、各単語を左右反転して標準出力に出力するプログラムを作成したい。つまり、以下の入力 The Dog and the Shadow It happened that a Dog had got a piece of meat and was carrying it home in his mouth to eat it in peace. Now on his way : が以下のようになればよい。 ehT goD dna eht wodahS tI deneppah taht a goD dah tog a eceip fo taem dna saw gniyrrac ti emoh ni sih htuom ot tae ti ni ecaep. woN no sih yaw : 以下の指示に従って、プログラムを作成せよ。 コード #include <stdio.h> #include <stdlib.h> #define STACKSIZE 256 char st[STACKSIZE]; int top=0; int push(char d) { if (top < STACKSIZE) { st[top]=d; top=top+1; return(0); } if(top >= STACKSIZE) return (-1); } char pop(void) { if(top>0){ top=top-1; return(st[top]); } if(top==0) return('\0'); } int main(void){ FILE *fp; int c; char moji; fp = fopen("aesop.txt", "r"); if (fp == NULL){ printf("入力ファイルを開けません\n"); exit(1); while ((c = fgetc(fp)) != EOF){ if(('A'>=c && c<='Z')||('a'>=c && c<='z')){ if(push(c)==0) {push(c);} if(push(c)==-1){ exit(1);} } else { while(top != 0){ moji=pop(); if(moji != '\0') printf("%c",moji); } } printf("%c",c); } } fclose(fp); return (0); } というコードを書いたのですが、実行できませんどこがまちがっているのでしょうか??

みんなの回答

回答No.4

こんばんは. 質問のタイトルは「具体的に」書いた方が良いと思いますが… 他の方も指摘されていますが,データを二重にpushしている点が問題である,というものが回答です. また,他にもいくつか修正すべき点があります. (1)単語ごとにスタックにpushして,区切り文字が出てきたらpopすべき (2)main関数で popの戻りとtopを同時に調べるのは無駄 (3)pop,pushの両関数でifを二つ書くのは無駄 (4)文字のチェックは ctype.h 内のマクロで行った方が良い 以下がこれらの方針に基づく実装例です. #include <stdio.h> #include <stdlib.h> #include <ctype.h> /* isalnum(),isspace()マクロのため */ #define STACKSIZE 256 char st[STACKSIZE]; int top=0; int push(char d) { if (top < STACKSIZE) { st[top]=d; top++; /* この書き方の方が自然 */ return(0); } else { /* どんな場合でも値を返すように修正 */ return (-1); } } char pop(void) { if(top>0){ top--; /* この書き方の方が自然 */ return(st[top]); } else{ /* どんな場合でも値を返すように修正 */ return('\0'); } } int main(void){ FILE *fp; int c; char moji; if ((fp = fopen("aesop.txt", "r")) == NULL){ printf("入力ファイルを開けません\n"); exit(1); } do{ c = fgetc(fp); if(isalnum(c)){ /* 文字か数字だったらスタックに積む */ if(push(c)==-1){/* スタックが溢れたら終了 */ exit(1); } } /* 単語の区切り文字(スペース,改行とピリオド)を検出したら単語のpop開始 */ else if ((isspace(c))||(c=='.')){ while((moji = pop()) != '\0'){ printf("%c",moji); /* 文字列をpopして */ } printf("%c",c); /* 区切り文字を出力 */ } }while (c != EOF); /* EOF直前の単語をpopする */ while((moji = pop()) != '\0'){ printf("%c",moji); /* 文字列をpopして */ } fclose(fp); return (0); }

全文を見る
すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

どこがどのように希望に沿わない結果なのかを明記しましょう if(('A'>=c && c<='Z')||('a'>=c && c<='z')){   if(push(c)==0) {     push(c);   }   if(push(c)==-1){     exit(1);   } } この部分は何を期待してるのでしょう ファイルから読み込んだ文字をpush関数でバッファにためる処理のように思いますが pushを何回も同じ文字に対して実行していますがこれは意図した動きでしょうか >The Dog and the Shadow の Tを読み込んで   if(push(c)==0) { で1回目のpush これが成功するので push(c)==0 条件が成立 if文の中の 2回目のpush(c); を実行   if(push(c)==-1) { で3回目ののpushを実行 といった具合になるので配列stには st[0] = "T", st[1] = "T", st[2] = "T" と格納されてしまいます これが意図した動きでしょうか? 最初にpush(c)の戻り値を取得してこれが失敗を表す-1かどうかを判断するのではないでしょうか

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

>というコードを書いたのですが、実行できませんどこがまちがっているのでしょうか?? 実行できません、とは、どういう状態ですか? 1)コンパイルできない。コンパイル時にエラーが出る。そのときのエラーメッセージは? 2)コンパイルはできて、実行ファイルは作れたが、その実行ファイルが正しく実行できない。エラーは出る?出ない?出る場合、メッセージの内容は? どこかが間違っているとして、まず自分の頭でどこが正しくないかを考えましたか? 「動かない」→○→「人に聞く」 ○印のところに「まずはとことん自分で考えてみる。それでもダメだったら」という過程があるはずですが、 それをすっ飛ばしていませんか?

全文を見る
すると、全ての回答が全文表示されます。
  • Yanch
  • ベストアンサー率50% (114/225)
回答No.1

main関数にて、 「{」と「}」の数が一致していないようですよ。 よくコードを確認しましょう。 そして、ソース全体において、字下げの書き方が統一されていないみたいです。 読みにくいので、何かに統一すると良いです。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • C言語 文字列の比較 compare

    プログラミング初心者です。 60文字以内の文字列を入力して、 大小関係を比較・表示するプログラムなのですが・・ 「AはBより大きい」という結果しか出ません。 どこが間違っているのか、ご指摘お願いしますっ。 #include<stdio.h> int main(void) { char moji1[61]; char moji2[61]; printf("文字列Aを入力===>"); scanf("%60s" ,&moji1); printf("文字列Bを入力===>"); scanf("%60s" ,&moji2); if(moji1-moji2>0){ printf("===AはBより大きい===\n"); } else if(moji1-moji2<0){ printf("===AはBより小さい===\n"); } else if(moji1-moji2==0){ printf("===AとBは等しい===\n"); } return 0; } int compare(char *x, char*y) { while(*x==*y){ if(*x=='\0') return 0; x++; y++; } return (*x-*y); }

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

    下に貼り付けたプログラムの流れを順番に教えて頂きたいです。 特にadd関数とinsert関数の中身の動きについてが分からないので教えていただきたいです。 (a,b,c,sentouなどの動きなど。) 参考にですが リスト構造を用いて、read関数で読み込んだ単語をアルファベット順にソートしてリストのセルに入れ、同じ単語はまとめてその単語と個数を順に表示するプログラムです。 1からの説明を要求して申し訳ありませんがよろしくお願いいたします。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<ctype.h> typedef struct moji{ char w[50]; int cnt; struct moji *next; }moji; int main(){ FILE *fp; char data[50]; moji *sentou; moji *p=NULL; if((sentou=(moji *)malloc(sizeof(moji)))==NULL){ printf("malloc error\n"); exit(1); } fp=fopen("tango.txt","r"); if((fp = fopen("tango.txt","r"))==NULL){ printf("can't open\n"); exit(1); } while(read(data,fp)){ add(data,sentou); } p=sentou->next; while(p != NULL){ printf("%s %d\n",p->w,p->cnt); free(p); p=p->next; } fclose(fp); return (0); } int read(char data[],FILE *fp){ /*1つの単語(連続したアルファベット)をdataに格納して、スペースで区切られたらそこで格納をやめ、値1を返す。再度単語を格納するときはdataを初期化し、再度1つの単語を取得する。ファイルの単語がなくなれば(EOFなら)0を返す関数read()*/ } void add(char data[],moji *sentou){ moji *a,*c; for(c=sentou;c!=NULL;c=c->next){ if(strcmp(c->w,data)==0){ c->cnt++; return; } if(strcmp(c->w,data)>0){ break; } else{ a=c; } } insert(a,c,data); } void insert(moji *a,moji *c,char data[]){ moji *b; if((b=(moji *)malloc(sizeof(moji)))==NULL){ printf("malloc error\n"); exit(1); } strcpy(b->w,data); b->cnt=1; a->next=b; b->next=c; }

  • 何故オーバーフロー??

    http://oshiete1.goo.ne.jp/qa4423673.html さらに続きになります。 #include<stdio.h> #include<string.h> #define NAME 256 // 暫定的に最大値を決めてます int Convert(const char* pInFileName, const char* pOutFileName); int ReConvert(const char* pInFileName, const char* pOutFileName); int main(){ int a,ret=-1; char InFileName[NAME]; // 入力ファイル名 char OutFileName[NAME]; // 出力ファイル名 FILE *pInFileName; // 入力ファイルポインタ FILE *pOutFileName; // 出力ファイルポインタ printf("1:コンバート 2:リコンバート\n"); scanf("%d",&a); /***** 入力ファイル名入力 *****/ printf("\n@@@@@入力ファイル名入力\n"); scanf("%s",&InFileName); // 入力ファイルオープン if((pInFileName=fopen(InFileName,"rb"))==NULL){ printf("ファイルがありません\n"); return -1; } /***** 出力ファイル名入力 *****/ printf("\n@@@@@暗号化後ファイル名入力\n"); scanf("%s",&OutFileName); // 出力ファイルオープン if((pOutFileName=fopen(OutFileName,"r"))!=NULL){ // read出来るのなら既にファイルあるという事なのでエラーにする printf("同名のファイルが既にあります\n"); return -1; } pOutFileName=fopen(OutFileName,"wb"); // 1:コンバート // 2:リコンバート // 1,2以外:終了 if(a==1){ ret=Convert((const char*)pInFileName,(const char*)pOutFileName); } else if(a==2){ ret=ReConvert((const char*)pInFileName,(const char*)pOutFileName); } if(ret==0){ printf("正常終了\n"); } else{ printf("異常終了\n"); return -1; } printf("数字+エンターで終了します\n"); scanf("%d",&a); fclose(pOutFileName); fclose(pInFileName); return 0; } /*****コンバート*****/ int Convert(const char* pInFileName, const char* pOutFileName) { unsigned char moji; while(1) { if(fread( &moji, 1, 1, (FILE*)pInFileName )>0){ fprintf((FILE*)pOutFileName,"%02x",moji); } else break; } return 0; } /*****リコンバート*****/ int ReConvert(const char* pInFileName, const char* pOutFileName) { char moji16[3]; // 16進表記 char moji10[4];★★★★★★★★★★ long i,j; while(1) { if(fread( moji16, 1, 2, (FILE*)pInFileName )>0){ for(i=0,j=0;i<2;i+=2,j++){ sscanf(&moji16[i], "%2x", moji10); } fprintf((FILE*)pOutFileName,"%c",moji10); } else break; } return 0; } 上記の char moji10[4];★★★★★★★★★★ の部分ですが、これを配列を用いずに、moji10とした場合(応じてsscanfでは&moji10になる)や moji10[2]、moji10[3]とした場合でもオーバーフローが検出されました。 sscanfの行になった時に、moji10[0]には文字が入りますが、 moji10[1]~moji10[3]まで、NULL文字'\0'が入っていました。 何故moji10[4]にしないとオーバーフローが消えないのでしょうか? 尚、Visual C++ 2008です。

  • C言語 strlen 再入力を促す

    文字列の比較で、 文字列の長さが60以上の時、再入力を促します。 while文を使って書いてみたのですが、 文字列Bの入力の前に、もう一度意味もなく 「文字列Aを入力===>」が表示されたり。 文字列Aのほうが小さいのに「Aのほうが大きい」と 表示されるようになったり、変な感じです。 どなたかご指摘・ご指導のほどよろしくお願いします。 int main(void) { char moji1[100]; char moji2[100]; while(strlen(moji1)>60){     printf("文字列Aを入力===>"); scanf("%80s" ,moji1); } while(strlen(moji2)>60){     printf("文字列Bを入力===>"); scanf("%80s" ,moji2);    } if(compare(moji1,moji2)>0){ printf("===AはBより大きい===\n"); } else if(compare(moji1, moji2)<0){ printf("===AはBより小さい===\n"); } else if(compare(moji1, moji2)==0){ printf("===AとBは等しい===\n"); } return 0; } int compare(char *x, char*y) { while(*x==*y && *x!=0){ x++; y++; } return (*x-*y); }

  • 質問です。

    このソースのscanf("%*c%c",&moji);の部分が分かりません。"%*c%c"はどういう意味があるのですか?また、。"%*c%c"と%cの違いは何ですか?教えてください。宜しくお願いします。 #include <stdio.h> int main(void) { char moji; printf("文字を入力 (終了するときは/) -->"); scanf("%c",&moji); for(;;){ if(moji!='/'){ printf("文字 = %2c\n",moji); printf("10進 = %2d\n",moji); printf("16進 = %2x\n",moji); printf("文字を入力 (終了するときは/)-->"); scanf("%*c%c",&moji); } else{ printf("プログラムを終了します"); break; } } return 0; }

  • 以下のソースコードについて

    #include<stdio.h> #include<stdlib.h> #include<string.h> int top, S[1000]; void push(int x) { S[++top] = x; } int pop() { top--; return S[top + 1]; } int main() { int a, b; top = 0; char s[100]; while (scanf_s("%s", s) != EOF) { if (s[0] == '+') { a = pop(); b = pop(); push(a + b); } else if (s[0] == '-') { b = pop(); a = pop(); push(a - b); } else if (s[0] == '*') { a = pop(); b = pop(); push(a*b); } else { push(atoi(s)); } } printf("%d\n", pop()); return 0; } このコードはプログラミングコンテストのためのアルゴリズムとデータ構造という本に 書かれていたコードで、項目はスタック構造に当たるものです。このコードを写してVIsual C++ に通したところ(バージョンは2015)エラーが発生しました。 どうしたらよいでしょうか 問題のURLはhttp://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_3_A です。言語はCです。

  • 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の行がたぶん間違っていると思うんですが。。。

  • 末尾の行が二回読み込まれてしまいます。

    末尾の行が二回読み込まれてしまいます。 以下のコードで #include <stdio.h> #include <stdlib.h> //ファイルに書き込まれた24:00:00の形式の時刻を秒単位で出力する。 int translate(char* str) { int a,b,c; int time; sscanf(str,"%d:%d:%d",&a,&b,&c); time = 60*60*a + 60*b + c; return time; } int main(int argc,char *argv[]) { FILE *fp; char str[100]; int s; fp = fopen("file.time","r"); if(fp == NULL){ printf("can not open the file.\n"); return 1; } while(!feof(fp)){ fscanf(fp,"%s",str); s = translate(str); printf("%d\n",s); } fclose(fp); return 0; } 末尾の行が二回処理されてしまいます。なにがまずいのでしょうか?よろしくお願いいたします。

  • 英文字の出現頻度

    英語で書かれているファイルを読み込んで英文字の出現頻度を調べるプログラムを作ったのですが、ところどころ正確な数が表示されません。どなたか教えてもらえませんか?欲を言えばスペースや改行もカウントできれば良いのですが・・・よろしくお願いしますm(_ _)m #include <stdio.h> #define N 500 int main(int argc, char *argv[]) { int c,i=0; int X[N]; FILE *fp; char ch[N]; if( argc != 2) { printf("使い方:コマンド名に続きファイル名を入れてください\n"); return -1; } fp = fopen( argv[1],"rb"); while(fgets(ch,500,fp) != NULL ) { printf("%sファイルにおけるアルファベットの出現頻度\n",argv[1],ch); { while ((c = getc(fp)) != EOF) if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') X[c]++; { for (c = 'a'; c <= 'z'; c++) printf("%c:%d\n",c, X[c]); printf("\n"); for (c = 'A'; c <= 'Z'; c++) printf("%c:%d\n",c, X[c] ); printf("\n"); } } } fclose(fp); return 0; }

  • スタックのプログラムを作成しているのですが、うまく出来ません。

    プログラムの内容を簡単に言うと、配列s[100]と変数topを用いて、ファイルdata.datからgetc()を用いて文字を1文字ずつ読み込み、スタック(s[100])にpush-downするプログラムです。 細かく言うと、作成したプログラムによりファイルからキー(文字)を読み込みスタックにpush-downし、スタックの内容を表示した後に、キーボードからキー(文字)を1文字ずつ入力して、スタックを操作する。 ・スタック操作の仕様はキーボードからキー(文字)を1文字ずつ入力する際に、0を入力した場合、プログラム終了。1を入力した場合、1文字pop-upした後、pop-upした文字とスタックの内容を表示。その他の文字を入力した場合、その文字をpush-downした後、スタックの内容を表示。(スタックの内容の表示はprint_stack_mtrx(s,top)を使用する。) ・push-downとpop-upはそれぞれ1つの関数で定義する。 といった感じのプログラムを作成しているのですが、関数push,popの部分をどう書いたら良いのか良く分かりません。一応自分で書いてみたのですが、うまくいきませんでした。どなたか教えていただけないでしょうか? *ファイルdata.datからはリダイレクションを用いて読み込む。 <作成途中のソースプログラム> #include<stdio.h> #include<stdlib.h> #define MAX 100 char s[MAX]; int top; void init_stack(){ ______top = 0; _______return; } void print_stack_mtrx(char* s, int top){ __int i; ____if(top == 0){ ______printf("Stack is empty.\n"); ____} ____else{ ______printf("--- Contents of Stack ---\n"); ______for(i = 0; i < top; i++){ ________if(!i){ __________printf("%2c < -- Top (%2d)\n", s[top - i - 1], top); ________} ________else{ __________printf("%2c \n", s[top - i - 1]); ________} ______} ______printf("-------------------------\n"); ____} } char push(char* s, int top, char j){ ___s[top]=j; ___top++; } char pop(char* s, int top){ _char c; ___c = s[top]; ___top--; ___return c; } int main(void) { _int c; _char j; _char i; init_stack(); _______while(((c=getc(stdin))!=EOF) && top<MAX){ _______/* ファイルdata.dat からgetc()を用いて1文字ずつ読み込みスタックsに格納.ただしスタックの出入り口を示す top の値も監視すること*/ _________s[top] = c; _________top++; _______} _______print_stack_mtrx( s, top );/* スタック(配列)の内容を表示する関数*/ _______while(1){ _________scanf("%c\n", &j); _________if(j=='0'){ ___________break; _________} _________else if(j=='1'){ ___/* 1文字pop-upした後, pop-upした文字とスタックの内容を表示 */ ___________i = pop(s, top); ___________printf("pop-upした文字: %c\n", i); ___________print_stack_mtrx( s, top ); _________} _________else{ ___/* その他の文字を入力した場合, その文字をpush-downした後,スタックの内容を表示 */ ___________push(s, top, j); ___________print_stack_mtrx( s, top ); _________} _______} _______return 0; }