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

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

ただいまの
回答率

90.48%

  • C

    3836questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

for()文の意味がわからないので教えてください

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,086

sanchu52

score 140

for文の初期値が ;で、何の意味か良く分かりません。
条件*pと、インクリメントP++ はわかります。
実行文  ;はなにもしないということでしょうか?
for文を抜けてp--はポインタをpが偽になった位置に
に戻しているでいいでしょうか?

そのあとのwhile 文は改行があれば0を代入して
文字列の最後の文字(改行の前の文字)のポインタを指すようにするでいいでしょうか?
よろしくおねがいします。

void chop(char *p) {
  for (; *p; p++)
    ;

  p--;
  while (*p == '\r' || *p == '\n')
    *(p--) = 0;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

+3

iを1から100までカウントするためのfor文

for ( i = 1; i <= 100; i++ )


のおよその意味が、

for (値の初期化; ループ継続条件; 値のカウント)


である事はご存知かと思いますが、
実態は、

for (ループ前に実行される式; ループ継続条件; 継続判定前に実行される式)


でしかありません。
なので、ループ開始前に値の初期化が必要なければ省略できますし、
他の式も必要なければすべて省略できます。

極端な例では

for (;;)


とすることで、無限ループを作ることもできます。
Cではwhile(1)と書くのが普通ですが。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/24 11:50

    ありがとうございます
    関数chop()が呼ばれた時点のpのあたいが初期化に使われるんですね。
    これは住所録にある関数で一番最初に出てきて、引っかかって前に進めないでいました。
    これから全体を読まなければいけません、助かりました。

    キャンセル

checkベストアンサー

0

*pが0になるまでpを進める、つまり文字列としてのpの最後までポインタを進める、という意味です。

もっとも、標準関数のstrlenを使って、p += strlen(p);と書いたほうが読みやすい気もします。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/24 07:29

    さっそく回答いただき、ありがとうございます。
    すみませんがfor文の中の説明とその後の ;、その後の p--でポインタをデクリメントしていますがfor
    文との関係はどうなるのでしょうか?

    キャンセル

  • 2016/04/24 07:37

    すみません分かりにくいコメントで質問の内容が判りにくいと思います
    全文を詳しく説明していただけませんか。おねがいします。

    キャンセル

  • 2016/04/24 08:10

    横から失礼します。
    C 言語の文字列が 0x00 で終わっている char 型の配列、ということを押さえた上で、ひとつの char 型領域をひとつのマス目に対応させて、たとえば "test" という文字列が格納されたメモリの状態を図に描いてみて、上記コードがどのように動くかを紙の上で確かめてみることをおすすめします。
    for (A; B; C) D
    は、模式的に書くと
    A; whlie (B) { D; C; }
    だと思ってどういう動きになるか、紙の上で手を動かしてみるといいのではにないでしょうか。

    キャンセル

0

OS、Cコンパイラの、種類、名称、エディションが書かれていませんが、
掲示の質問の大部分は、
1.ソースコードデバッガを使って、ステップ実行しつつ
  変数の内容を確認する。コンパイル時に、オプティマイザは切っておく。
2.もうちょっと興味があるのであれば、機械語対応のデバッガを使って、
  機械語レベルで、1ステップづつトレースしてみる
  コンパイル時に、オプティマイザは切っておく。
 ⇒構造体、ポインタ、キャスト、変数定義への疑問が、アセンブラを齧っている程度でも
  理解に繋がる方法の、一つです。
  言語によっては、ライブラリコールの塊の事があるので、全てに適用できるわけでは有りません。
3.エディタ、コンパイラが使えるだけでも、プログラムは組めるけれど
  効率の良いデバッグを行うには、デバッガが使えないと、話になりません。
  デバッガが使えるだけでも、効率は上がりますが、
  更に、デバッグをどう行ったら良いか、を考えながらコードを書く事も必要です。
  ⇒コードを書く前に、テスト手順を考えておく事も大切です。
  デバッグコードを入れるは、どうしようもない場合の手段。
   見難く、醜いコードになるので、可能であれば避けます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

for の意味は既に他の回答にある通りです。
質問文にあるコードの問題点について述べます。

問題点: chop() は、与えられた 文字列の領域外のデータを書き変えてしまう恐れがある。
↓のコードと実行結果を参照してください。

x.c

#include <stdio.h>
#include <string.h>

void chop(char *p) {
  for (; *p; p++)
    ;
  p--;

  while (*p == '\r' || *p == '\n')
    *(p--) = 0;
}

void chop2(char *p) {
  for (char * t = p + strlen(p) - 1; p <= t; t--) {
    if (*t == '\r' || *t == '\n') {
      *t = 0;
    } else {
      return;
    }
  }
}

//void chop2(char *p) {
//  int len = strlen(p);
//  for (int i = 0; i < len; i++) {
//    if (p[i] == '\r' || p[i] == '\n') {
//      p[i] = 0;
//    }
//  }
//}

void dump(char * p, int len) {
  for (int i = 0; i < len; i++) {
    printf(" %02X", *p & 0xff);
    p++;
  }
  printf("\n");
}

int main(int atgc, char** argv) {
  char str[10];

  printf("--- chop1\n");
  strcpy(str, "0\n\n");
  printf("[%s]\n", str);
  chop(&str[3]);
  printf("[%s]\n", str);
  dump(str, sizeof(str));

  printf("--- chop2\n");
  strcpy(str, "0\n\n");
  printf("[%s]\n", str);
  chop2(&str[3]);
  printf("[%s]\n", str);
  dump(str, sizeof(str));

  printf("\n");

  strcpy(str, "1\n2\n");
  chop(str);
  printf("chop\n[%s]\n", str);
  strcpy(str, "1\n2\n");
  chop2(str);
  printf("chop2\n[%s]\n", str);
  return 0;
}


実行例

$ gcc x.c

$ ./a.out
--- chop1
[0

]
[0]
 30 00 00 00 B5 57 FF 7F 00 00
--- chop2
[0

]
[0

]
 30 0A 0A 00 B5 57 FF 7F 00 00

chop
[1
2]
chop2
[1
2]

chop には &str[3] を渡しているので、str[0], str[1], str[2] の内容が書き換わってはいけないです。
chop  を呼んだ後は 30 00 00 ... となってます。
chop2 を呼んだ後は 30 0A 0A ... となってます。
str[1], str[2] は 0A, 0A のままであるべきです。

chap(p) では、 0 をさがした後、 p-- しています。
これが p の領域の外になってしまうことがあるわけです。
そしてそこから p-- しながら \n, \r を探して 0 への置き換えをしているので...
chap2(p) では、 p の領域外へのアクセスが発生しないようにしています。

変更: 2016-04-24 17:10
変更前は, 文字列の途中に改行がふくまれている場合、 chop2() の挙動が chop() と異なっていました。
chop2()の挙動が chop() と同じになるようにしました。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/24 10:07

    元のchopが領域外の値を書き換えてしまうという指摘はその通りと思いますが、chopは文字列の最後の改行までにするのに対し、chop2だと文字列を最初の改行までにするので、振る舞いが変わってませんか?

    キャンセル

  • 2016/04/24 10:19

    回答ありがとうございます。for (; *p; p++) で初期値が  ;
    というのはどういうことですか?、その後の文 ;は何もしないということでしょうか?
    for文を抜けた後のp--は*p==0の位置ということでしょうか?

    キャンセル

  • 2016/04/24 10:54

    横から失礼します。
    初期値が;というのは何もしない、つまりその前に設定された値のままということです。この場合は引数で渡されたポインタpのままになります。
    その後の;は何もしないということであってます。
    このfor文はポインタpを進めていってポインタが指す値が0だったら抜けるという処理です。
    *p==0のときfor文を抜けますので、その時pは0の位置を指しています。次のp--で1つ前の位置に移動させています。

    キャンセル

  • 2016/04/24 13:42

    chop2 の振る舞いが chop とは異なるのは認識してます。
    同じにするにはもう少しコードをかかないといけなさそうだったのでサボりました。
    指摘したかったのは、 for を抜けた後の p--と *p への代入が問題ということだったので、chop2 はなるべく簡単なコードにしたかったのです。

    キャンセル

  • 2016/04/24 17:14

    chop2() を変更したものを回答に書きました。
    (変更前のものはコメントで残しています)

    キャンセル

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

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

関連した質問

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

  • C

    3836questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。