文字列をswapするプログラムを作りたいと思っています。
やってみると、最初の一文字しかswapされません。
どうしてこれではいけないのでしょうか?
よろしくお願いします。
以下が作ったプログラムです。
#include<stdio.h>
void swap(char *a,char *b);
int main()
{
char a[2][5]={"abc","efg"};
printf("befor a[0]:%s a[1]:%s?n",a[0],a[1]);
swap(&a[0],&a[1]);
printf("after a[0]:%s a[1]:%s?n",a[0],a[1]);
}
void swap(char *a,char *b)
{
char *tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
実行結果は
befor a[0]:abc a[1]:efg
after a[0]:ebc a[1]:afg
となります。
befor a[0]:abc a[1]:efg
after a[0]:efg a[1]:abc
となって欲しいです。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
配列の概念やポインタの概念の理解がまだ十分ではなさそうですね^^
brilliantmole さんが、例としてあげている場合のように、
両者のポインタが指す領域が十分確保されている(a には (strlen(b)+1)バイト以上、b には (strlen(a)+1)バイト以上の領域を確保されている)と仮定すれば、
void swap(char *p, char *q)
{
char *r;
while (*p && *q) { char c = *p; *p++ = *q; *q++ = c; }
if (!*p && !*q) return;
if (*p) { r = p; while (*q++ = *p++) /* empty */; }
else { r = q; while (*p++ = *q++) /* empty */; }
*r = '\0';
}
とすればいいですが、こういうことをすると、領域の確保をうっかりしたりして、バグになりがちなので、文字列のswapはしないのにこしたことはないと思いますよ。
No.4
- 回答日時:
★追記。
模範解答。// 文字列の入れ替え関数
void swap( char *a, char *b )
{
char tmp;
// 文字列の入れ替え
while ( (*a != '\0') && (*b != '\0') ){
tmp = *a;
*a = *b;
*b = tmp;
a++;
b++;
}
// a 文字列が長い場合
while ( *a != '\0' ){
*b++ = *a; *a++ = '\0';
}
// b 文字列が長い場合
while ( *b != '\0' ){
*a++ = *b; *b++ = '\0';
}
*a = '\0';
*b = '\0';
}
以上。
No.3
- 回答日時:
#include <stdio.h>
void swap(char *a, char *b)
{
char c, *cp;
while(*a != '\0' && *b != '\0'){
c = *a;
*a ++ = *b;
*b ++ = c;
};
if(*a == '\0' && *b == '\0') return;
if(*a != '\0'){
cp = a;
while(*a != '\0') *b ++ = *a ++;
*cp = *b = '\0';
}
else if(*b != '\0'){
cp = b;
while(*b != '\0') *a ++ = *b ++;
*cp = *a = '\0';
}
}
int main(void)
{
char a[16] = "abc", b[16] = "wxyz";
printf("a : %s\nb : %s\n\n", a, b);
puts("a <-> b");
swap(a, b);
printf("a : %s\nb : %s\n\n", a, b);
puts("a <-> b");
swap(a, b);
printf("a : %s\nb : %s\n\n", a, b);
return 0;
}
No.2
- 回答日時:
★アドバイス
>やってみると、最初の一文字しかswapされません。
>どうしてこれではいけないのでしょうか?
↑
ポインタを理解していないからです。
単純にそこの問題。あと文字列も理解していないような気がします。
・今回の swap() 関数はどちらのタイプですか?
(1)ポインタを使って入れ替えるタイプ
(2)文字列の内容を入れ替えるタイプ
ソースをみると
main() では文字列内容を入れ替えるタイプのような書き方で
swap() 関数ではポインタを使って入れ替えているようです。
この方法だとそれぞれに矛盾しているので実行結果が期待通りになりません。
・下に2タイプのサンプルを載せておきます。→main() にも注目。
サンプル1:ポインタを使って入れ替え
void swap( char **a, char **b )
{
char *tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
char *a[ 2 ] = { "abc", "efg" };
printf( "befor a[0]:%s a[1]:%s\n", a[0], a[1] );
swap( &a[0], &a[1] );
printf( "after a[0]:%s a[1]:%s\n", a[0], a[1] );
return 0;
}
------------------------------
サンプル2:文字列内容を操作して入れ替え
void swap( char *a, char *b )
{
char tmp;
while ( (*a != '\0') && (*b != '\0') ){ ←ここに注目。
tmp = *a;
*a = *b;
*b = tmp;
a++;
b++;
}
}
int main( void )
{
char a[ 2 ][ 5 ] = { "abc", "efg" };
printf( "befor a[0]:%s a[1]:%s\n", a[0], a[1] );
swap( a[0], a[1] ); ←ここも注目。
printf( "after a[0]:%s a[1]:%s\n", a[0], a[1] );
return 0;
}
その他:
・さてどちらのタイプが参考になりましたか?
タイプ1はポインタの値を入れ替えることで文字列を入れ替えているようにしています。
タイプ2では文字列の内容を入れ替えるという入れ替えです。
多分はタイプ2の方法を知りたいのでしょうけど2タイプ載せました。
・この2タイプでは main() 関数の文字列宣言や swap() 関数の引数に違いがあります。
C言語では文字列を文字型(char)の配列として扱い、その文字列はポインタでやり取りされます。
なので『&』演算子をつけるべきかどうかをしっかりと覚えて下さい。
・以上。
No.1
- 回答日時:
関数swapが1文字しか入れ替えないからです。
・swapが文字列の先頭から末尾まで順に処理するように
swapの処理内容を変更する。
・文字列の先頭から末尾まで順にswapの呼び出しを繰り返す。
(swapは1文字の入れ替えの処理のまま書き換えない)
の「どちらか」をおこなう必要があります。
頑張ってみてください。
できたらまたソースを見せてください。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
ゆるやかでぃべーと タイムマシンを破壊すべきか。
これはディベートの論題だと仮定したうえでの回答お願いします。あなたは、その末にタイムマシンを壊してしまうのか、使い道を探すのかどうかを考えてもらいたいです。
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
C言語のポインターに関する警告
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
コマンドライン引数 *argv[]は...
-
new charとnew char[N]の違いは?
-
C言語で文字列をかえす正しい書...
-
C言語のプログラムについてです
-
DWORDとcharの変換
-
C言語の文字列について
-
C++17で、unsigned char * 配列...
-
ASCIIコードへの変換方法
-
警告 : 問題のあるポインタの変換
-
【C言語】引数にファイルパスを...
-
小数点入りの文字列をfloat型に...
-
2次元配列の文字"列"の初期化方法
-
C言語のintとcharの違いってな...
-
C言語 strstrの実装
-
警告
-
fgetsで読み込んだ値のvector処理
-
文字列の反転
-
fstream型オブジェクトを関数の...
-
Cの関数の引数のconst *charに...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
DWORDとcharの変換
-
小数点入りの文字列をfloat型に...
-
new charとnew char[N]の違いは?
-
char 文字列型 の表現範囲が-12...
-
C言語の文字リテラル中の16進文...
-
C++17で、unsigned char * 配列...
-
fstream型オブジェクトを関数の...
-
char型にint型の数値を代入する。
-
2次元配列の文字"列"の初期化方法
-
strcat関数を自作したいです
-
C言語で文字列をかえす正しい書...
-
C++Builder 2009 テキスト...
-
動的メモリの初期化方法について。
-
C言語のプログラムについてです
-
入力された文字列の中の数字を...
-
エクセルのMID関数は、C言語では?
おすすめ情報