• ベストアンサー

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

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

  • a-k-a
  • お礼率43% (77/176)

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

  • ベストアンサー
  • 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);  } } 間違っているのだと思うのですが、該当箇所が分かればお願いします。 質問ばかりで申し訳ありません。

関連するQ&A

  • C言語の変換する関数について教えてください。

    キーボードからローマ字で入力された名前の英文字を変換する関数を定義し、その関数の機能を確認するプログラムを作成する問題について教えてください。 (1)英小文字であればそれを英大文字に変換する関数 (2)英大文字であればそれを英小文字に変換する関数 (3)英小文字であればそれを英大文字に、英大文字であればそれを英小文字に変換する関数 ただし、キーボードから入力された名前を格納する配列と、変換後の名前を格納する配列を別にする。 また、名前は関数main()内で表示する #include <ctype.h> #include <stdio.h> void name_toupper(char str[]) { unsigned i = 0; while (str[i]) { str[i] = toupper(str[i]); i++; } } void name_tolower(char str[]) { unsigned i = 0; while (str[i]) { str[i] = tolower(str[i]); i++; } } int main(void) { char str[100]; printf("文字"); scanf("%s", str); name_toupper(str); printf("大文字: %s\n", str); name_tolower(str); printf("小文字: %s\n", str); return 0; } 自分で作った上のプログラムではKa siと入力すると(1)ではKA、(2)ではkaと表示されsiが消えてしまいます。原因がよくわかりません。 あと(3)ができないし、ただしを満たしているのかもあいまいです。 文字列の入力の形式:char *gets(char *buffer)を用いればどうにかなるのではと思っていますがどうですか? 説明が長くなって申し訳ありませんが教えてください。 よろしくお願いします。

  • C言語の変換する関数について教えてください。

    キーボードからローマ字で入力された名前の英文字を変換する関数を定義し、その関数の機能を確認するプログラムを作成する問題について教えてください。 (1)英小文字であればそれを英大文字に変換する関数 (2)英大文字であればそれを英小文字に変換する関数 (3)英小文字であればそれを英大文字に、英大文字であればそれを英小文字に変換する関数 ただし、キーボードから入力された名前を格納する配列と、変換後の名前を格納する配列を別にする。 また、名前は関数main()内で表示する。 #include <ctype.h> #include <stdio.h> void name_toupper(char istr[], char ostr[]) { unsigned i = 0; while (istr[i]) { ostr[i] = toupper(istr[i]); i++; } } void name_tolower(char istr[], char ostr[]) { unsigned i = 0; while (istr[i]) { ostr[i] = tolower(istr[i]); i++; } } void name_change(char istr[], char ostr[]) { unsigned i = 0; while (istr[i]) { if(isupper(istr[i])) { ostr[i] = toupper(istr[i]); } else { ostr[i] = tolower(istr[i]); } i++; } } int main(void) { char buffer[100]; printf("文字"); gets(buffer); name_toupper(buffer); printf("大文字: %s\n", buffer); name_tolower(buffer); printf("小文字: %s\n", buffer); name_change(buffer); printf("大小交換: %s\n", buffer); return 0; } 上のプログラムでは、呼び出し時のパラメータが足りないとエラーが発生してしまいます。文字列を入れておく配列をbuffer以外にもう一つ作らなくてはいけないと思うのですが、うまくいきません。 教えてください。よろしくお願いします。

  • 計算機言語(C言語)の課題です。

    ポインタstrが文字列の先頭文字を指している時、その文字列に含まれる英小文字を英大文字に変換する関数 void str_toupper(char *str) を作成しなさい。ただし、英小文字a~zおよび英大文字A~Zには、それぞれ昇順に、連続した1バイトの整数が割り当てられているものとする。例えば、aには10進数の97、zには10進数の122が割り当てられ、Aには10進数の65、Zには10進数の90が割り当てられるといった具合である。

  • c言語プログラミングHELP!

    c言語でプログラムを組んでるんですが、どうしてもわからないものがありまして、 まず一つ目がキーボードから英小文字を一つ入力し、その文字を大文字に変換して出力するプログラミングです。結果がまずひとつの英小文字を入力して、入力した文字と、大文字に変換した文字を出力するプログラミングです。 ちなみにヒントは'a'=97,'A'=65です 二つ目が二桁の16進数('41'から'49','50'から'59')を入力すると対応する文字を表示するプログラミングです。また、%xは使用しないこと。なお、入力に間違いはないものとする。(ヒントは入力は一つの数値か、二つの文字か?だそうです。) 結果は二桁の16進数('41'から'49','50'から'59')を入力して、文字コードの二桁の数字と文字を出力するプログラミングです。 お願いします。

  • ファイルからの変換

    c言語初心者です。 あらかじめファイルを作っておいて その中に小文字でvffjfと入れておきます。 それを読み取り大文字に変えファイルに表示させるプログラムをつくりたいのですが、 toupperの使い方や、変換させてまた再度入力させるには どのようなものが必要ですか?

  • c言語.ctrl文字の読み取り

    unixでのプログラミングについてです. コンソールで,キーボードから[ctrl+英文字]が入力されたことが 分かるプログラムを作りたいのですが, どのようにすればいいのでしょうか. 例えばctrl+Cやctrl+Zならば,signal.hを利用すれば入力された事がわかりますが, シグナルを送るキーでない,ctrl+Lなどはどのようにすれば 押されたことが分かりますか. よろしくお願いします.

  • 初心者です。C++の課題

    C++の課題が出たのですが、行き詰まりました。 cinで入力した英数字、記号から、文字の系列に変換するプログラムで、 例えば、abbcdeee00))) と入力した場合、 a b c d e 0 ) と出力されるようにしたいのです。 条件は、 入力した文字系列はchar型の変数に1文字ずつ入力されること、 使えるのは、for、while、if のみ、 入力はEOFで終わること、 以上です。どなたか教えてください。

  • c言語で文書検索プログラムについて質問です。

    いつもお世話になっています。 今回、大学の課題でc言語を用いて文書検索のプログラムを作成しています。 クエリ(検索単語)を2つ入力して、クエリ2つを同じ行に含む1文が存在した場合そのテキストファイルのファイル名を出力するプログラムを作成しています。 検索する文書は、ソースファイルと同じディレクトリにあるcorpusディレクトリ内のテキストファイルについて行います。 概ね、自力で作成はできているよう思うのですが、どうしても出力がうまくいきません。 出力条件、もしくはstrcmpのあたりに原因があるような気がするのですが・・・。 以降に私の作成したソースファイルを添付しておきますので、 原因のわかる方ぜひお願いします。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<ctype.h> int main(int argc, char* argv[]){ FILE* fp; char buffer[1024]; char kueri1[256]; char kueri2[256]; int flag_kueri = 0; //kueri1,kueri2がどちらもあれば1に int flag_kueri1 = 0; //kueri1があれば1に int flag_kueri2 = 0; //kueri2があれば1に int i; cahr* s; char* delimiter = " .,"; /*コマンドラインが正しく入力されているかの確認*/ if(argc < 4){ printf("error1\n"); exit(1); } /*入力されたクエリ1をkueri1に格納*/ strcpy(kueri1,argv[1]); /*入力されたクエリ2をkueri2に格納*/ strcpy(kueri2,argv[2]); /*kueri1の英小文字を英大文字に変換する処理を\0まで繰り返す*/ s = kueri1; while(*s != '\0'){ *s = toupper(*s); s++; } /*kueri2の英小文字を英大文字に変換する処理を\0まで繰り返す*/ s = kueri2; while(*s != '\0'){ *s = toupper(*s); s++; } /*メインループ*/ for(i = 3; i < argc; i++){ /*ファイルを開く*/ if((fp = fopen(argv[i], "r")) == NULL){ printf("error2"); exit(1); } /*文書を1行ずつ読み込んで処理を行う*/ while(fgets(buffer,sizeof(buffer),fp) != NULL){ /*最後に\0を格納*/ buffer[strlen(buffer) - 1] = '\0'; /*bufferの英小文字を英大文字に変換する処理を\0まで繰り返す*/ s = buffer; while(*s != '\0'){ *s = toupper(*s); s++; } /*strtokを用いて単語ごとに区切っていく(1単語目)*/ s = strtok(buffer,delimiter); if(s != NULL){ /*kueri1かどうか判定*/ if(strcmp(s,kueri1) == 0){ flag_kueri1 = 1; } /*kueri2かどうか判定*/ if(strcmp(s,kueri2) == 0){ flag_kueri2 = 1; } /*strtokを用いて単語ごとに区切っていく(1単語目)*/ while((s = strtok(NULL,delimiter)) != NULL){ /*kueri1かどうか判定*/ if(strcmp(s,kueri1) == 0){ flag_kueri1 = 1; } /*kueri2かどうか判定*/ if(strcmp(s,kueri2) == 0){ flag_kueri2 = 1; } } } /*kueriが両方なかったらflar_kueriを1にする*/ if(flag_kueri1 == 1 && flag_kueri2 == 1){ }else{ flag_kueri = 1; } /*両方のkueriがあればファイル名を出力*/ if(flag_kueri == 0){ s = argv[i]; printf("file_name: %s",s); } } fclose(fp); exit(0); }

  • プログラミングC

    以下に示すプログラムは、キーボードから39文字以下の文字列を入力した後で、その文字列を表示するプログラムである。ただし、文字列の表示においては、printf命令における変換指定で、%sを使用するのが一般的であるが、以下のプログラムあえて%sを使用せずに、%cを使っている。このプログラムについてキーボードから入力される文字列の文字数が391文字以下である限り、その文字列を正しく表示できるよう、下線部を埋めてプログラムを完成させなさい。 char x[40],i printf("39文字以下の文字列を入力:"); scanf("%s",x); for(i=0;x[i]_____;i++) printf("%c",x[i]); printf("です。\n"); [実行例] 39文字以下の文字列を入力:programming 入力された文字列はprogrammingです。

  • C言語

    (a) キーボードから入力された文字列をそのままディスプレイに表示するプログラムを作成しなさい。 という問題 #include<stdio.h> main() { char word[1000]; /*文字型の変数の宣言*/ scanf("%s", word); /*キーボードから文字列を入力*/ printf("%s\n", word); /*入力した文字列を出力*/ } と作りましたがこれではコンソール中で文字を打ってからエンターを押さないといけないからといわれ再提出になってしまいました。 エンターを押さないでそのまま出力するということは、できるのでしょうか? あと自分の作ったプログラムではスペースや改行を使うことができないから使えるようにしろと言われてましたがそれわできますか? 変換仕様をかえればいいのですか ほかにもかえる所はありますか?

専門家に質問してみよう