文字を入力してそれを反転させる関数を作るという練習問題があって
出力だけならデクリメントで簡単にできたんですが配列の中身を反転させるのがわからなくて答えを見たんですが見てもよくわかりませんでした
この関数を詳しく解説してほしいです
c
1void rev(char *str) 2{ 3 char c, *p; 4 5 p = str + strlen(str) - 1; 6 7 while (str < p) { 8 c = *str; 9 *str++ = *p; 10 *p-- = c; 11 } 12 return; 13}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
質問への回答ではありませんが、stackoverflow のサイトにこんな QA がありました。
- Reversing a string in C http://stackoverflow.com/questions/784417
英語ですが、コードの部分だけを読めばよいです。
いろいろな方法が可能なことがわかるとおもいます。
これらのコードの意味も考えてみるとよいと思います。
配列、ポインターとその使い方について、より理解が深まるはずです。
投稿2015/10/17 23:02
総合スコア22324
0
C言語の文字列は一文字ずつ格納された配列である。
C言語の配列はイメージ的に正直に連続してメモリ上に存在している
ポインタはメモリ上のアドレスを格納する
「*str」はアドレス先に格納された値を参照し「str」はアドレス値そのものを参照する
格納されているものがアドレスなのに「int *str」や「char *str」のように宣言時に型を指定するのは、宣言した型に合わせた色々な処理に対応するため。
例えば「char *str」でstr+1とするだけで、一文字後ろのアドレスになる。
※intとcharではメモリ上に占める大きさが違うので、型指定が無いとstr+1のような書き方はできず、それぞれの大きさをプログラマが把握してstr+32bitのように記述するはめになる。
以上を前提にコードを見ていきます。
c
1p = str + strlen(str) - 1;
pには最後の文字のアドレスが格納される。
str: 文字列の先頭アドレス「abc」ならaの位置が格納されている
strlen(str): 文字列の長さ。「abc」なら3
※「abc」なら、aの位置から -> 3文字分後ろへ -> 1文字分前へで、「c」の位置
c
1while (str < p)
文字列を反転させる関数なので、
pを文字列最後尾から一文字ずつ先頭へ移動
strを文字列先頭から一文字ずつ最後尾へ移動させて
pとstrが交わるかすれ違うまでループします。
c
1c = *str; 2*str++ = *p; 3*p-- = c;
初回ループでは次のようになります。
1行目 cに先頭文字をバックアップ 「ABCDE」なら「A」
2行目 先頭文字を最後尾文字で上書きした後、strを1文字分進める
3行目 最後尾文字をバックアップしておいた先頭文字で上書きし、pを1文字分戻す
※「ABCDE」ならループ1回目で「EBCDA」になる
これがpとstrが交差するまで繰り返し実行されると、文字列が反転するはずです。
c
1*str++ = *p;
これは次の2行をまとめて書いたものです。参考
*str = *p;
str++;
投稿2015/10/17 17:24
編集2015/10/17 17:34総合スコア2068
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
この関数は簡単に言いますと, 手で 「外側から内側へ, 前と後ろの文字を入れ替えて行くような作業」を行っています.
まず, 変数に関して言えば.
char cは文字をコピーして一時退避しておくもの.
*pは 入れ替えてstrの最終文字(最初"Hello"で言えば, "o"にあたるポインタの格納.)のポインタ
4行目で, pにはstrの最終文字が入り, 初期化されます.
つぎにwhileループの中に入ります.
インクリメント, デクリメントを考えないでいくと,
最初, 文字の一番目をcに 退避, ("H"がcへ格納)
つぎに, その退避したところに最終文字を入れる ("o"が"H"の位置へ格納)
最後に, 退避した文字を最終文字部分に格納. ("H"を"o"位置へ)
すると,"oellH"となることがわかると思います.
これをwhileループで変更した部分まで(strがpより大きくなったら評価済み)繰り返します.
インクリメント等については飛ばしましたが, 交換するときの作業には関わってはいません.
ループしたとき次のポインタ(変更した文字より内側)へ移したいから使われています.
一応試した, Cコードも記載しておきます.
C
1#include <stdio.h> 2#include <string.h> 3 4void rev(char *str) 5{ 6 char c, *p; 7 8 p = str + strlen(str) - 1; 9 printf("p :%c\n", *p); 10 11 while (str < p) { 12 c = *str; 13 printf("c: %c\n", c); 14 *str = *p; 15 *str++; 16 17 *p = c; 18 *p--; 19 printf("%s\n", str); 20 } 21 return; 22} 23 24int main(void){ 25 26 char str[] = "Hello"; 27 printf("before :%s\n", str); 28 29 rev(str); 30 31 printf("after : %s\n", str); 32 return 0; 33} 34
投稿2015/10/17 17:17
総合スコア15
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。