• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:アルファベットの出現頻度求めるプログラム)

アルファベットの出現頻度求めるプログラム

このQ&Aのポイント
  • アルファベットの出現頻度を求めるプログラムを作成しています。
  • プログラムの意味がわからない箇所やエラーメッセージについて質問しています。
  • 使用しているアポストロフィーが使えないエラーが発生しており、解決方法を求めています。

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

  • ベストアンサー
回答No.3

なんか質問者が理解できてないのかTacosanさんの回答を右から左に流しているので, 実際のコードで見せてみます。 // memset も微妙だけど (初期化すればいいのに) // -> = {0}で宣言時に初期化。 int alpha[ALPHA] = {0}; int c; // ・なんで scanf を使ってるんだろう. 1文字ずつ読み込むようにすればバッファオーバーランなど起こりようもないのに. // -> getcharを使ったプログラムに変更。1文字ずつ処理してバッファーに入れるという動作をしないので、バッファオーバーランは起きない。strの代わりにcというint型の変数を使うことにする。 // ・条件式しかない for って, あんまり普通じゃないと思う. while はお嫌い? // -> 条件だけ取り出して、while文に書き換え while ((c = getchar()) != EOF) { if(isalpha(c)) { c = toupper(c); alpha[c - 'A']++; } } 以下、落穂拾い的に残りのコメントについて解説します。 > #1 への指摘を先にすると, 15行目は「Cannot convert 'int' to 'char *'」だから「EOF が変換できていない」んだと思います. また, 「for()の閉じ括弧がありません」じゃなくて「scanf の呼び出しの閉じ括弧がない」です (おそらくセミコロンのところでエラーになってる). 質問者もこれには気づいているようなので特にコメントをすることはありません。 ただ、getcharに変更して、scanfにはご退場いただいたのでこのエラーはなくなりました。 ちなみに、scanfは初心者向けの本に必ず書いてあるものの、使える場面が限られている上に、扱いが非常に難しいので自分は殆ど使わないです。代わりにfgets、fgetc、freadを使うことが多いです。 > ・そもそもアルファベットがきちんと並んでいるという保証はどこにもない. Windows なら ASCII がベースなので問題ないけど, 一般論としてはアウト. 文字をコンピュータ上でどう表すかというのを文字コードといいますが、文字コードには様々な種類があります。例えば、ASCIIだとAからZまで文字コードが順に並んでいるものの、EBCDICなどそれが保証されていないこともあって、C言語ではどの文字コードを想定するか決まりがありません。 例えば、ASCIIだと'J' - 'I' は1ですが、EBCDICだと、'J' - 'I'は1ではありません。 だから、大文字 - 'A'が26までの範囲に収まることは必ずしも保証されていません。 ただ、Windowsなど一般に普及している環境ではASCIIを採用していることがほとんどなので、大文字 - 'A'が26未満と想定しても問題になることはほぼないでしょう。 あえてやるならこうやって求めるとかでしょうか。 const char alphabet_sample[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int get_index(int c) { char* p = index(alphabet_sample, c); if (p != NULL) return p - alphabet_sample; else return -1; } もっとマシな書き方はありそうですが。 > ・str[i]!='0' これは、誤植したんでしょうね。str[i] != '\0'とすべき。 このコードもscanfからgetcharに変更したことでなくなりました。 文字と数値では意味が全然違います。 str[i] != 0だと0という数値との比較ですが、str[i] != '0'だと0という文字との比較になります。 '0'の文字コードはASCIIだと48なので、str[i] != '0'はstr[i] != 48と書いてるのと同じ動作をします。 一方str[i] != '\0'だと'\0'はNULL文字で、数値の0に中身はなっているはずなので、str[i] != 0と同じ動作をします。 ただ、文字として扱っているということを意識すると、str[i] != '\0'が正しいです。 > ・putchar('/n'); これも誤植ですね。 正しくはputchar('\n')でしょう。 以上の修正をして、FreeBSD上でコンパイルして動かしてみるとこんなかんじです。 >./a.out Hello World! ^D A= 0 B= 0 C= 0 D= 1 E= 1 F= 0 G= 0 H= 1 I= 0 J= 0 K= 0 L= 3 M= 0 N= 0 O= 2 P= 0 Q= 0 R= 1 S= 0 T= 0 U= 0 V= 0 W= 1 X= 0 Y= 0 Z= 0 >cat /COPYRIGHT | ./a.out A= 284 B= 93 C= 180 D= 220 E= 556 F= 140 G= 84 H= 157 I= 473 J= 3 K= 18 L= 177 M= 110 N= 351 O= 396 P= 102 Q= 5 R= 359 S= 337 T= 471 U= 142 V= 48 W= 68 X= 13 Y= 82 Z= 1 というわけで、頑張って。

yumikoro0324
質問者

お礼

hanabutako先生、 ご親切なご回答をどうもありがとうございました。 実際のコードありがとうございました。 Tacosan先生の言っている意味がわかりました。 たぶん本では memsetという変数を紹介したかったんだと思います。 今までのPageではなく初登場でしたのであえて紹介したんだと思います。 たしかに使い勝手が悪いので 普通の初期化の方がいいと思いました。 この本は全てscanfを使ってます、基礎編だからでしょうか? getcharはたまにしか出てきません、きっと応用編にいったらgetcharを使うように書いてあるのかもしれません。 whileでも書けるんですね! 見やすいしわかりやすいです! ありがとうございました。 >>str[i] != '\0'とすべき。 >>正しくはputchar('\n')でしょう。 ご指摘ありがとうございました。 間違っていました。ほんとうに私はよく間違えて気付かないので情けないです。 (何回も見直し考えましたが 気づきませんでした涙) すべてを直したら無事にプログラムは動き、結果も正しく得られました。 詳しい解説のおかげで 私が理解できなかった1行も理解することができました。 長々とお付き合い頂きhanabutako先生はじめ 皆さま、どうもありがとうございました。 私が理解できていないのは、頭が悪いのと、C言語を学校へ行かず一人で勉強しようと無茶をしていることと 日本語が得意ではないからです。 何度もこちらで親切で物知りな先生たちに助けてもらいただただ感謝です。 すみませんが、今後ともよろしくお願いします。 ★ゆみころ★

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

その他の回答 (2)

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

#1 への指摘を先にすると, 15行目は「Cannot convert 'int' to 'char *'」だから「EOF が変換できていない」んだと思います. また, 「for()の閉じ括弧がありません」じゃなくて「scanf の呼び出しの閉じ括弧がない」です (おそらくセミコロンのところでエラーになってる). ただ, このプログラムはいろいろと突っ込みどころが.... ・なんで scanf を使ってるんだろう. 1文字ずつ読み込むようにすればバッファオーバーランなど起こりようもないのに. ・条件式しかない for って, あんまり普通じゃないと思う. while はお嫌い? ・そもそもアルファベットがきちんと並んでいるという保証はどこにもない. Windows なら ASCII がベースなので問題ないけど, 一般論としてはアウト. ・str[i]!='0' ・putchar('/n'); memset も微妙だけど (初期化すればいいのに)

yumikoro0324
質問者

お礼

Tacosan先生、 ご指摘どうもありがとうございました。 scanfのカッコはお陰さまで修正済みです、ありがとうございました。 いろいろ突っ込むところはあると思いますが 私はまだ自分で作れるレベルまで達しておらず、本に書いてあるものをそのまま真似して作って 本当に動くかどうかとなぜそのソースで結果が得られるのかを理解するのが精一杯です。 もっと便利な変数があったり、きれいな書き方もあると思いますがどのように修正していくかも今はわかりません。(今回指摘頂いたこともいずれわかるようになりたいです) 分かる人から見たら 気になって仕方ないと思いますが どうぞご了承くださいませ。 今後ともご指導をよろしくお願いします。 ★ゆみころ★

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

>str[i]=(char)toupper(str[i]);/*このソースの意味がわからない。Capitalへ conversionできるのは理解できましたが、なぜ(char)がいるのですか?*/ toupper()のマニュアルを見ましょう。 戻り値の型はint型になっているかと。 小さい型への代入になりますので、明示的にキャストしているのでしょう。 >(alpha[str[i]-'A'])++;/*このソースの意味がわからない 該当文字出現回数を更新しているそうです*/ この中のどの部分が不明…なんでしょうか? str[i]の値は直前の判定で半角アルファベットの大文字であることが確定しています。 つまり'A'から'Z'です。 そこから'A'の文字コードを引いた値はいくつになると思いますか? >for(;scanf("%s",&str[0]!=EOF;) /*continue till EOF(Ctl+z) */ 閉じ括弧が1つ足りないようですが? また、この方法でも256字以上入力するとバッファオーバーランになります。 http://www.kijineko.co.jp/tech/superstitions/buffer-overrun-of-scanf.html scanf("%255s",&str[0]) または scanf("%255s",str) でしょうかね。 >Error E2206 alph2.cpp 10: Illegal character ' ' (0x8140) in function main() ソースコードの10行目に全角空白が紛れ込んでいるようです。 「char str[MAX];」の間違いではありませんか? # charとstr[MAX];の間の空白が全角空白ではありませんか? 多バイト文字は変数名などには使用できないでしょう。 >Error E2206 alph2.cpp 14: Illegal character '[' (0x816d) in function main() >Error E2121 alph2.cpp 14: Function call missing ) in function main() >Error E2206 alph2.cpp 14: Illegal character ']' (0x816e) in function main() &alpha[0]の括弧が全角になっていませんか? >Error E2034 alph2.cpp 15: Cannot convert 'int' to 'char *' in function main() >Error E2121 alph2.cpp 15: Function call missing ) in function main() scanf()の閉じ括弧が無い為、第2引数が「&str[0]!=EOF」になっています。 &str[0]がchar *で、EOFとの比較の為にint型に変換できていません。(「Cannot convert~」のエラー) で、for()の閉じ括弧がありません。(「Function call missing )~」のエラー)

yumikoro0324
質問者

お礼

Wr5先生、 今回もご丁寧なご回答どうもありがとうございました。 (char)toupperについてキャストの概念を忘れていました。 理解できました、ありがとうございます。 >(alpha[str[i]-'A'])++;/*このソースの意味がわからない 該当文字出現回数を更新しているそうです*/ この中のどの部分が不明…なんでしょうか? str[i]の値は直前の判定で半角アルファベットの大文字であることが確定しています。 つまり'A'から'Z'です。 そこから'A'の文字コードを引いた値はいくつになると思いますか? →同じ解説が本にも書いてありましたがまだ私には理解ができません。 前ラインで入力した文字を全て大文字変換しそれをstr[i]へ格収したのは理解できましたがなぜこの一行で出現回数を更新できるのかが謎です。 馬鹿ですみません。 >for(;scanf("%s",&str[0]!=EOF;) /*continue till EOF(Ctl+z) */ →カッコが足りない件のご指摘どうもありがとうございました。 エラーが消えました。 バッファオーバーランのAdditional Inforありがとうございました。 私にはまだ難しくて理解できませんが、わかるようになったら参考にさせて頂きます。 空白や全角ミスのご指摘ありがとうございました。 全てなおし、無事コンパイルはできました。 しかし、実行しても結果がでてきません。涙 まだ何か間違っているのでしょうか? よろしくお願いします。 ★ゆみころ★ *******修正後********* #include<stdio.h> #include<ctype.h> #include<string.h> #define MAX 256 /*Max input data*/ #define ALPHA 26/*Alpha nubmer a - z*/ void main(void) { char str[MAX]; int alpha[ALPHA]; int i; memset(&alpha[0],'\0',sizeof alpha);/*アルファの0配列からalphaの配列分だけ0で埋めてくれる->0で初期化*/ for(;scanf("%s",&str[0])!=EOF;) /*continue till EOF(Ctl+z) */ { for(i=0;str[i]!='0';i++) { if(isalpha(str[i]))/*アルファベットか?*/ { str[i]=(char)toupper(str[i]);/*Capital conversion*/ (alpha[str[i]-'A'])++;/*該当文字出現回数を更新*/ } } } for(i=0;i<ALPHA;i++)/*alphabet 26回分繰り返す*/ { if((i%5)==0)/*横に5こづずならべる*/ { putchar('\n'); } printf(" %c=%5d",i+'A',alpha[i]); } putchar('/n'); } *********実行結果*************** C:\Practice>alph2 this is a pen. ^Z C:\Practice> 何もでてきませんでした涙

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

関連するQ&A

  • Borlandで組んだC+サンプルでエラーに

    borlandでc++のあるサイトのサンプルを動かそうとしたのですが、 C:\borland\work\stl_sample3>bcc32 stl_sample3.cpp Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland stl_sample3.cpp: エラー E2206 stl_sample3.cpp 22: 不正な文字 '$' (0x24)(関数 main() ) エラー E2206 stl_sample3.cpp 30: 不正な文字 '$' (0x24)(関数 main() ) エラー E2206 stl_sample3.cpp 33: 不正な文字 '$' (0x24)(関数 main() ) エラー E2206 stl_sample3.cpp 43: 不正な文字 '$' (0x24)(関数 main() ) エラー E2206 stl_sample3.cpp 45: 不正な文字 '$' (0x24)(関数 main() ) エラー E2206 stl_sample3.cpp 48: 不正な文字 '$' (0x24)(関数 main() ) *** 6 errors in Compile *** というエラーになりました。 22行目は map<string, vector<string> > $_POST; となっています。 もしかして、borland c++コンパイラでは$が使えないのでしょうか? VSでないとダメなのですか?

  • 課題で、アルファベットを入力するとすべてのアルファベットを小文字に変換

    課題で、アルファベットを入力するとすべてのアルファベットを小文字に変換して出力するプログラムを作成しました。2度以上同じ処理を行う場合はその部分を関数としなければいけないのですが、うまくできなかったようです。一応実行結果のとおりに表示されますが、複数のエラーや警告が出ました。どこが間違っているのでしょうか? ・警告 W8065 test.c 9: プロトタイプ宣言のない関数 'henkan' の呼び出し(関数 main ) ・エラー E2379 test.c 10: ステートメントにセミコロン(;)がない(関数 main ) ・警告 W8070 test.c 10: 関数は値を返すべき(関数 main ) ・エラー E2356 test.c 12: 'henkan' の再宣言で型が一致していない ・エラー E2344 test.c 5: 一つ前の 'henkan' の定義位置 ・エラー E2040 test.c 16: 宣言が正しく終了していない ・エラー E2141 test.c 16: 宣言の構文エラー ・エラー E2141 test.c 16: 宣言の構文エラー ・エラー E2190 test.c 29: 不要な } 実行結果↓ **************************** Atsushi TAKEDA ==>atsushi takeda **************************** #include <stdio.h> #include <string.h> #include <ctype.h> int henkan(); int main(void) { henkan() } int henkan; char str[100]; int i,j,chk,len; for(j=0;j<6;j++){ gets(str); len=strlen(str); printf("==>"); for(i=0;i<len;i++){ chk=isupper(str[i]); if(chk!=0) str[i]=tolower(str[i]); printf("%c",str[i]); } printf("\n"); } return 0; }

  • DOSでコンパイルしたらインクルードファイルがない?(開けない?)

    borland c++ コンパイラ5.5をインストールして コマンドプロンプトで実行したのですが こんなメッセージがでました。どうすればよいのでしょうか? ライブラリとかいるんでしょうか? C:\borland\bcc55\Bin>bcc32 ffff.cpp Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland ffff.cpp: エラー E2209 ffff.cpp 1: インクルードファイル 'iostream.h' をオープンできない エラー E2451 ffff.cpp 5: 未定義のシンボル cout(関数 main() ) *** 2 errors in Compile *** ちなみにソースファイルの内容は以下のとおりです。 #include <iostream.h> void main(){ cout<<"ffff"; }

  • このプログラムのどこを直せばいいんでしょうか?

    いま、文字列strの中に文字cが含まれている個数を表示するプログラムを作っているんですが、下のように作っても、上手く行きません。 どこをどう直せばいいのか教えてください! #include <stdio.h> int str_chnum (const char str[],int d) { int i=0; int sum=0; while(str[i]!=0){ if(str[i]==d ){ sum++; } i++; } return(sum); } int main(void) { int c; char str[128]; puts("put sentence..."); scanf("%s",str); puts("search character..."); scanf("%d",&c); printf("there are %d %ds in this sentence.",str_chnum(str,c),c); return(0); }

  • Borland C++ Compiler 5.5について(3)

    つい最近Borland C++ Compiler 5.5をインストールしたんですがコンパイルしようとすると test.cpp: エラー E2209 test.cpp 1:インクルードファイル'stdio.h'をオープンできない。 エラー E2268 test.cpp 5:未定義の関数'printf'を呼び出した(関数 main()) *** 2 errors in Compile*** と出てしまうんですがどういうことなんですか? 教えてください。

  • プログラムのご指摘

    ファイルを読み込み、英字のみか、先頭が英字で二文字目以降が英字または数字である文字列を出力するプログラムを作りたいです。 #include<string> #include<fstream> #include<cctype> #include<iostream> int main (){ char c; std::string key; std::ifstream fin( "1234.txt"); if( fin.fail() ){ std::cerr << "ファイルを開けませんでした" << std::endl; exit(1); } while (fin >> get(c)){ if(!isalpha(c)) continue; key = tolower(c); while (fin >> get(c)){ if (!isalnum(c)){ key.unget(); break; } key = tolower(c); } break; std::cout << key; } } このようなプログラムを作りましたが、↓のエラーが出ていました。 どなたご指摘願います。 エラーメッセージ: sou2-1.cpp: In function `int main()': sou2-1.cpp:20: error: `get' undeclared (first use this function) sou2-1.cpp:20: error: (Each undeclared identifier is reported only once for each function it appears in.) sou2-1.cpp:25: error: `unget' undeclared (first use this function)

  • 10進⇔16進変換プログラム

    こんにちは、C言語を独学しているものです。 すみませんがお助け頂けますでしょうか? C言語の基礎の本のプログラムをそのままコピーしていますが、 私のミス(自分で自覚なし)のためうまく生成できません。 (1)エラーで言っているLについて どうやって修正すべきでしょうか? (2)また、ソース内の/* このソースコードの意味が理解できません */ コメントについて どういう意味を示しているのかお手数ですが教えて頂けませんか? 返信が遅くなるかもしれませんが、必ず目を通し、学ばせて頂きます。 お手数をお掛けしますがよろしくお願いします。 ★ゆみころ★ ************ルール************* 1)プロンプトを表示する 2)”d またはD 10進”が入力されたら 16進へ変換 3)”h,またはH 16進”が入力されたら 10進へ変換 4)”qまたはQ”が入力されたら 終了 5)変数あ 変換指定を保持するフラグと変換すべき数値を保持するものを用意する。 *******ソースコード*********** #include <stdio.h> #include <stdlib.h> void main(void) { char conv_flag[2]; unsigned long data; int loop; for(loop=1;loop;) /*意味がわかりません。Loop=1で初期化(これはOK理解できる);Loop ここでループ継続条件なのですが、なぜLoopだけなのかわかりません*/ { printf("\n>"); if(scanf("%1s",&conv_flag[0]) ==EOF) { continue; /*errorのためこれ以降処理しない*/ } switch(conv_flag[0]) { case 'd':/*10->16*/ case 'D': if(scanf("%ld",&data)=!1) /*意味がわかりません。なぜ=!1 ? これはl (Long) の間違えでしょうか?本には1(いち)に見えますが。。。*/ { scanf("%*s");/*意味がわかりません。入力した文字の始めの一文字目のスペースを読み捨てるということでしょうか?*/ continue; } printf(" =%lX(HEX)",data); break; case 'h':/*16->10*/ case 'H': if(scanf("%lx",&data)=!1) { scanf("%*s"); continue; } printf(" =%lu(DEC)",data); break; case 'q':/*16->10*/ case 'Q': loop=0; break; default: scanf("%*s"); break; } } } *****エラーメッセージ************ C:\Practice>bcc32 16.cpp Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland 16.cpp: Error E2277 16.cpp 21: Lvalue required in function main() Error E2277 16.cpp 32: Lvalue required in function main() *** 2 errors in Compile ***

  • drand48()が使えない

    お世話になっております、皆様のおかげで昨日ウインドウズ上でCを動かせるようになったサルプログラマーです。 Borlandの無償配布をダウンロードしました。Linuxで gcc program1.c -o program1 -lm -O としてコンパイルできていたものをそのまま持ってきて(拡張子変えて)、 C:\bcc>bcc32 program1.cpp としたら Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland program1.cpp: エラー E2268 program1.cpp 61: 未定義の関数 'srand48' を呼び出した(関数 main() ) エラー E2268 program1.cpp 66: 未定義の関数 'drand48' を呼び出した(関数 main() ) *** 2 errors in Compile *** となってしまいました。 いままでプログラムの中身は ======================================================== srand48(seed); for(i=0; i<I; i++){ while(1){ do{ x=drand48()*2.0-1.0; y=drand48()*2.0-1.0; : : ======================================================== という形でLinux上ではコンパイルできてましたが、ウインドウズに持ってきたらダメでした。ある掲示板でdrand48()は非標準関数であるとありましたが、このために使えないのでしょうか?[0,1)のdoubleの乱数を返す、また質がいいからオススメと友達に言われて使っていたのです。ですから非常にいいなあと思って使っていたのですが、どうにかならないでしょうか。使えるようにするにはどうしたらよいのでしょうか、色々あるかと思いますが何か解決方法をご教授ください。

  • C アルファベットのカウント

    #include<stdio.h> #define N 97 #define M 122 int main(void) { char str[ ]="national university"; int i,h,count; char check; for(h=N-1;h<=M;h++){ h++; char check = (char)h; for(i=0;str[i] != '\0';i++){ if(str[i] = check){ count++; } } printf("%c:%d\n",check,count); } } というコードで、アルファベットをそれぞれ何文字使用しているか調べるつもりだったのですが、結果は次のようになってしまいました。解説お願いします。 a:28 c:56 e:84 g:112 i:140 k:168 m:196 o:224 q:252 s:280 u:308 w:336 y:364 {:392

  • bcpadでコンパイルできない

    この前学校でbcpadをつかった授業があったので家でやってみようと思い、 Borland C++ Compiler 5.5 とCPad for Borland C++Compiler をインストールして設定もしました。 そしてbcpadに #include<stdio.h> int main(void){ printf("Hello World"); return 0; } と入力し、保存してコンパイルしてみました。 しかし、以下のようなエラーメッセージが出ました。 「コンパイルに失敗しました ファイル"C:Users\aaaa\downloads\Documents\C\hello.exe" は存在しません」 また下のメッセージのところには hello.cpp: Error E2379 hello.cpp 7: Statement missing ; in function main() *** 1 errors in Compile *** と出ていました。 何がダメなのか全くわかりません。 OSはwindows7です。 どなたか詳しい方ご教授をお願いします。

ADSLから光回線への工事について
このQ&Aのポイント
  • 光回線への切り替えについての疑問について解説します。
  • 光セット契約中で、ADSLから光回線への切り替えを考えています。
  • 光回線の開通工事のみ行えば、契約内容の変更なしで光回線を使用できるかについて説明します。
回答を見る

専門家に質問してみよう