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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

Q&A

解決済

4回答

3936閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2016/04/23 22:12

編集2016/04/24 02:12

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

1for文の初期値が ;で、何の意味か良く分かりません。 2条件*pと、インクリメントP++ はわかります。 3実行文 ;はなにもしないということでしょうか? 4for文を抜けてp--はポインタをpが偽になった位置に 5に戻しているでいいでしょうか? 6 7そのあとのwhile 文は改行があれば0を代入して 8文字列の最後の文字(改行の前の文字)のポインタを指すようにするでいいでしょうか? 9よろしくおねがいします。 10 11void chop(char *p) { 12 for (; *p; p++) 13 ; 14 15 p--; 16 while (*p == '\r' || *p == '\n') 17 *(p--) = 0; 18}

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

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

C

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

のおよその意味が、

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

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

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

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

極端な例では

C

1for (;;)

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

投稿2016/04/24 02:21

chun

総合スコア324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/04/24 02:50

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

0

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

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

x.c

c

1#include <stdio.h> 2#include <string.h> 3 4void chop(char *p) { 5 for (; *p; p++) 6 ; 7 p--; 8 9 while (*p == '\r' || *p == '\n') 10 *(p--) = 0; 11} 12 13void chop2(char *p) { 14 for (char * t = p + strlen(p) - 1; p <= t; t--) { 15 if (*t == '\r' || *t == '\n') { 16 *t = 0; 17 } else { 18 return; 19 } 20 } 21} 22 23//void chop2(char *p) { 24// int len = strlen(p); 25// for (int i = 0; i < len; i++) { 26// if (p[i] == '\r' || p[i] == '\n') { 27// p[i] = 0; 28// } 29// } 30//} 31 32void dump(char * p, int len) { 33 for (int i = 0; i < len; i++) { 34 printf(" %02X", *p & 0xff); 35 p++; 36 } 37 printf("\n"); 38} 39 40int main(int atgc, char** argv) { 41 char str[10]; 42 43 printf("--- chop1\n"); 44 strcpy(str, "0\n\n"); 45 printf("[%s]\n", str); 46 chop(&str[3]); 47 printf("[%s]\n", str); 48 dump(str, sizeof(str)); 49 50 printf("--- chop2\n"); 51 strcpy(str, "0\n\n"); 52 printf("[%s]\n", str); 53 chop2(&str[3]); 54 printf("[%s]\n", str); 55 dump(str, sizeof(str)); 56 57 printf("\n"); 58 59 strcpy(str, "1\n2\n"); 60 chop(str); 61 printf("chop\n[%s]\n", str); 62 strcpy(str, "1\n2\n"); 63 chop2(str); 64 printf("chop2\n[%s]\n", str); 65 return 0; 66}

実行例

$ 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 00:33

編集2016/04/24 08:13
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eripong

2016/04/24 01:07

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

退会済みユーザー

2016/04/24 01:19

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

2016/04/24 01:54

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

2016/04/24 04:42

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

2016/04/24 08:14

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

0

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

投稿2016/04/24 00:18

編集2016/04/24 00:31
daive

総合スコア2028

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

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

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

投稿2016/04/23 22:18

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/04/23 22:29

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

退会済みユーザー

2016/04/23 22:37

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

2016/04/23 23:10

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問