文字列を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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
char*を初期化したいのですが
-
小数点入りの文字列をfloat型に...
-
CStringからchar*への型変換に...
-
C言語にて構造体のメンバがNULL...
-
C言語:小文字を大文字に変換す...
-
char 文字列型 の表現範囲が-12...
-
C言語のintとcharの違いってな...
-
SubStringの使い方について
-
DWORDとcharの変換
-
strcat関数を自作したいです
-
ASCIIコードへの変換方法
-
new charとnew char[N]の違いは?
-
csvファイルをfscanfで読み込む...
-
簡易版smtpクライアント(メール...
-
fread()関数とfwrite()関数につ...
-
文字列を表すための配列とポインタ
-
ostringstreamではまりました
-
コマンドライン引数 *argv[]は...
-
fgetsで読み込んだ値のvector処理
-
【C言語】引数にファイルパスを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
C言語にて構造体のメンバがNULL...
-
C言語のintとcharの違いってな...
-
小数点入りの文字列をfloat型に...
-
new charとnew char[N]の違いは?
-
const char* s1とただのchar s1...
-
DWORDとcharの変換
-
strcat関数を自作したいです
-
C++17で、unsigned char * 配列...
-
文字列内の数字削除
-
エクセルのMID関数は、C言語では?
-
char 文字列型 の表現範囲が-12...
-
char型にint型の数値を代入する。
-
C言語を用いた環境変数の作成/...
-
動的メモリの初期化方法について。
-
fstream型オブジェクトを関数の...
-
C言語のプログラムについてです
-
文字列の途中から途中までを抽出
-
C言語:小文字を大文字に変換す...
おすすめ情報