非常に基礎的な質問で申し訳ないのですが
mainから渡した文字列を関数内で書き換えることができません。
int型の整数やchar型一文字はできるのですが。。。
例えば以下のようなソースでmainのABCをDEFに書き換えたいとき
どのようにすればいいのでしょうか。
(関数の戻り値で変更という方法以外で)
以下のソースでは値は書き換わりませんでした。
void func(char *str2)
{
str2 = "DEF";
}
int main()
{
char str1[20] = "ABC"
printf("%s", str1); //ABC
func(str1);
printf("%s", str1); //DEFになるようにしたい
}
No.1
- 回答日時:
ポインタの理解が足りませんね。
str2自体は仮引数なのでfunc関数から抜けると消滅します。
だからstr2をいくらいじっても無駄なのです。
ポインタそのものをいじるのじゃなくて、ポインタが指しているメモリに書き込まないとね。
void func(char *str2)
{
strcpy(str2, "DEF");
}
これでOK
この回答への補足
ありがとうございます。
func関数から抜けると消滅するということは分かるのですが
int型の場合、参照で渡して
*str2 = 10;
のようにすればstr1も置き換わると思います。
char配列型の場合は似たような記述方法はないのでしょうか?
strcpyのような関数を使わなければ無理ですか?
No.3ベストアンサー
- 回答日時:
Cには値渡し(Call by value)しかないので、str2に直接値を代入しても呼び出し元では値が変わらないですね。
例えば、次のようにすると呼び出し元でも値が変わります。
void func(char *str2)
{
str2[0] = 'D';
str2[1] = 'E';
str2[2] = 'F';
}
Cの文字列変数は文字列の先頭文字に対するアドレスが入っているだけなので、funcが呼ばれたとき、str2にはmain()のstr1のアドレスが入っています。元の書き方ではこのstr2に"DEF"という文字列の先頭文字に対するアドレスを代入しているだけなので、main()のstr1の中身は変わりません。余談ですが、このようにアドレスを格納した変数のことをポインタといいます。
ちなみに、同じ事を文字列操作関数を使ってやるとこんなかんじです。
#include <string.h>
void func(char *str2)
{
strcpy(str2, "DEF");
}
この場合、呼び出し元はstr2の最大サイズを知らず、多めに書きこんでしまう可能性があります。そして、確保した容量以上にメモリーを使用するとプログラムを異常終了させたり、プログラマの意図しない誤った動きをさせたりすること (バッファ溢れ攻撃) が可能となります。
よって、この様なプログラムを書いたほうがよりよいでしょう。
#include <stdio.h>
#include <string.h>
void
func(char *str, size_t str_size)
{
strncpy(str, "DEF", str_size - 1);
str[str_size - 1] = '\0';
}
int
main(void)
{
char str1[20] = "ABC";
printf("%s\n", str1);
func(str1, sizeof(str1));
printf("%s\n", str1);
return 0;
}
strncpy(str, "DEF", str_size - 1);はstr_size - 1の長さだけ"DEF"を書き込む関数で、最期の一文字をNULL文字で終了させない場合があるのでstr[str_size - 1] = '\0';しないといけません。この問題を解決するためにstrlcpyという関数を代わりに使うケースもあります。
No.4
- 回答日時:
Cでは「文字列」という型は無くて、「ポインタ/配列が示す場所から0までのchar」を文字列として扱う、というルールで運用しています。
プログラムを作る際は、他の数値型とは分けて、他の数値型の配列やポインタを扱うようなつもりで考える必要があります。
たとえば
void func(int *n2)
{
int n0={1,2,3} ;
n2 = n0 ;
}
これが、実質何もしない、ということはおわかりですね? あなたの書いたfunc関数は上のintをcharの置き換えただけのものです。
No.5
- 回答日時:
例えば
void testmain()
{
int i=0;
test(&i);
printf("%d",i);
}
void test(int*p)
{
*p=1;
}
の場合、&iが0x1000とすると、test内では0x1000の内容が1に変更されるため、testmainでもiの値が変わります。
ところが、
void testmain2()
{
char str[10] = "ABC";
test2(str);
printf("%s",str);
}
void test2(char* p)
{
p="DEF";
}
としたとき、strが0x2000、"DEF"の先頭アドレスが0x3000とすると、test2内ではpの値が0x3000に変更されるだけで、0x2000にあるデータは"ABC"のままです。当然、testmain2ではstrの値は0x2000なので、文字列は変更されません。
No.6
- 回答日時:
>例えば以下のようなソースでmainのABCをDEFに書き換えたいとき、どのようにすればいいのでしょうか。
「ABC」を「DEF」の同じ連番記載に換えたいということですよね。
やり方は2通りあると思います。
1つはあなたが承知の文字定数「DEF」に換える場合と、もう一つは元の文字について一定の幅を持たせて任意の「DEF」に換える場合です。
前者の場合は #1 さんの strcpy()関数を使うのが良いと思います。ただし、string.hヘッダーファイルを include しなければなりません。
後者の場合は↓に示す方法で、与えられた文字列str2全部に対して一定の幅を持たせて変換するものです。
まあ、結局は好みの問題でもありますが...。
/* 定数3の理由:A,B,C,D -> 4番目のD-1番目のA */
void func(char *str2){
while(*str2) *str2++ += 3; //str2文字列の最後まで変換
}
すみません、ABCをDEFにというのは一例で
連番にしたいというわけではなかったです。
でも、連番だとそのような考え方もあるのですね。
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
文字列内の数字削除
-
SetWindowTextについて。
-
構造体が戻り値の関数について...
-
WM_CHAR or WM_KEYDOWN の「wPa...
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
new charとnew char[N]の違いは?
-
文字列str内の全ての数字を...
-
C言語において、以下の条件で...
-
strcat関数を自作したいです
-
ポインタを使用 [数字列を数値...
-
DWORDとcharの変換
-
文字列の途中から途中までを抽出
-
C言語で文字列をかえす正しい書...
-
文字の代入とコピーについて
-
小数点入りの文字列をfloat型に...
-
callocについて
-
'\\0'とはなんですか?
-
p = (char **)*p の意味
-
C言語を用いた環境変数の作成/...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
CStringからchar*への型変換に...
-
C言語にて構造体のメンバがNULL...
-
小数点入りの文字列をfloat型に...
-
C言語のプログラムについてです
-
strcat関数を自作したいです
-
fstream型オブジェクトを関数の...
-
new charとnew char[N]の違いは?
-
DWORDとcharの変換
-
文字列の途中から途中までを抽出
-
char 文字列型 の表現範囲が-12...
-
const char* s1とただのchar s1...
-
wsprintf( ポインタ , "%d" , "...
-
c言語でポインタ変数を用いた配...
-
char型にint型の数値を代入する。
-
C言語で文字列をかえす正しい書...
-
C++17で、unsigned char * 配列...
-
共用体について
-
エクセルのMID関数は、C言語では?
おすすめ情報