ページ 1 / 1
コマンドラインについて
Posted: 2006年12月14日(木) 21:49
by 努力中
先輩が今授業で「コマンドライ」というものを扱っているらしく、来年同じ科目を履修しようとしていたので、自主的に先生に少し教えていただいた後、次のような課題をいただきました。
コマンドラインからのファイルの指定を利用して,read-b.txtから英文を読み込み,ファイル内にあるa~z,ピリオド,カンマ,スペースのそれぞれの文字数をwrite-b.txtに書き出せ.ただし,大文字,小文字は区別しない.
プログラムの読み込みに使うfopen fclose等をおそらく使うのであろうと予想し、考えていますが、さすがに先輩たちがやっているだけあって、ほとんど知識の無い初心者の自分には難しいです。 書き始めの部分に#include<stdio.h> 以外にほかにどんなものが必要なのでしょうか。 できれば途中までのプログラムを示していただければ幸いです。 よろしくお願いします
Re:コマンドラインについて
Posted: 2006年12月14日(木) 22:47
by 管理人
えぇと、努力中さんがどの程度プログラムの知識をもっていらっしゃるかで説明のしかたがかなり変わると思うので
一度、どの程度知っていらっしゃるか、教えてもらえませんか?
たとえば
1 stdio.h以外には何もインクルードしたことがありませんか?
2 コマンドラインからの入力は今までやったことがありませんか?
3 配列・ポインタについて一通り勉強されていますか?
4 文字列操作・ファイル操作について、勉強されていますか?
Re:コマンドラインについて
Posted: 2006年12月14日(木) 23:04
by 管理人
では、コマンドラインからご説明します。
#include <stdio.h>
int main(int argc,char *argv[/url]){
int i;
printf("引数の総個数 = %d\n", argc);
for (i = 0; i < argc; i++)
printf("%d番目の引数 = %s\n", i, argv);
}
コマンドラインから入力を受けるとき、メイン文はこのように書き始めます。
int main(int argc,char *argv[/url]){
argcには引数の数が、argvにはそれぞれの文字列が・・とかいうよりまぁ実行結果を見てください。
このプログラムの実行ファイルをtest.exeとしましょう。Cドライブの直下にあるとします。
その時。test.txtを引数に持たせたいときはこのように書きますね。
C:\>test.exe test.txt
このように入力して実行したとき、どのような結果になるかサンプルを示します。
C:\>test.exe test.txt
引数の総個数 = 2
0番目の引数 = test.exe
1番目の引数 = test.txt
C:\>は最初から表示されていますから含まれません。
test.exe test.txtが自分の入力した部分ですね。
argvというのは2次元配列になっています。
argv[0]と示すと、argv[0][0]から成る配列の先頭アドレスを示します。
つまり
argv[0]にはtest.exeという文字列が入っている先頭アドレスが入っており、
argv[1]にはtest.txtという文字列が入っている先頭アドレスが入っており、
argcには何個入力の文字列があったか、その個数が入っています。
今回はtest.exeとtest.txtの2つがありますから「2」が入っています。
これでコマンドラインについてはいいでしょうか?
Re:コマンドラインについて
Posted: 2006年12月14日(木) 23:30
by 管理人
先に行っていいかどうかわからないですが、次の説明します。
コマンドラインから受け取った文字列を使ってファイルをオープンする方法。
先に説明したとおり、argcは2が入っていることが期待されます。
しかし2が入っていない場合がありますから、そのときは即終了させましょう。☆1
fopenによってファイルポインタを取得し、それが無効なら終了させます。☆2
読み込みをするので読み込み形式であるrで指定しましょう。
ここからファイル内容の処理を行います。
☆3で開いたファイルは閉じましょう。
#include <stdio.h>
#include <stdlio.h>
int main(int argc,char *argv[/url]){
FILE *fin;
if(argc!=2){//☆1
printf("引数の数が正常ではない\n");
return 1;
}
if((fin = fopen(argv[1], "r")) == NULL ) {//☆2
printf("入力ファイルオープンエラー\n");
return 1;
}
//ここにファイル内の操作
fclose(fin);//☆3
return 0;
}
ここまでいいですか?
Re:コマンドラインについて
Posted: 2006年12月14日(木) 23:46
by 管理人
まず、test.txtを作りましょう。
http://dixq.net/txt/test.txt
からダウンロードして、コンパイルするフォルダにいれてください。
読み込みについては上記に示したとおりです。
fgetc(fin)はfinで指定した部分から1文字とってくる関数です。
それをcに代入し、EOF(ファイルの終わり)なら終了します。
fputc(c,fout);
はさきほど格納したcを書き出しファイルように用意したfoutに書き込む関数です。
これをファイルの終わりまで続けると、結局同じファイルが2つ出来ます。
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[/url]){
FILE *fin, *fout;
int c;
if(argc!=3){
printf("引数の数が正常ではない\n");
exit(1);
}
if((fin = fopen(argv[1], "r")) == NULL ) {
printf("入力ファイルオープンエラー\n");
exit(1);
}
if((fout = fopen(argv[2], "w")) == NULL ) {
printf("出力ファイルオープンエラー\n");
exit(1);
}
while ( (c=fgetc(fin)) != EOF)
fputc(c,fout);
fclose(fin);
fclose(fout);
return 0;
}
実行コマンドは
C:\>test.exe test.txt test2.txt
といった形で行ってください。
test.txtと同じ内容のtest2.txtが生成されます。
Re:コマンドラインについて
Posted: 2006年12月15日(金) 09:04
by 努力中
お返事が遅くなってしまい、まことにもうしわけありません。 丁寧な解説ありがとうございます。 自分は学校の授業では、まだプログラミングを履修しておらず、コンパイルやジャンケンゲームなどをかろうじてつくることができる、超初心者です。管理人さんが上げた4個の項目のうち2番3番4番に該当するとおもわれます。
引数の説明も一応先生におききしたのですが、管理人さんの説明のほうがわかりやすかったです
Re:コマンドラインについて
Posted: 2006年12月15日(金) 11:19
by 管理人
努力中さん、おはようございます^^
まだ履修していらっしゃらないのなら説明難しく無かったですか?
2次元配列とか配列の先頭アドレスとかって説明でわかりました?
もし配列やポインタがわからなければ、そこを重点的に勉強してからこの課題に挑むとよりよく解ると思いますよ^^
Re:コマンドラインについて
Posted: 2006年12月15日(金) 12:23
by 努力中
おはようございます管理人さん なんとか理解しはじめていけています。 今回のかだいで、引数などの数字系統の例題は教科書などにのっていたのですが、アルファベット系統のものがのっておらず、どうしようかと悩んでいますまた、スペースの区別などはどうすればいいのでしょうか
Re:コマンドラインについて
Posted: 2006年12月15日(金) 12:34
by 管理人
例えば、このようなプログラムは処理の意味がわかりますか?
#include <stdio.h>
int main() {
int i;
char str[20]="abcd ABCD aAbBcCdD ";
for(i=0;i<20;i++){
if(str!=' ')
printf("%c",str);
}
return 0;
}
このプログラムの意味がわかれば、その疑問も晴れるかと思います。
このプログラムはスペース以外を出力するプログラムです。
行いたい処理は具体的にどんな処理ですか?
Re:コマンドラインについて
Posted: 2006年12月15日(金) 12:41
by 管理人
また、文字コードについての知識も備えておけばよりよいでしょう。
#include <stdio.h>
int main() {
char x='1';
printf("%c %d\n", 'a' , 'a' );
printf("%c %d\n", 'a'+1, 'a'+1);
printf("%c %d\n", 'a'+2, 'a'+2);
printf("%c %d\n", x , x );
printf("%c %d\n", x+1 , x+1);
printf("%c %d\n", x+2 , x+2);
return 0;
}
Re:コマンドラインについて
Posted: 2006年12月15日(金) 20:17
by 努力中
丁寧なかいせつありがとうございます。管理人さんにしめしていただいた以下の式を引数のプログラムに置き換えるという感じでしょうか
#include <stdio.h>
int main() {
int i;
char str[20]="abcd ABCD aAbBcCdD ";
for(i=0;i<20;i++){
if(str!=' ')
printf("%c",str);
}
return 0;
}
Re:コマンドラインについて
Posted: 2006年12月15日(金) 20:37
by 管理人
スペースを除去したいのですか?
Re:コマンドラインについて
Posted: 2006年12月15日(金) 21:52
by 努力中
「コマンドラインからのファイルの指定を利用して,read-b.txtから英文を読み込み,ファイル内にあるa~z,ピリオド,カンマ,スペースのそれぞれの文字数をwrite-b.txtに書き出せ.ただし,大文字,小文字は区別しない。」 という課題をいただいたので スペース ピリオード カンマ は避けては通れないみたいです。
先生からいただいたread-b.txtをひらいてみると英語がたくさん書いてありました
Re:コマンドラインについて
Posted: 2006年12月15日(金) 22:15
by box
実行の仕方は、作成するプログラム名をprog.exeとすると、
prog read-b.txt write-b.txt <Enter>
となるようですね。
コマンドラインについてこれまで勉強してきた内容に基づいて、
上記の場合における
・コマンドライン引数の数
・各引数の内容
を求めてください。
Re:コマンドラインについて
Posted: 2006年12月16日(土) 00:26
by 管理人
>スペース ピリオード カンマ は避けては通れないみたいです
結局何をするのでしょうか・・・。
ファイルの内容をそのままコピーするわけじゃないんですか?大文字小文字は区別しないとなると・・。
どういういみだろう;
Re:コマンドラインについて
Posted: 2006年12月16日(土) 00:45
by box
1)コマンドライン引数から入出力ファイル名を得る。
2)入出力ファイルをオープンする。
3)英字の数、ピリオドの数、カンマの数およびスペースの数をゼロで初期化する。
4)入力ファイルから1文字ずつを読んでいる間、以下の処理を行なう。
4-1)その1文字が英字(大文字、小文字)ならば、英字の数を1増やす。
4-2)その1文字がピリオドならば、ピリオドの数を1増やす。
4-3)その1文字がカンマならば、カンマの数を1増やす。
4-4)その1文字がスペースならば、スペースの数を1増やす。
5)英字の数、ピリオドの数、カンマの数およびスペースの数を出力ファイルに書き出す。
6)入出力ファイルをクローズする。
7)おしまい。
Re:コマンドラインについて
Posted: 2006年12月16日(土) 14:17
by 努力中
不鮮明な質問でみなさんに迷惑をかけてしまい本当にすいません。 今朝学校にいきプログラミング担当の先生にお聞きしてみたら boxさんの考え方で正解みたいでした。 「read-b.txtから情報を読み込んで最終的に英字の数、ピリオドの数、カンマの数およびスペースの数をwrite-b.txtファイルに書き出すんだよ」とおっしゃっていました。
Re:コマンドラインについて
Posted: 2006年12月16日(土) 21:18
by 管理人
あ、ごめんなさい!
>・・・ファイル内にあるa~z,ピリオド,カンマ,スペースのそれぞれの文字「数」をwrite-b.txtに書き出せ・・・
の 数 を読み飛ばしていました。
すみません、ちゃんと意味が通りますねm(_ _)m
文字コードについてのサンプルがご覧になりましたか?
文字コードはa,b,cから順番にzまで並んでおり、A,B,Cから順番にzまで並んでいます。
つまり、取得した1文字が小文字だと判断するには取得した1文字をcだとすると
if( c >= 'a' && c <= 'z' )
このように判定できます。
if( c >= 'A' && c <= 'Z' )
大文字の判定ならこうですね。この条件文で、文字数をカウントしていけばいいんだと思いますよ。
if( c >= 'A' && c <= 'Z' )
count_a++;
こんな感じですね。
boxさんのおっしゃるように書いてみてください。
Re:コマンドラインについて
Posted: 2006年12月16日(土) 21:52
by 努力中
#include <stdio.h>
int main() {
char x='1';
printf("%c %d\n", 'a' , 'a' );
printf("%c %d\n", 'a'+1, 'a'+1);
printf("%c %d\n", 'a'+2, 'a'+2);
printf("%c %d\n", x , x );
printf("%c %d\n", x+1 , x+1);
printf("%c %d\n", x+2 , x+2);
return 0;
}
管理人さんに書いていただいたこの文字コードに小文字判定大文字判定を足していくかんじでしょうか
Re:コマンドラインについて
Posted: 2006年12月16日(土) 22:08
by box
> 管理人さんに書いていただいたこの文字コードに小文字判定大文字判定を足していくかんじでしょうか
その前に、コマンドライン引数を正しく受け取ることから始めましょう。
一連の投稿を、最初から読み返してみてください。
Re:コマンドラインについて
Posted: 2006年12月16日(土) 23:11
by 管理人
私の書いた投稿の文章をよく読んでいただければ、そのような疑問はお持ちにならないと思います。
そのコードは文字コードを確認するだけのためのもので、全く、今作ろうとしているコードとは関係ないです。
コードはアルファベット順に並んでいることを確認していただきたかったのです。
もう一度きちんと上から読んでみてください。
Re:コマンドラインについて
Posted: 2006年12月16日(土) 23:33
by 努力中
すみませんでしたもう一度よみかえしてみます
Re:コマンドラインについて
Posted: 2006年12月17日(日) 17:50
by 努力中
よみかえしてみましたが、書くことはできませんでした。なにも知識のない1年生が2年生の学期末最終課題に興味本位で手を出したのが間違いでした。 アドバイスをくださったみなさん本当にすいませんでした
Re:コマンドラインについて
Posted: 2006年12月18日(月) 02:38
by 管理人
努力中さん、こんにちは。
なかなかお返事が出来ず、申し訳ないです。
こちらとしては、努力中さんが、どの程度C言語を理解されてらっしゃるのかがわからないので、どれくらい説明をすればいいのかわからないのです。
とりあえず、上の説明でわからないのでしたら「ここがわからない」といってもらえたら、わからない箇所の説明をしますし、似たような実装をしてくれといわれたらサンプルをお書きします。
とりあえず、どの辺を説明すればいいかわからなかったので、一通り全部説明したつもりです。
そこでわからないとなると、そのわからない箇所を教えてもらわないと説明のしようがないので。
1
2
3
4
という風に説明したので、ご自分でつなげて1234にしていただけたら完成するんですけど、わかりませんか?
一つ躓きだすと、全て躓いてしまう事ってよくあるんで、始めに答えを見てから自分で理解していくほうがいいかもしれませんね。
本当は、人の書いたプログラムというのは理解が難しいので、完成したプログラムを先にお見せすることはしたくなかったのですが。
プログラムのソースは少々長いですが、全く難しいことはしていません。
上記どおりのことをしているだけで、つなぎあわせただけです。
では、実際に作ってみましたので、見てください。
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[/url]){
FILE *fin, *fout;
char c;
int st_A=0,st_a=0,st_space=0,st_else=0;
if(argc!=3){
printf("引数の数が正常ではない\n");
exit(1);
}
if((fin = fopen(argv[1], "r")) == NULL ) {
printf("入力ファイルオープンエラー\n");
exit(1);
}
if((fout = fopen(argv[2], "w")) == NULL ) {
printf("出力ファイルオープンエラー\n");
exit(1);
}
while ( (c=fgetc(fin)) != EOF){
if(c==' ')
st_space++;
else if(c>='a' && c<='z')
st_a++;
else if(c>='A' && c<='Z')
st_A++;
else
st_else++;
}
fprintf(fout, "スペース%d字\n小文字%d字\n大文字%d字\nその他%d字\n", st_space, st_a, st_A, st_else);
fclose(fin);
fclose(fout);
return 0;
}
実際に実行していないので、もしかしたらバグがあるかもしれませんが、見た感じ大丈夫だと思います。
次の投稿で注釈します。
Re:コマンドラインについて
Posted: 2006年12月18日(月) 02:45
by 管理人
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[/url]){
//argcの使い方がわからなければ上の投稿を読み返してください。
//とりあえず、argv[1]に指定したファイル名1が、argv[3]に指定したファイル名3が入ります。
FILE *fin, *fout;
//ファイル情報を格納するためのファイルポインタ
char c;
//ファイルから1文字取得し格納するための変数
int st_A=0, st_a=0, st_space=0, st_else=0;//文字をカウントするための変数です。
// ↑大文字用 ↑小文字用 ↑スペース用 ↑その他用
if(argc!=3){//ファイル名が2つ記述されていなければ
printf("引数の数が正常ではない\n");
exit(1);
}
if((fin = fopen(argv[1], "r")) == NULL ) {//1つ目のファイルオープン処理
printf("入力ファイルオープンエラー\n");
exit(1);//ひらけなかったら終了
}
if((fout = fopen(argv[2], "w")) == NULL ) {//2つ目のファイルオープン処理
printf("出力ファイルオープンエラー\n");
exit(1);//ひらけなかったら終了
}
while ( (c=fgetc(fin)) != EOF){//ファイルから1文字取得。取得し終わったらポインタは1つ次に進む。
if(c==' ')//取得した文字がスペースだったら
st_space++;//スペースをカウントする。
else if(c>='a' && c<='z')//取得した文字が小文字だったら
st_a++;//小文字をカウントする。
else if(c>='A' && c<='Z')//取得した文字が大文字だったら
st_A++;//大文字をカウントする。
else//その他なら
st_else++;//その他をカウントする。
}
fprintf(fout, "スペース%d字\n小文字%d字\n大文字%d字\nその他%d字\n", st_space, st_a, st_A, st_else);
//変数のデータをファイルfoutに書き出す。
fclose(fin);//ファイルを閉じる
fclose(fout);//ファイルを閉じる
return 0;
}
わからない関数があればgoogleなどで直接検索すればだいたい解決します。
何かわからない部分があれば聞いてください。基本的に上の投稿を読み返したらわかるはずです。