ページ 1 / 1
宿題教えてください。
Posted: 2008年1月30日(水) 17:11
by すず
C言語で秀丸を使っています。その宿題は,問題:prog12f.cのプログラムを改良し,アルファベットの
全ての文字を大文字にして表示するようにせよ.但し,文字
列の長さを求めるstrlen関数は使ってはいけない.単語単位で文字列を逆順にする点などは,そのままです.
読み込むファイルは前回と同じですが,そのファイルしか
処理できないようなプログラムはダメです。prog12f.cは添付します。
Re:宿題教えてください。
Posted: 2008年1月30日(水) 17:33
by バグ
それで、その宿題の何が分からないのでしょうか?
自分ではどこまで取り組んでみましたか?
Re:宿題教えてください。
Posted: 2008年1月30日(水) 17:53
by たかぎ
そのまま答えを書くのも問題がありそうなので、参考までにC++で書いてみました。
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <iterator>
#include <cctype>
int main()
{
std::string str;
while (std::cin >> str)
{
std::transform(str.rbegin(), str.rend(),
std::ostream_iterator<char>(std::cout),
std::ptr_fun<int, int>(&std::toupper));
std::cout << ' ';
}
return 0;
}
多分、参考にならないでしょうけど。
Re:宿題教えてください。
Posted: 2008年1月30日(水) 18:07
by やそ
おおっと、重鎮が率先してお答えされているではないですか(笑)
>すずさんへ
具体的な質問内容が明記されておりませんが、何をお聞きしたいのでしょうか?
それとも答えだけ教えて欲しい「丸投げ」でしょうか。
丸投げ(お手上げ)ならばここのルールに則りその旨をきちんと明記して、自分は前回の問題「prog12f.c」はどこまで理解できているか(自分の実力はどの程度か)も明記してください。
またファイルの仕様が見えません。
前回の問題に使ったtest.txtの内容もさらしていただくか、
ファイルの仕様を公開してください。
1レコードの最大文字数や内容に関する制限(数字や記号、2バイトレコードの可否)は?
回答する側の立場に立てば、どのような質問の仕方が満足のいく回答を得られるか分かっていただけると思います。
きっと、大文字小文字の入り混じった英文なんでしょうね。
1行の文字数もそれほど長いものではなさそうですね(a[20]ですからね^^;)
1単語=1レコードでしょうかね。
ならばfscanf()で読み込んでいるのも頷けるのですけど。
また、問題文を要約すると・・・
問題:prog12f.cのプログラムを改良し,アルファベットの
全ての文字を大文字にして、単語単位に逆順に表示するようにせよ.
と言うことでしょうか?
Re:宿題教えてください。
Posted: 2008年1月30日(水) 18:17
by keichan
>多分、参考にならないでしょうけど。
教師に各ステップで何をやっているのか聞かれたらoutでしょうね。
質問者さんへ
・なにが/どこが分からないのか具体的なポイントを提示して頂かなければ回答が付きにくいと思います
・どこがわからないのかが「わからない」場合は、ソースを書こうとせずに作業の工程を洗ってみてはどうでしょうか
(ファイルオープン処理・ファイル読み込み処理etc)
・(バグさんも仰っていますが)ご自身でどこまで試行錯誤したかの後が見受けられれば、間違っている点や改善点を指摘しやすくなります
・頑張ってください
Re:宿題教えてください。
Posted: 2008年1月30日(水) 23:43
by tk-xleader
>文字列の長さを求めるstrlen関数は使ってはいけない
ということはstrlen関数を使えば効率よく作業ができるということです。つまり類似関数を自作しちゃいましょう。
int GetStringLength(const char *string)
{
int count=0;
while(string[count]!='\0')count++;
return count;
}
まぁこれくらいは文章から分かりそうです。
Re:宿題教えてください。
Posted: 2008年1月31日(木) 00:35
by tk-xleader
使うべき関数群(組み合わせは考えて下さい)
fopen
fscanf
fclose
printf
isupper
islower
tolower
toupper
関数の詳細は検索などで調べてください。
Re:宿題教えてください。
Posted: 2008年1月31日(木) 11:34
by たかぎ
大サービスでC言語でも作ってみました。
前回もそうでしたが、面倒なので今回も標準入力からの入力にしています。
ファイルから入力したいのであれば、リダイレクトするか適当に修正してください。
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
bool sub(void)
{
if (feof(stdin)) return false;
int c = getchar();
if (isspace(c)) return true;
bool result = sub();
putchar(toupper(c));
return result;
}
int main(void)
{
while (sub()) putchar(' ');
return 0;
}
例によって、多分参考にはならない気がします。
質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 11:53
by すず
c言語のプログラミングは超初心者です。ファイルの入出力にという章でfopen,fclose,fscanf,fprintfなど基本的なことは習いました。例題で書き込んだファイルを読み込むというのもやったことがあります。でもこの宿題が出題されてお手上げ状態です。答えを教えてください。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 12:07
by たかぎ
> 答えを教えてください。
↓これではダメでしょうか?
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
bool sub(FILE *stream)
{
int c = fgetc(stream);
if (c == EOF) return false;
if (isspace(c)) return true;
bool result = sub(stream);
putchar(toupper(c));
return result;
}
int main(void)
{
FILE *stream = fopen("test.txt", "r");
if (stream != NULL)
{
while (sub(stream)) putchar(' ');
fclose(stream);
}
return 0;
}
元のプログラムの原型を留めていませんが、とことん改良したということにでもしてください。
ただし、何をやっているのか説明できるようにだけはしておいてください。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 12:14
by たかぎ
一応、元のプログラムの主な問題点を指摘しておきます。
char a[20], b[20];
…
fscanf(fp,"%s",a);
これではバッファオーバーランが発生します。
仮にバッファオーバーランを防いでも、scanf や fgets を使ったのでは、どうしても単語の文字列長に制限が出てしまいます。
if(a[0] >= 'A' && a[0] <= 'Z')
…
if(b[0] >= 'a' && b[0] <= 'z')
'A'~'Z' および 'a'~'z' が連続であることは保証されていません。
http://www.kijineko.co.jp/tech/supersti ... uence.html
a[0] += 32;
…
b[0] -= 32;
特定のエンコーディングに依存しているようです。
今回の質問では処理系を特定していませんので、こういう書き方はできません。
先ほどの「答え」は、これらの問題点を「改良」しています。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 13:07
by やそ
>たかぎさんへ
回答のプログラムのレベルが高すぎます(苦笑)
すずさんのレベルは・・・
>>c言語のプログラミングは超初心者です。ファイルの入出力にという章でfopen,fclose,fscanf,fprintfなど基本的なことは習いました。例題で書き込んだファイルを読み込むというのもやったことがあります。
と言うレベルです。
いきなりたかぎさんの出された回答を読み解くのはキツいんじぁ・・・(再帰とか再帰とか(笑))
すずさんは答えが欲しかったらどのような答えが欲しいのか示さないといけません。
お手上げなのは分かりましたが、皆さんが懸念されている問題点について分かっていることはありませんか?
1.そのC言語を動かしている環境。WinやMacなどのPCでしょうか?unix系でしょうか?汎用機でしょうか?その処理系によりコード体系も変わってきますので、たかぎさんの指摘する・・・【'A'~'Z' および 'a'~'z' が連続であることは保証されていません。】に関わります。
2.すずさんが今までに習った関数や命令は?今回みなさんがいろいろ大サービスで提示してくださっているプログラムでそれぞれ使用されている関数は理解できますか?また今回使用しても良さそうですか?
(たかぎさんが言うように「とことん改良したんです」と言い張るにはそれらの関数や、プログラムの流れを理解して他人に説明できるようでないと、カンニングがバレてしまいます(笑))
3.ファイル読み込み時のバッファーオーバーランの可能性については特に先生?から指示(指摘)はなかったのでしょうか?完全に「入力されてくる文字列には間違いはない!」という善意に頼った仕様でよろしいですか?
まあ、せっかく回答が得られたのだから、それを必死に読み解いていただいてすずさんの血肉となればOKすよ。がんばってください。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 13:17
by たかぎ
> まあ、せっかく回答が得られたのだから、それを必死に読み解いていただいてすずさんの血肉となればOKすよ。がんばってください。
要するにそういうことですね。
同じカンニングするなら、有意義なカンニングの仕方をしましょう。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 13:26
by たかぎ
こちらにもコメント
> 1.そのC言語を動かしている環境。WinやMacなどのPCでしょうか?unix系でしょうか?汎用機でしょうか?その処理系によりコード体系も変わってきますので、たかぎさんの指摘する・・・【'A'~'Z' および 'a'~'z' が連続であることは保証されていません。】に関わります。
今回の宿題に関しては、(多バイト文字を扱うのでない限り)処理系に依存しなければ実装できないような要素は一つもありません。
ところで、先に示したコードはC99に対応したコンパイラでなければコンパイルできません。
処理系を特定していないので、(いつものように)現行規格に従いましたが、規格のバージョンに制約があるなら、それを指定してください。
> 2.すずさんが今までに習った関数や命令は?今回みなさんがいろいろ大サービスで提示してくださっているプログラムでそれぞれ使用されている関数は理解できますか?また今回使用しても良さそうですか?
(たかぎさんが言うように「とことん改良したんです」と言い張るにはそれらの関数や、プログラムの流れを理解して他人に説明できるようでないと、カンニングがバレてしまいます(笑))
難しい関数は一つも使ってないんですけどね。
> 3.ファイル読み込み時のバッファーオーバーランの可能性については特に先生?から指示(指摘)はなかったのでしょうか?完全に「入力されてくる文字列には間違いはない!」という善意に頼った仕様でよろしいですか?
これについては、
> 読み込むファイルは前回と同じですが,そのファイルしか
> 処理できないようなプログラムはダメです。
とあるのでダメでしょう。
バッファオーバーランは論外として、文字列の長さに制限があるのもダメですね。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 13:52
by やそ
> 読み込むファイルは前回と同じですが,そのファイルしか
> 処理できないようなプログラムはダメです。
とあるのでダメでしょう。
バッファオーバーランは論外として、文字列の長さに制限があるのもダメですね。
たしかにそうでしたね。
これはたかぎさんのコードで回避可能ですね^^
文字コードについてもまあ、ASCIIコードにしたがっているのなら問題ないでしょうね。
全角(2バイト)英数OKとかでも無い限り(笑)
EBCDICをつかってたら気をつける必要ありなのかな^^;
問題文の最後に「単語単位で文字列を逆順にする点などは,そのままです.」
と有りますが、これはすずさん自身に考えてもらいましょうかね?
(っていうか、”そのままです”っていうのは結局やるの?やらないの?(笑))
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 15:47
by tk-xleader
ある程度は自分でやる必要もあると思います。まぁ単語を逆順に配列に配置しなおす関数を書いてみます。
void ReverseString(char *string)
{
int strsize,i;
char *temp;
strsize=GetStringLength(string);
temp=malloc((strsize+1)*sizeof(char));
temp[strsize+1]=string[strsize+1];
while(i<=strsize){
temp=sizeof[strsize-i];
i++;
}
i=0;
while(i<=strsize){
string=temp;
i++;
}
free(temp);
}
答えは出てますが、自分で考えるなら手助けします。
修正:mallocの引数が大問題だったので修正。{malloc(strsize+1*sizeof(char);→malloc((strsize+1)*sizeof(char));}
いろいろ回答ありがとうございます。
Posted: 2008年1月31日(木) 16:11
by すず
C言語を動かしている環境はWindowsXPです。たかぎさんのプログラムを実行しみたら「インクルードファイルがオープンできません。」と表示されました。test.txtは添付しておきます。皆さんの使っている関数は正直理解できないのが多いですが,インターネットで調べてなんでもつかってもよいと言われています。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 16:18
by やそ
tkさんもお優しいなぁ^^
このtkさんのプログラムは
Date: 2008/01/30(水) 23:43
の投稿にある
GetStringLength()もあわせて見る必要があるのだ!!(笑)
mallocの引数の計算もなんでこのような計算式が必要なのか。考えてみると非常にお勉強になってよいと思いますです^^
また、一つ目のwhileループの際にiの初期値を追加しておいたほうがいいかも^^
temp[strsize+1]=string[strsize+1];
i=0;
while(i<=strsize){
temp=sizeof[strsize-i];
i++;
}
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 16:25
by たかぎ
> インターネットで調べてなんでもつかってもよいと言われています。
では、おそらくエラーが出たのであろう <stdbool.h> についても調べてみましょう。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 16:50
by やそ
>インターネットで調べてなんでもつかってもよいと言われています。
というのは、「調べる技術も実力のうち」
と言う考えなのかもしれません。
ここのような掲示板で聞くことも大きく捉えればそのうちに入るかもしれませんが、
即時性は無いので、googleなりWikiなりいろいろ活用して調べるクセをつけると良いでしょう。
検索のキーワードもひとつだけに限らず、いろんな角度からやって見ましょう。
stdboolは調べればすぐに出ますよね^^
エラーになったと言うことは、それが用意されていなかったわけで、
ヘッダファイルを探して(作って)保存するなり、内容をベタ打ちしてもいいでしょう。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 17:02
by たかぎ
> ヘッダファイルを探して(作って)保存するなり、内容をベタ打ちしてもいいでしょう。
現実にはヘッダファイルを用意しただけでは済まないんですけどね。
調べるべきキーワードは「C99」です。
ちなみに、私もWindows XPで動作確認しましたが、コンパイラはCygwin上のGCCを使いました。
Re:質問が明確でなくてすいません。
Posted: 2008年1月31日(木) 17:05
by たかぎ
> stdboolは調べればすぐに出ますよね^^
試しにGoogleで検索してみると、更新をサボっている私のブログがトップに来るではないですか。
そこは余り参考にならないので、別のサイトを見たほうがいいです。
無題
Posted: 2008年2月01日(金) 11:31
by すず
いろいろありがとうございました。後は自分で調べるなりしてやっていきたいと思います。