質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.48%

K&R演習 解説おねがいします!

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,172

score 36

****プログラミング初心者です。
プログラミング言語C(K&R)の演習1-18の解答例を見たのですが、わからないです。
(http://www.c-program-example.com/2011/11/k-r-c-exercise-1-18.html)
関数 get_line と char_remove のしくみを教えて頂けるとありがたいです!

特に
関数 char_remove で配列の中の文字が
’\n’ ' ' '\t'
のときにどうして、i の値をを +1 にしたり、-1
するのかがよくわかりません。

プログラミング言語C(K&R) P38第一章 演習1-18
「各入力行から、行の後のタブやブランクを取り除き、かつ空白行はすべて削除するようなプログラムを書け。」

...c

#include <stdio.h>
#define MAXLINE        1000 /* 入力行の最大長*/

int get_lines(char line[], int maxline); /* 関数 get_lines の宣言 */
int char_remove(char str[]);             /* 関数 char_removeの宣言 */

main()
{
    char line[MAXLINE];/* current input line 
                        : 現在の入力行*/
    
    while((get_lines(line,MAXLINE)) > 0)
        if (char_remove(line) > 0)
            printf("%s",line);        
    return 0;
}
/* 
 remove: trailing blanks and tabs from character string str
文字列から ついていく? タブや空白
*/

int char_remove(char str[])
{
    int i = 0; /* i の初期値は 0*/   
    while (str[i] != '\n') /* 文字が '\n'以外なら*/
        ++i;/*i = i + 1*/
    
    --i; /* 文字が'\n'なら、i = i -1*/
    
    while (i >= 0 && (str[i] ==  ' '|| str[i] == '\t'))/*i が0以上 かつ 
                                                        文字が空白 あるいは タブなら*/
        --i;/* i = i -1*/
    if (i >= 0)/*i が0以上なら(文字は空白あるいはタブではない)*/
    {
        ++i;/*i = i + 1*/
        str[i] = '\n';/* str[i] に '\n' を代入*/
        ++i;
        str[i] = '\0';/* str[i]に'\0'を代入*/
    }
    return i;/*i の値を返す*/
}
/* getline: read a line into str, return length */
/*    str に行を入れて、長さを返す */
int get_lines(char str[], int line)
{
    int c,i,j;
    
    for (i = 0, j = 0; (c = getchar()) != EOF && c != '\n'; ++i)
    /*i ,jの初期値は0.とってきた文字がファイルの終わりではない かつ '\n'でなければ*/
    {
        if (i < line - 1) /*i が 999よりも小さければ */
        {
            str[j++] = c;/*str[j = j +1] に c を代入*/
        }
    }
    if (c == '\n') /*とってきた文字が '\n'なら*/
    {
        if (i <= line -1) /*iが998以下なら*/
        {
            str[j++] = c;
        }
        ++i;
    }
    str[j] = '\0';/*str[j]に'\0'を代入*/
    return i;/*iの値を返す */
}

コマンドプロンプトで
>a.exe < hello.c 
と実行すると

#include <stdio.h>
main()
{
    printf("hello,");
    printf("world");
    printf("\n");
}

でした。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+4

仕組みと言われても何をどう解説すれば良いのかわかりません、
まず、わかる行はコメントで自分で解説を入れていくとよいです、
※ int i = 0; の意味くらいはわかりますよね?
その結果、どこの行がわからないのかがわかるはずです。


投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/02/28 15:13

    よくわかりました!

    次のwhile文で「 i >= 0 」という条件があるのは
    最初に入力された文字が改行コードなら(空白行の場合)
    i = -1
    になっているから

    そして
    最後の文字が空白かタブなら、
    カウンタを-1する。

     ということですか?

    キャンセル

  • 2015/02/28 16:24

    >最後の文字が空白かタブなら、カウンタを-1する。

    その通りです、
    空白かタブ以外になるまでマイナス1するので、
    whileを抜けるときは空白かタブの1個までになっているはずです。
    空白が無い場合は改行コードの1個前です。

    最後の空白かタブは削除したいので、
    改行コード・空白・タブのいずれかの1個前の状態になっているはずのカウンタを
    1足すことによって、改行コード・空白・タブのいずれかを全て改行コードに置き換えます。

    キャンセル

  • 2015/03/01 05:31

    解説ありがとうございます!
    とてもわかりやすかったです。

    最後に、上の質問とは関係ないですが、プログラミングが上手くできるようになるには
    どうすればいいですか?

    キャンセル

+1

senbeさんの性格によります。

もしsenbeさんが私と同じでめんどくさがりで勉強が嫌いで、
でもプログラミングが好きなのであれば同じ方法が使えると思います。

1. 目標を決める
目標と言っても「~~ができるようになる」ではなく「~~を作りたい」と定めます、
「C言語が使えるようになる」が目標だと、何処までやればよいのかわからなくなります。

2. 最初は寄り道しない
「C言語だけやってて大丈夫だろうか、javaとかやらなくて良いのだろうか」となるかもしれません、
そんなことはC言語を使いこなせるようになってから考えれば良いです、
基礎ができれば他の言語は応用です。

3. 面倒くさがる
「もっと楽に作業ができないだろうか、むしろ作業しなくて済む方法は無いだろうか」
とか「残業なんて嫌だ早く帰りたい、会議なんて嫌いだ、すぐ終わればよいのに」
と言うようなことを常に考える、そして面倒くさくない方法を考える。

地道にやれば10時間かかる作業を、15時間かけてツールを作って10時間で終らせる。
最初はそんな感じでも良いのでずっと続けてるとそのうち技術が身についてきます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/03/02 18:27

    ありがとうございます。
    私は「技術者はプログラミングできないとだめだから…」
    と、はっきりした目標をもって勉強はしていませんでした。
    これからはⅭ言語を使って、めんどくさくないようにツールを作って
    いっぱい自分の遊べる時間をつくっていきたいです!

    キャンセル

0

senbeさん、そのプログラムは、そもそも
「各入力行から、行の後のタブやブランクを取り除き、かつ空白行はすべて削除する」
という動作をしていますか?それをきちんと確認されましたか?

「コマンドプロンプトで >a.exe < hello.c と実行すると…」とありますが、これだけではまともに動作しているのかどうかを(少なくともこちらでは)判断できません。
簡単に判別できるのは空白行が削除されたかどうかです。hello.c に空白行があって、その出力ならまだ望みはありますが、最初からhello.cに空白行が無いのではテストになりません。もっと言えば、hello.c の中に、行の後ろに空白やタブがある行があって
a.exe < hello.c > temp.txt
とした後、エディタで temp.txt を開き、行の後ろの空白やタブが削除されているかどうかを確認する必要があります。コマンドラインの結果を見せていただいただけでは、行の後ろの空白が無くなっているかどうかを判別できないのです。

何でこんな事を書いているかと言うと、私の手元(Cygwin、gcc)では空白行も行の最後の空白も削除されなかったからです(原因はすぐわかったので手元ではバグを取った)。「a.exe」でテストしたのなら私と似たような環境だと思われますので十分疑わしいのです。
ちゃんと動いているかどうかを確認していないのに、仕組みも何も無いのではありませんか?

しかも「解答例」として示されているURLを見て、またびっくり。なんとコンパイルさえ通らないプログラムじゃありませんか笑。つまり、senbeさんはコンパイルが通るように書き変えたのですね?立派立派w
ついでに、get_lines() は読み込んだ行の長さを返しているのだから、その値を利用するようにchar_remove()関数を修正すれば、中の処理を簡単にできる(その分無駄が無くなる)のに、とも思いました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る