戻し値がchar

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
さっかん

戻し値がchar

#1

投稿記事 by さっかん » 18年前

C言語を学んでまだ2ヶ月なので色々と知識に乏しいのですが、よろしくお願いします。

#include<stdio.h>
char change(int number);
int main()
{
int x;
char y[10][10];
x=56;
y=change(x);
return 0;
}
char change(int number)
{
char result[10][10];
sprintf(result[1],"%d",number);
return result;
}

xにintの56を入れたらyに文字列の56を返す関数を使ったプログラムにしたいのですが、コンパイルするとエラーが出てしまいます。何処が悪いのでしょうか?

バグ

Re:戻し値がchar

#2

投稿記事 by バグ » 18年前

戻り値の型がchar型なのに、実際にはchar型のポインタを返しているからだと思います。

さっかん

Re:戻し値がchar

#3

投稿記事 by さっかん » 18年前

バグさん返信有難う御座います。しかし本当にすいませんが、ポインタとやらがよくわかりません;;大変お手数ですが、少々変えてもらってもかまわないので、実際に何処を直せばいいか書いてもらえませんか?それを見てポインタを理解したいと思います。できればでいいので、よろしくお願いします。

バグ

Re:戻し値がchar

#4

投稿記事 by バグ » 18年前

ポインタを理解しないままに、サンプルを見てもよく分からないと思いますので、順を追って説明しますね。
まず、文字と文字列の違いは理解できていますか?

さっかん

Re:戻し値がchar

#5

投稿記事 by さっかん » 18年前

とてもありがたいです!よろしくお願いします。文字列は自信がないんですが、文字は'abc'とかを扱う型でprintfで出力する時に%cを使って、文字列は後ろに[/url]をつけて複数保存できるようにした型で%sを使うんですよね?

バグ

Re:戻し値がchar

#6

投稿記事 by バグ » 18年前

基本的に文字とは、あくまで1文字('A'←こんなのです)を指し、2文字以上("ABCDE"←こんなのです)になると文字列になります。

ちなみに、'abc'という記述をするとエラーになります。'(シングルクォーテーション)で括ってよいのは文字だけです。複数の文字…文字列を記述したい場合は、"(ダブルクォーテーション)で括ってやりましょう。

通常、文字列を扱う場合、char型の配列を利用するのですが、char型に限らず、配列については御存じでしょうか?

さっかん

Re:戻し値がchar

#7

投稿記事 by さっかん » 18年前

そうでした!文字列の場合はダブルクォーテーションでしたね;文字については少しあやふやなところがあったんですが、配列自体は大丈夫だと思います。

バグ

Re:戻し値がchar

#8

投稿記事 by バグ » 18年前

それでは、1つ問題です。

char str[6] = {"ABCDE"};

上記のように初期化した場合、a[0],a[1],a[2],a[3],a[4],a[5]のそれぞれに格納されている値は何でしょうか?

さっかん

Re:戻し値がchar

#9

投稿記事 by さっかん » 18年前

a[0]=A,a[1]=B,a[2]=C,a[3]=D,a[4]=E,a[5]=なし
ですよね??

YuO

Re:戻し値がchar

#10

投稿記事 by YuO » 18年前

>>>> ちなみに、'abc'という記述をするとエラーになります。'(シングルクォーテーション)で括ってよいのは文字だけです。

とりあえず,'abc'は「実装依存の振る舞い」なので,エラーになるとは限りません。


> a[0]=A,a[1]=B,a[2]=C,a[3]=D,a[4]=E,a[5]=なし

値を示す場合はソースの表記にあわせる方がよいです。
1と書かれたら,数値の1か数字の'1'か区別がつきません。

「なし」という値はあり得ません (空ポインタはあるが,これは値がなしであるわけではない)。
a[0] : 'A'
a[1] : 'B'
a[2] : 'C'
a[3] : 'D'
a[4] : 'E'
までは正解です。あとは,a[5]の値が何になっているか,です。

バグ

Re:戻し値がchar

#11

投稿記事 by バグ » 18年前

a[5]は'\0'が入りますが、ほかはOKです。
こちらが想定していたよりも、分かっているようですね(^-^)
それでは…
void main(void)
{
	char a[6];
	sprintf(a, "%s", "ABCDE");
}
こうした場合と…
void Dainyu(char* str)
{
	sprintf(str, "%s", "ABCDE");
}

void main(void)
{
	char a[6];
	Dainyu(a);
}
こうした場合、両方ともa[/url]の中は同じ物になります。
理由は分かりますか?

バグ

Re:戻し値がchar

#12

投稿記事 by バグ » 18年前

おおっと、YuOさんの言われるとおり

a[0]=A

こういう記述はまずかったですね…失礼しました(^_^;)

さっかん

Re:戻し値がchar

#13

投稿記事 by さっかん » 18年前

YuOさんもご教授有難う御座います。確かに’’が必要ですね。
えと、問題の方は上の方がそのままmain内で実行されていて、下の方はDainyuという関数を自分で作って、それをmainで使用しているから結局は結果が同じになるんですよね?

バグ

Re:戻し値がchar

#14

投稿記事 by バグ » 18年前

いや、たしかにそうなのですが…
main関数の中のa[/url]が、何故Dainyu関数の中で書き替えられたか?の理由です。
void Test(int c)
{
int d = 1234;
c = d;
}

void main(void)
{
int a = 0;
Test(a);
}

こんなプログラムを実行しても、aの中身は0のままで変わりませんよね?この理由も分かりますか?

さっかん

Re:戻し値がchar

#15

投稿記事 by さっかん » 18年前

え~と、Test(a);だけだったら戻し値が入る場所が指定されてないからですか?
となると、先ほどのプログラムでa[/url]が書き換えられた理由が分かりません;;

バグ

Re:戻し値がchar

#16

投稿記事 by バグ » 18年前

>>え~と、Test(a);だけだったら戻し値が入る場所が指定されてないからですか?

そうですね、そういう考え方も正しいですが、今はポインタの勉強をしているので、戻り値の事は、今だけはとりあえず忘れてください(^-^)


>>となると、先ほどのプログラムでa[/url]が書き換えられた理由が分かりません;;

という事で、ここからがようやく本題です。

『何故、値を書き換えられたのか?』ですが、これは変数の中身ではなく、変数が収められている場所(アドレス)を渡しているからなんです。



ちょっと、脱線しますが、たとえ話です。

1冊の本を思い浮かべてください…。あなたの読みたい場所を探すにはどうしますか?

おそらく目次を見るのではないかと思います。それでは、目次には何が書かれているでしょうか?

そう、ページ数ですね。アドレスというのは、ここでいうページ数だと思って下さい。

そして、ポインタというのは、そのページ数を指し示す『しおり』のようなものだと思って下さい。




文字列が書き換わった理由は、文字列の収められた場所を関数の引数として渡してやり、そのページを書き換えたので、内容が書き換わった訳です。

そして、1つ前の書き込みで、値が書き換わらなかったのは、本の中身をコピーして、コピーした紙を書き換えていたから、本そのものの内容は変わらなかったという訳なんです。

サンプルです
#include	<stdio.h>

void Change(int nNumber, char szBuf[10][10]);

int main()
{
	int x; 
	char y[10][10];
	
	x = 56;

	// 第2引数のyはy[10][10]の先頭のアドレスを示します
	Change(x, y);

	// Change関数の中身で書き換えられたのはy[1][/url]の中身なので、y[1]を表示する
	printf("%s\n", y[1]);

	return 0;
}

void Change(int nNumber, char szBuf[10][10])
{
	sprintf(szBuf[1], "%d", nNumber);
}

さっかん

Re:戻し値がchar

#17

投稿記事 by さっかん » 18年前

#include<stdio.h>
char change(int number,char buf[1][10]);
int main()
{
int x;
char y[1][10];
x=56;
change(x,y);
printf("%s\n%s\n",y[0],y[1]);
return 0;
}
char change(int number,char buf[1][10])
{
sprintf(buf[0],"%d",number);
sprintf(buf[1],"%d",number-11);
}

今このように作り変えてみたら

56
45

とちゃんと表示されました!階乗を計算するpow(x, y)と同じような使い方なんですね。
でも授業では
y【returnの返し値を入れる】=change(x【実因数】);
と習っていて、今までこのように使っていたのですが、何故返し値が文字列になったとたん
change(x,y);
という書き方にしなければならないのですか??
言ってしまえばy=pow(x);でもいいような気になってしまうのですが・・・。

バグ

Re:戻し値がchar

#18

投稿記事 by バグ » 18年前

それは、変数には寿命が存在するからです。

基本的にスコープ(環境によって例外はありますが、{ }で括られている範囲)内で用意された変数は、そのスコープ内でのみ有効となり、スコープの外に出た時点で破棄されてしまう物だと思って下さい。

一番最初にさっかんさんが書かれたプログラムですと、change関数内で用意された配列のアドレスを戻り値としていましたよね?

これをしてしまうと、change関数を出た時点で、アドレスを受け取ったものの、実体が存在しないという事になってしまい、危険なんですね。

box

Re:戻し値がchar

#19

投稿記事 by box » 18年前

うまくいったのは偶然の産物であるようです。
というのは、

> char y[1][10];

この定義だと

> printf("%s\n%s\n",y[0],y[1]);

y[1]は定義範囲外だからです。buf[/url]についても同じことが言えます。

さっかん

Re:戻し値がchar

#20

投稿記事 by さっかん » 18年前

では、戻り値がintの時もy=change(x);やreturnなどを使わずにchange(x,y);を使ったほうが無難なのですか?

さっかん

Re:戻し値がchar

#21

投稿記事 by さっかん » 18年前

え!;;え~と定義範囲外とはどういうことですか?

組木紙織

Re:戻し値がchar

#22

投稿記事 by 組木紙織 » 18年前

>定義範囲外とはどういうことですか?

簡単に言うと"配列の外側"です。

char ch[3];
と配列を確保すると、
ch[0]からch[2]までの3つのcharの領域として定義されます。

このときch[100]の位置は、定義された配列の範囲の外側であるということです。

さっかん

Re:戻し値がchar

#23

投稿記事 by さっかん » 18年前

そうだったんですか!y[2][10]とbuf[2][10]にすればよかったんですね。
ご教授有難う御座います。

さっかん

Re:戻し値がchar

#24

投稿記事 by さっかん » 18年前

バグさんを初め、YuOさん、BOXさん、組木紙織さん本当に有難う御座いました。
あと一つ疑問があるのですが、スレ違いなので改めて投稿させていただきます。
初めに書いた通り、今年大学生になって初めてプログラミングの世界に触れた初心者なので、本当に基本的なことすら分かりませんが、よろしければまたご教授の程よろしくお願いします!

閉鎖

“C言語何でも質問掲示板” へ戻る