プロが教える店舗&オフィスのセキュリティ対策術

初めて質問します。最近、C言語の勉強をし始めた者ですが、今回「20字以上の行を全て印字せよ。」という演習プログラムを書いています。

専門書の方では文字配列の単元の演習問題なのですが、例題を参考にして以下にここまでは自力で書きました。しかしこのソースコードに対して実行したところ、どうやら「20字以上ある行の、次の行」が印字されているようで、全く原因がわかりません。

putcharの使用が必須だったのですが、試しに関数putlineを消して
printf("%s",line);
で出力してみるとうまくいきました。どうやら関数putlineに問題があると思っているのですが(ここは完全に自力だったため^^;)、ご指摘、アドバイス頂けると光栄です。
よろしくお願いしますm(_ _)m


#include<stdio.h>
#define MAXLINE 1000


int getline (char s[], int lim)
{
int c,i;

for (i=0; i<lim-1 && (c=getchar()) !=EOF && c!='\n'; i++){
s[i]=c;
}

if (c= ='\n'){
s[i]=c;
i++;
}

s[i]='\0';
return i;
}


int putline (char t[])
{
int c,i;

for (i=0; (c=getchar()) !=EOF && c!='\n'; i++){
t[i]=c;
putchar(t[i]);
}

if (c= ='\n'){
t[i]=c;
putchar(t[i]);
}

return 0;
}


main()
{
int len;

char line[MAXLINE];

while( (len=getline(line,MAXLINE) )>0 ){
if (len>20){
putline(line);
}
}
}

A 回答 (8件)

・コメント文がない


演習問題といえども、日頃からコメントを付加する習慣を
つけたほうがいいですよ。
人の書いたプログラムなんて初見では意味不明です。
・インデントがない
プログラムが非常に見づらく感じます。

あと、問題の原因は
putline関数の中でline配列に新たに文字列を入力している為です。
確認ですけど、getline関数が文字列を入力し、
putline関数が文字列を出力する関数ですよね?
ならputline関数の中でgetcharしなくてもいいはずです。
    • good
    • 0

特に無いと思います。


頑張ってください
    • good
    • 0
この回答へのお礼

わかりました。ありがとうございます^^

Cを学び始めてから日が浅いですが、自力で考えることを忘れずに精進します。

お礼日時:2007/11/26 03:33

> 配列tから一文字ずつ取り出す



配列tのn番目の要素を取り出すときは
t[n]
と書きます。
    • good
    • 0
この回答へのお礼

度々のアドバイスありがとうございます。
関数、配列についてまだ理解できていない点が多々あるので、よく学んで行きたいと思います。

お礼日時:2007/11/26 03:37

老婆心ながら一つ忠告しておきますが


「なんとなく」や「イメージ」ではプログラムは作れません。
ちゃんと関数の機能やアルゴリズム、仕様を理解して作ってください。
たとえ”まぐれ”で上手くいったとしても、
中身の分からないプログラムは無価値です。

とりあえず、どこがどのように分からないのか
示していただかないと、答えようがありません。
もうちょっと情報ください。

参考URL:http://www.bohyoh.com/CandCPP/C/Library/hindex.h …

この回答への補足

確実に理解していくように努めます。
関数getlineとmainの部分は理解できています。分からない部分は関数putlineのなかで、「配列tから一文字ずつ取り出す。」という部分でした。これまでの演習で、getcharとputcharは関数内で同時に使われる、つまり
 int c;
c = getchar();
while (c != EOF) {
putchar( c );
c = getchar();
}
という感じでputcharの前には必ずgetcharがなくてはならないのだと勘違いをしていました。

みなさんからの指摘を受けこのように書き換えてみました。
int putline (char t[ ]) /*関数の宣言*/
{
int n;

for (n=0; t[n] != '\0'; n++){ /*'\0'まで配列tを一文字ずつとりだす*/
putchar( t[n] ); /*配列tの出力*/
}

return 0;
}

結果うまくいったようです。シンプルにまとめることができたと思うのですが、もっと明確にすべきところはありますでしょうか?

補足日時:2007/11/25 11:30
    • good
    • 0

#2です。


インデント消えるんですか!知らなかったスイマセン

>putline内にgetcharは必要ないとのことでしたが、どのように
>putcharを用いたらよろしいんでしょうか? 初心者で本当にお手数
>おかけします^^;;;
そちらのプログラムの正確な仕様が分からないので
関数名から推測して暫定的にお答えします。
putline関数の中ではputcharは必要ありません。
>「20字以上ある行の、次の行」が印字されている
この場合印字されている文字列を獲得しているのはgetline関数でなく
putline関数だと思われます。
おそらく目指しているのは
(1)getlineで文字列取得
(2)20文字以内ならputlineで表示
という仕様だと思います。
しかし、getcharをputline内においた場合
せっかくgetline関数で取得した文字列を
それが20文字以上だった場合、putline関数で再度取り直しています。
その結果、問題が生じています。

この回答への補足

問題が起きてる部分は何となくですが、その原因が理解できました。

>おそらく目指しているのは
>(1)getlineで文字列取得
>(2)20文字以内ならputlineで表示

はい、その通りです。配列tから一文字ずつ取り出す、というイメージもわかるのですが、取り出す=「getchar」しか浮びませんでした。
違いますよね^^; もう少しご教授頂けますか?

補足日時:2007/11/25 01:39
    • good
    • 0

putline()で、出力すべきデータは配列tに入っています。


tから1文字ずつ取り出し、putchar()してください。
1文字ずつ取り出すのが終わるのは、'\0'が見つかったときです。
    • good
    • 0

> ・インデントがない


> プログラムが非常に見づらく感じます。

仮に、元のソースがタブやスペースできちんとインデントしていたとしても、
アップロードした時点できれいさっぱり消えてしまいます。残念なことですけれど。

例えば全角スペースを使えば、アップロード結果はインデントしているように見えますが、
そうするとそのままコピー&ペーストしたのではコンパイルできない、
という痛しかゆしの状態です。
    • good
    • 0
この回答へのお礼

asuncionさんの仰る通りです^^; コピーペーストの結果、かなり見にくくなってしまったのに気付かなくて…すいませんでした。

初めての投稿だったもので、コメント文がないなど、気が付かなくてこれもまたすいませんでした。これから気をつけたいと思ってます。

putline内にgetcharは必要ないとのことでしたが、どのようにputcharを用いたらよろしいんでしょうか? 初心者で本当にお手数おかけします^^;;;

お礼日時:2007/11/25 00:39

putline関数の機能(役割分担)は何でしょうか?



getline関数で入力を受け持っている上に、
さらにputline関数で入力を行なう必要はあるのでしょうか?

putline関数は、引数で受け取った内容を出力する、
という機能に特化すべきではないでしょうか。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!