![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
#include<cstdio>
#include<cstring>
#define _CRT_SECURE_NO_DEPRECATE 1
#define MAXBUFF 256
void s_swap(char* str_a, char* str_b)
{
char str_dummy[MAXBUFF];
strcpy_s(str_dummy,strlen(str_dummy),str_a);
★strcpy_s(str_a,strlen(str_a),str_b);
★strcpy_s(str_b,strlen(str_b),str_dummy);
}
void main(void)
{
char* str_a = "ABC";
char* str_b = "DEF";
int a;
printf("呼出前:str_a=%s, str_b=%s\n", str_a, str_b);
s_swap(str_a,str_b);
printf("呼出後:str_a=%s, str_b=%s\n", str_a, str_b);
}
str_aとstr_bの中身を入れ替える処理で、エラーや警告はでないのですが
★のところで実行失敗します。
昔から文字列の処理は苦手でどのように攻略したらよいのか
解説していただけないでしょうか。
No.8ベストアンサー
- 回答日時:
>そこの部分は変えずに他を変えてできませんでしょうか?
void s_swap(char** str_a, char** str_b)
{
char *t;
t=*str_a;
*str_a=*str_b;
*str_b=t;
}
void main(void)
{
char* str_a = "ABC";
char* str_b = "DEF";
int a;
printf("呼出前:str_a=%s, str_b=%s\n", str_a, str_b);
s_swap(&str_a,&str_b);
printf("呼出後:str_a=%s, str_b=%s\n", str_a, str_b);
}
No.7
- 回答日時:
追記。
s_swap内でstr_dummyがMAXBUFFの大きさである事を期待しているので
char str_a[] = "ABC";
char str_b[] = "DEF";
じゃなく
char str_a[MAXBUFF] = "ABC";
char str_b[MAXBUFF] = "DEF";
として、str_a、str_bの大きさを「最低、MAXBUFFサイズ以上」で定義して下さい。
それに合わせ、コピールーチンは
strcpy_s(str_dummy,MAXBUFF,str_a);
strcpy_s(str_a,MAXBUFF,str_b);
strcpy_s(str_b,MAXBUFF,str_dummy);
に変えなければなりません。
じゃないと
char str_a[MAXBUFF] = "ABCDEF";
char str_b[MAXBUFF] = "GHI";
など「文字列の長さを違えて書いた時」にうまく行きません。ひっくり返した結果は「"GHI"と"ABC"」になると思われます。
それ以前に
char str_dummy[MAXBUFF];
strcpy_s(str_dummy,strlen(str_dummy),str_a);
だと、str_dummyの中身が不定なので、strlen(str_dummy)は、0を返したり、MAXBUFFよりも大きい値を返す可能性があります。つまり「何が起こるか判らないバグを含んでいる」のです。
No.6
- 回答日時:
char* str_a = "ABC";
char* str_b = "DEF";
と書くと、str_aやstr_bは「書き換え出来ない、コンスタントなデータ領域のアドレスを指す」ことになります。
言うなれば「文字列の実体がリードオンリーにされたメモリに配置され、ポインタ変数は、その、リードオンリーになっているメモリを挿す」のです。
つまり
s_swap(str_a,str_b);
は
s_swap("ABC","DEF");
と書いたのと同じ意味になってしまうのです。これが「やっちゃいけない事」なのは判りますよね?
なので、
char str_a[] = "ABC";
char str_b[] = "DEF";
と書き換えて下さい。
こうすると、書き換え可能なメモリ領域に、必要なバイト数の配列が用意され、定義を行っている場所で、内部的に「書き換え不可なデータ領域にある文字列が、配列にコピー」されます。
そして、str_aやstr_bは「書き換え可能なメモリ領域に置かれた配列」なので「中身を入れかえる事」が可能です。
No.5
- 回答日時:
ごめんなさい m(__)m
arsizeの定義を間違えました ・・・
#define arsize (sizeof(a))/(sizeof(a[0]))
でした ・・・
No.4
- 回答日時:
セキュリティ強化版の strcpyを使う際に 第2引数はバッファのサイズですからstrlenでは NULL文字の分を考慮しないためエラー(アサーション)になると思います
typedef arsize(a) (sizeof(a))/(sizeof[a])
void swap(char* str_a, char* str_b)
{
// str_dummyを初期化
char str_dummy[MAXBUFF] = {0};
// VC2005以降なら arsizeを _countofでもいいようです
strcpy_s( str_dummy, arsize(str_dummy), str_a);
strcpy_s(str_a, strlen( str_a ) + 1, str_b);
strcpy_s(str_b, strlen( str_b ) + 1, str_dummy);
}
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_14.png?e8efa67)
No.3
- 回答日時:
strcpy_sという関数は、初めてみました。
(あなたが自作した関数ではないですよね)ご使用のOSとコンパイラは何でしょうか?
この回答への補足
先日、Visual C++ 2008 Express Edition(フリー)をダウンロードして使ってます。OSはXPです。
こちらを参考にして、strcpy_sを使ってます。
http://msdn.microsoft.com/ja-jp/library/td1esda9 …
No.1
- 回答日時:
> char* str_a = "ABC";
> char* str_b = "DEF";
"ABC"や"DEF"などの文字列リテラルは変更不可能な固定文字列として扱われます。
上記プログラムの場合、str_aやstr_bは変更不可能な固定文字列領域アドレスを挿すポインターなのに、s_swap内で内容を書き換えようとして実行時例外が発生していると思われます。
変更不可能なのにchar*型の変数に代入できるのはなぜかというと、確かはるか昔のCプログラムとの互換性を保つためだったはずです。
この場合、
> char str_a[] = "ABC";
> char str_b[] = "DEF";
というようにポインターではなく、配列として文字列を定義すれば、失敗せずにすむはずです(すみません、未検証です)
当然のことながら、str_a及びstr_bの配列サイズが入れ替えるのに十分な大きさがないと、やはり実行時エラーになりますが。
お探しの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言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# C# 浮動小数の数値文字列化 1 2022/04/18 15:15
- C言語・C++・C# C言語 少しの疑問 4 2022/11/08 02:48
- C言語・C++・C# C言語の質問です HTMLでこのようなコードを書いたのですがそれをC言語で同じように書きたいです < 1 2022/08/11 23:38
- PHP PostgreSQLからCSV形式でエクスポートする際にカラム内の改行をとる方法 1 2023/02/22 10:05
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のintとcharの違いってな...
-
char*を初期化したいのですが
-
new charとnew char[N]の違いは?
-
文字列の扱いについて教えてく...
-
文字列配列を動的に割り当てる...
-
C言語にて構造体のメンバがNULL...
-
C言語のプログラムについてです
-
まだまだCプログラマーの初心者...
-
文字列内の数字削除
-
文字列のswap
-
CStringからchar*への型変換に...
-
ASCIIコードへの変換方法
-
C言語で文字列をかえす正しい書...
-
csvファイルを構造体に格納した...
-
文字列str内の全ての数字を...
-
const char* s1とただのchar s1...
-
文字型配列に格納した空白の切捨て
-
c言語のワーニングを無くしたい
-
2次元配列の文字"列"の初期化方法
-
ライブラリ関数
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
小数点入りの文字列をfloat型に...
-
strcat関数を自作したいです
-
C言語のプログラムについてです
-
const char* s1とただのchar s1...
-
DWORDとcharの変換
-
char型にint型の数値を代入する。
-
文字列の途中から途中までを抽出
-
new charとnew char[N]の違いは?
-
文字列内の数字削除
-
csvファイルをfscanfで読み込む...
-
fgetc( )の戻り値はなぜ整数??
-
char 文字列型 の表現範囲が-12...
-
fstream型オブジェクトを関数の...
-
エクセルのMID関数は、C言語では?
-
ポインタを使って回文かどうか...
-
ポインタ配列
おすすめ情報