逆順に並び替える
Posted: 2011年1月24日(月) 02:10
文字列を入力させて関数を用いて(関数内では配列を使用できない)それを逆の順序に並び替えるというプログラムをつくっているのですが、
逆順にうまく並び替えることができません。
どのようにしたらよろしいのですか?
逆順にうまく並び替えることができません。
どのようにしたらよろしいのですか?
ちょっと違いますね。bitter_fox さんが書きました:また、bは"\0"という文字列リテラルの先頭アドレスを指していて、そこに値を代入することは不正です。
void reverse
( char *a, /* 逆順にする文字列へのポインタ */
int n /* 文字列長 */
)
{
char *p1 = a; /* 交換位置(前側) */
char *p2 = a + n - 1; /* 交換位置(後側) */
for (; p1 < p2; ++p1, --p2) /* 交換位置が反転するまで */
{ /* 前と後ろを交換(swap)する */
char c = *p1; /* 前側を一旦退避 */
*p1 = *p2; /* 後ろを前に代入 */
*p2 = c; /* 退避しておいた前側の値を後ろに代入 */
}
}
while (p1 < p2) /* 交換位置が反転するまで */
{ /* 前と後ろを交換(swap)する */
char c = *p1; /* 前側を一旦退避 */
*p1++ = *p2; /* 後ろを前に代入 */
*p2-- = c; /* 退避しておいた前側の値を後ろに代入 */
}
質問者さんのコードでは、maru さんが書きました:ちょっと違いますね。bitter_fox さんが書きました:また、bは"\0"という文字列リテラルの先頭アドレスを指していて、そこに値を代入することは不正です。
b はどこも指していません。ポインタの値がNULLであるのと"\0"という文字列リテラルの先頭アドレスを指すことは異なります。
"\0"という文字列リテラルを参照する(読み出しを行う)ことは可能ですが、NULLポインタは参照することさえ不正です。
そこに値を代入することが正しくないということは同じですけどね。
はい。間違っています。bitter_fox さんが書きました: になるので、「bは"\0"という文字列リテラルの先頭アドレスを指す」としたのですが、間違ってますでしょうか・・・?
なるほど、集成体の時にだけ{}は意味を持つのですか・・・
ポインタと配列とに、そんな初期化の違いがあるとは知りませんでした、ご指摘ありがとうございます。
ポイントと言っても、このコードは特にポイントとなるような部分も無いかと思いますが初心者向けに解説してみます。beginner さんが書きました:>>maruさん
分かりやすいコードで説明していただきありがとうございます。
コードを書くにあたってポイントとなる部分はどこでしょうか?
a a a a a
[0][1][2]....[n-2][n-1]
↑ ↑
+------------------+
a a a a a
[0][1][2]....[n-2][n-1]
↑ ↑
+----------+
...(以下省略)
ポインタ(pointer)はそのまま「(何かを)指し示す」変数です。ポインタを扱う場合、その先の実体をイメージしておく必要があります。beginner さんが書きました:>>bitter_foxさん
ポインタの使い方がよくわからないのでお手数ですが説明の方をお願いします。
なんですけど、それが理解できないとするとちょっと難しいかも?って感じです。
ポインタ(領域サイズは固定)を初期化するのと、配列(領域サイズは宣言ごとに異なる)を初期化するのでは違いがあって当然です。bitter_fox さんが書きました: ポインタと配列とに、そんな初期化の違いがあるとは知りませんでした、ご指摘ありがとうございます。
*p = 'A'; /* 定数文字列リテラルへの書き込みなので実行時エラー */
p[0] = 'B'; /* ポインタを配列として書き込み、上を同じく実行時エラー */
*str = 'C'; /* 文字配列名をポインタとして書き込み。OK */
str[0] = 'D'; /* 文字配列を普通に書き込み。OK */
ですね。この場合、 とすれば、文字型変数へのポインタ配列なので、{"str", "ing"}を二つの文字列を持つ配列として処理することができます。
#include<stdio.h>
#include<string.h>
void reverse(char *,int );
int main(void) {
char a[100];
int n;
printf("文字列を入力してください\n");
scanf("%s",a);
n=strlen(a);
printf("逆順に並び替えます\n");
reverse(a,n);
printf("%s\n",a);
}
void reverse(char *a,int n)
{
int i;
char *b = (char*)malloc((n+1) * sizeof(char)); // 末尾のヌル文字も考えて+1
if (b == NULL) // メモリエラーチェック
{
printf("Error\n");
return;
}
strcpy(b, a); // aをbにコピー
for(i=0;i<n;++i) // 0から文字列長まで
a[i] = b[n-i-1]; // iの所にn-i-1を代入
// n-i-1はiの対極に位置する
free(b); // bを解放
}
「配列を使わない」=「動的確保」と考えるのは少し短絡的かと。bitter_fox さんが書きました:流れからすると動的確保の問題なので動的確保を使ったものを作りました。また、beginnerさんが書かれたコードを元にしています。