• ベストアンサー

Cについて教えてください。

学校で 「文字列を繰り返し読み込み、英文字以外を削除し小文字を大文字に  変換して表示するプログラムを作成せよ。'!'を入力したとき終了  するようにすること。」 使う関数などについて指定はなく、第1回目の授業で説明もなく課題が 出てしまいました。他にもあるのですが、それはとりあえずできた。 教科書があるので、そちらを参考にしなさいと言うことだと思います。 教科書…ソフトバンクパブリッシング社 改訂新C言語入門-ビギナー編- 環境はUNIXです。dtpadで入力し、ccでコンパイルしています。 自分なりに考えたのは isalpha(x)を使って英文字を認識してtoupper(x)で文字の変換。 入力はcharでしているのでこれらをintに変換してxに文字コード(10進) を入力すればできるかな~と。 また、「繰り返し~」からwhile(1)で無限ループにして、if(a == '!') break で抜けて終わりかな。 と考えたのですが、うまくプログラムが立てることができず困っています。 ぜひぜひ教えて下さい。

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

  • ベストアンサー
  • sasasatto
  • ベストアンサー率20% (4/20)
回答No.4

 もうすでにyatokesaさんが回答なさっているので恐縮ですが・・・こういう書き方もあるということで、もしよかったら参考になさってください。 ============ ここから ============== #include <stdio.h> #include <ctype.h> /* 使用関数宣言 */ void ChangeStrPrint( char *); /* main 関数 */ void main() {  /* 型の宣言 */  char str[256];  /* 入力繰り返し */  while(1){   /* 入力 */   printf("Please Input ---> ");   scanf( "%s", str);   /* 終了記号ならおしまい */   if( str[0] == '!' ) break;   /* 主処理 */   ChangeStrPrint( str);  } } /* 主処理 英文字のみ大文字に変換して出力 */ void ChangeStrPrint( str) char *str; {  /* 型の宣言 */  int i;  printf("\nResult ---> ");  /* 文字列の各文字についてチェックし出力 */  i = 0;  while( str[i] != NULL){   if(isalpha(str[i]))  printf("%c",toupper(str[i]));   i++;  }  /* 出力し終わったら改行 */  printf("\n"); } ============ ここまで ============== これからプログラムの勉強をされるのですね。ソースにコメントを書くくせをつけておくとよいと思いますよ。 がんばってください。

a-k-a
質問者

お礼

>ソースにコメントを書くくせをつけておくとよい そうですね。 perlを少々した事があるんですがperlのコメントは#だけ。 Cは/* */と面倒だなぁと思っていたんですが、やっぱり ある方が見安いですね。 それから質問です。 >/* 使用関数宣言 */ >void ChangeStrPrint( char *); この部分(ChangeStrPrint)は自分で決めたのでしょうか? どういうことをこれでしているのか分からないので、 解説を加えていただけないでしょうか? このままコピーさせていただいたとき、エラーの連発。 ”文字 '0x81' は認識できません。”みたいなの。 いったい何が原因なんだ~~ sasasattoさんの回答を疑ったりもしました(ごめんなさい) 理由は全角スペースがあった。 コピー&ペーストした罰があたったんですね。 おかげでまた一歩知識が増えました。 はやく皆さんのように教えれる立場になりたいです。

その他の回答 (4)

  • sasasatto
  • ベストアンサー率20% (4/20)
回答No.5

 #4です。すいません、遅くなりまして。追加しますね。 >それから質問です。 >>/* 使用関数宣言 */ >>void ChangeStrPrint( char *); >この部分(ChangeStrPrint)は自分で決めたのでしょうか? >どういうことをこれでしているのか分からないので、 >解説を加えていただけないでしょうか?  関数の名前(ChangeStrPrint)は勝手に決めたものです。好きなように決めてよいです。ただ、関数名はなんとなく関数の内容がわかるように決めたほうが、分かりやすいと思います。ちなみに「文字列を変換して出力する」という意味でつけました。  関数の宣言は、「関数を呼び出す方の記述」が「関数の記述」よりも先になる場合に書きます。そうしないと、呼び出し側で「こんな関数しらないよ」という警告がでるからです。(コンパイル時に、あれ?リンク時だったかな)  それから、この問題はとても短いプログラムなので、main関数にすべて書いても大した長さにはならないのですが、プログラムの流れがシンプルに見渡せる方がいいと思ったので、今回は関数に分けました。 >そのままコピーさせていただいたとき、エラーの連発。 >”文字 '0x81' は認識できません。”みたいなの。 >いったい何が原因なんだ~~ >sasasattoさんの回答を疑ったりもしました(ごめんなさい) >理由は全角スペースがあった。  どきっ。このプログラム、コンパイルもなにもしてません。(ごめんなさい。動作確認もしてません。)なので、エラーがあったりするかも・・・  半角のスペースだとなぜかうまくインデント(字下げ)できませんでしたので・・・全角のスペースをいれました。  ご質問に答えられたでしょうか・・・的外れだったらごめんなさい。

a-k-a
質問者

お礼

ありがとうございます。 main関数の中でしかプログラムがかけない=ややこしいのにmainっていらない。 って思ってたんですが、Cではすべてを関数表現するだけあって mainの外に置くこともできるのですね。 学校の参考書では役不足(ビギナー編だし)で、図書館等でも調べてみたら 大体理解できました。 ( char *); これってアドレス渡しとかいうやつかな? 変数の名前にしてもaやbを使ってしまいたくなるのは超初心者の悪いとこ かな?今度から気にしてみます。 (英語も覚えないといけないか・・・) プログラムのエラーの件はこちらのミスですので気になさらないで下さい。 >ご質問に答えられたでしょうか・・・的外れだったらごめんなさい。 完璧です。 ありがとうございました。

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.3

問題文だと「文字列」を繰り返し、ってことですね。前回の回答は的を射ていないようでしたので再度。 文字列を繰り返し、というと 入力>a1b2C3dEf (改行) 出力>ABCDEF 入力>Ghi4JkL56M (改行) 出力>GHIJKLM 入力>! (改行) (終了) という結果を期待しているんだと思います。 これを踏まえて 文字列の入力は char buf[256]; scanf ("%s", buf); こうするとキャラクタコードが buf[0] から順に格納されます。 改行で取り込みが終了し、文字列の終端に '\0'が入り、buf配列は文字列として扱うことができます。 そして、文字列内のキャラクタコードを、ループを使って一文字ずつ文字列の終端('\0')まで検査します。 char buf[80]; int i; whilte (1) {  scanf ("%s", buf);  if (buf[0] == '!') break;  for (i = 0; i < 80; i++) {   if (buf[i] == '\0') {    printf ("\n");    break;   }   if (isalpha(buf[i]) {    printf ("%c", toupper(buf[i]));   }  } } 蛇足ですが先の for 文は for (i = 0; i < 80 && buf[i]; i++) {  if (isalpha(buf[i])) printf ("%c", toupper(buf[i])); } print ("\n"); なんて置き換えることもできます。研究してみてください。

a-k-a
質問者

お礼

ありがとうございます。 このままコピーさせていただいたとき、エラーの連発。 ”文字 '0x81' は認識できません。”みたいなの。 いったい何が原因なんだ~~ yatokesaさんの回答を疑ったりもしました(ごめんなさい) 理由は全角スペースがあった。 コピー&ペーストした罰があたったんですね。 おかげでまた一歩知識が増えました。 はやく皆さんのように教えれる立場になりたいです。 ありがとうございました。

  • sasasatto
  • ベストアンサー率20% (4/20)
回答No.2

 こんにちは。ご質問への回答は#1の方がなさっているので、補足で書かれたことに対して書きますね。 >#include <stdio.h> >#include <ctype.h> > >char a, z; >while(1) { >  scanf("%c",&a); >  if (a == '!') break; >  if (isalpha(a)) { >   z = toupper(a); >   print ("%c",z); >  } >} ということですが・・ 1.mainの記述が抜けている。(わざと書いてないとしたらごめんなさい) 2.「12ab9c」と入力したいと書いてあるのですが、このプログラムだと一文字を入力して出力、また一文字を入力して出力・・・となります。  イメージだと・・・(単純な画面に出力として)  12aAbB9cC (1,2,a,b,9,cは入力文字、A,B,Cは出力文字)となります。(改行マーク"\n"がない為です)  「文字列」を繰り返し入力したいのか、「文字」を繰り返し入力したいのかで、若干プログラムは変わってくると思うのですが・・・補足お願いします。

a-k-a
質問者

補足

>1.mainの記述が抜けている。 忘れてました(^^ゞ これはまぁ全体を入れればOKということでクリア~ >2. 「文字列」の方です。 課題の内容から、そう推測したのです。 >単純な画面に出力として かまいません。 端末エミュレータ上でコンパイル-実行-結果、すべてします。 >出力結果・・・12aAbB9cC そうなりそうですね。 ちょっと思ったのですが、mainを書いたとして僕の書いたプログラムで とりあえず変換まではできるということでしょうか? あとは文字列ってことになります? ここで参考書をみたんですが、Cには文字列型はなく配列を使う。 見たいな事が書いてありました。 配列は全く分からなく、とりあえず考えて見ようと思いますが、 今回のサンプルプログラム的なものを例示していただけないでしょうか? 質問している身でお願いしている自分が悲しいですがよろしくお願いします。 ではまた、足らないことがあれば。

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.1

考え方に問題はないですよ。 a-k-aさんの書いていらっしゃることをそのままプログラムにすると char a, z; while(1) {  a = 読み込み処理  if (a == '!') break;  if (isalpha(a)) {   z = toupper(a);   z の出力処理  } } となります。入出力(ファイル/キー入力/画面出力等)の対象が何なのかによって多少構造を買えなければならない場合もありますが、基本的な流れは変わりません。

a-k-a
質問者

補足

入力はキーボードから。 scanf("%c",&a); として出力はそのまま画面にでてくればOKです。 例:) 12ab9c <-----入力 ABC <-----出力 イメージとしてはこのようになって欲しいと思っています。 気になったことですが、isalpha(a)でaがcharとなっていますが、 参考書の記述では int isalpha(c) となっていたのですが、 これはisalpha()はint型で使いなさい。と理解したのですが、 違うのでしょうか? 書き方が理解できていないので補足ありましたら お願いします。 今自宅からで環境がないので、実地テストができなく申し訳ないのですが、 一応考えてみました。 #include <stdio.h> #include <ctype.h> char a, z; while(1) {  scanf("%c",&a);  if (a == '!') break;  if (isalpha(a)) {   z = toupper(a);   print ("%c",z);  } } 間違っているのだと思うのですが、該当箇所が分かればお願いします。 質問ばかりで申し訳ありません。