#include<stdio.h>
/*---非負の整数を読み込んでます*/
int scan_uint(void)
//関数scan_uintは、キーボードから非負の整数値を読み込んでその値を返す関数です。
{
//この関数には受け取るべき仮引数がありません。仮引数がないことを示すためには()の中をvoidとします。
int tmp;//テンプの箱作成
do {
printf("非負の整数を入力してください:");scanf("%d",&tmp);
if(tmp< 0)
printf("\a負の数を入力しないでください");
}
while(tmp<0);
return (tmp);
}
/*非負の整数を逆転した値を返す*/
intrev_int(int num)
{
inttmp = 0;
if(num> 0){
do{
tmp = tmp * 10 + num % 10;
num /= 10;
}while (num > 0);
}
return (tmp);
}
int main(void)
{
int nx = scan_uint();
printf("反転した値は%dです。\n", rev_int(nx));
return 0;
}
教えてください!参考書に書いてあることをまとめて
プログラムを読んでるのですが、わからない部分があります。
(1)まずint scan_uint(void)からこのプログラムは読み込んでるのでしょうか? どこかのサイトを調べたら、最初にint mainからプログラムは
読み込むというのを観たのですが、コンパイルして実行した動きをみるかぎり一番最初はint scan_uint(void)から読んでるように見えます。。。
(2)int scan_uint(void)の文は理解できました。私なりに解釈したのは
ここでは正の数を入力しないと次に進まないことと
負の数を入力した場合、負の数を入力しないでくださいと注意がずっと
でるという文です。
質問ですが、このあとint rev_int(int num)文に移ると思うのですが
ここの int tmp = 0; これはこのint rev_int(int num)文のみの
tmpの箱と参考書に記載がありました。つまり int scan_uint(void)で
出てきたtmpとは別個と解釈しました。
そうなると、int rev_int(int num)文を読んでみると
tmpの箱を作成。そこは0を代入。
if文で num>0の時、 do文に入る (ここでいうnumは int numと宣言してないですけど、またscanfとか作って値はまだいれてないですけど??)
do文は
tmp = tmp*10 + num %10
num /=10
wile(num>0)
これを見る限り、numという箱が見えません。全体を見渡しても
どこかでnumに値が代入されたのち、このint rev_int(int num)
という文を読みこんでいき if num>0のときと宣言されていますが
もっと前の段階でnumの値が入力されていない限り
このif文は適用されないと思ったのですが、プログラムは動いてます
三つ目の質問です
tmp = tmp *10 + num % 10
num /=10 の部分がわかりませんでした。
tmpはまず、int scan_uint(void)で作成したtmpと
int rev_intで登場してきたtmpとは別個と参考書に書いてあるのが
正しいのであれば
tmpの値はここでは初のはずです。
一体いつ値を入力したのでしょうか?
もしも一番最初のscanfの時に入力した例えば12345が此処でも適用されるなら tmp = 12345 ×10 + num % 10を tmpに代入するって文になりますが
どうしてtmpを10かけるのですか?123450になり、
そのあとnumの値が此処でもまだ不明なのですがnum/10したものと
足すみたいですが、わかりませんでした。。。
まとめると、tmp = tmp*10+num%10がわかりません。
また、numとは何かわかりません、値もどの値がどこで代入されていて
while(num>0)が引っかかるのか不明です。
tmpはint scan_uint文内で入力した値(scanfの部分で)
12345と仮に入力したら、それは次のint rev_int(int num)でも続いて活用されてるのですか?
参考書はなぜ別個と書いてるのかわかりません。
ごめんなさい>_< とても長くなりました。
どなたか解る方、教えてください、よろしくおねがいします。
No.1
- 回答日時:
(1)main関数を最初に実行します。
今回は、main関数の先頭部分でscan_uint関数を実行していますので、あたかもscan_uint関数を最初に実行しているように見えているだけです。
(2)rev_int関数のnumを定義していない、とのことですが、関数の先頭部分
int rev_int(int num)
で、rev_int関数のint型の引数として定義済みです。
(3)rev_int関数のtmpは、同関数の先頭部分で
int tmp = 0;
このように、定義と初期化を行なっています。scan_uint関数のtmpとは、全く別物です。
No.2ベストアンサー
- 回答日時:
(1)
C言語の場合「書いてある順番」と「実行する順番」は、まったく関連がありません。
決まっているのは「必ずmain関数から実行する」と言う事だけです。
因みに「実行を開始する場所(ポイント)」のことを「エントリポイント」と呼び、Cでは「main関数の先頭がエントリポイント」と決まっています。
(2)
>質問ですが、このあとint rev_int(int num)文に移ると思うのですが
いいえ。移りません。
これが「そもそもの誤解の始まり」です。
上記(1)で言った通り、必ずmainからプログラムが動き始めます。
main関数で
int nx = scan_uint();
printf("反転した値は%dです。\n", rev_int(nx));
と、それぞれの関数を呼んでいるので、実際の動作を実行順に羅列すると
1.必ずmainの先頭からプログラム開始。
2.mainからscan_uintが呼ばれる。
3.呼ばれたscan_uintが処理を行う(内容は理解しているようなので省略)
4.scan_uintからmainに帰ってくる。その時の戻り値がnxに入る。
5.printfの引数にrev_int(nx)があるので、nxを引数にしてrev_intを呼ぶ。
6.呼ばれたrev_intは、nxの値をnumとして受け取る。
7.rev_intは受け取ったnum(mainのnxと同じ値)を元に処理を行う。
8.rev_intはtmpに作った値を戻り値として関数を終わる。
9.rev_intからmainに帰ってくる。その時の戻り値がprintfの引数になる。
10.mainからprintfが呼ばれる。
11.呼ばれたprintfは何かを画面に表示し、関数を終わる。
12.printfからmainに帰ってくる。printfの戻り値は受け取ってないので捨てられる。
13.mainがreturn 0;で関数を終わらせ、プログラムが終了する。
となります。
>これを見る限り、numという箱が見えません。全体を見渡しても
上記の6.で「引数の実体として、mainから渡してもらってる」でしょう?
それが判らなかったのは「プログラムはmainの先頭から実行する」と言うのを理解できていないからです。
(3)
>tmp = tmp *10 + num % 10
>num /=10 の部分がわかりませんでした。
>どうしてtmpを10かけるのですか?123450になり、
123450にはなりません。
rev_intに入ってきたら
int tmp = 0;
ってやってるので、tmpは「最初は0」です。別の場所(scan_uintなど)にあるtmpは「同姓同名の赤の他人」なので忘れましょう。
scan_uintで「12345」を入力すると、12345がmainのnxに返って来て(nxが12345になって)、そのnxの値である12345がrev_intに渡され、rev_intは12345をnumに受け取ります。
つまり「最初は、numは12345、tmpは0になっている」のです。
そして、numが0かどうか調べます。
numが0でない(12345になっている)ので、次に
tmp = tmp *10 + num % 10;
を実行します。
tmp(中身が0)を10倍した値と、numを10で割った余りを足し、tmpに戻しています。
つまり0を10倍した0に、12345を10で割った余り5を足し、足した結果5をtmpに戻します。なのでtmpは5になります。
次に
num /=10;
を実行します。
これは「numを10で割って、numに戻す」です。
num = num / 10;
と同じです。
numは12345なので、10で割った商1234がnumの新しい値になります。
なお、Cでは、整数の割り算の答えは「商」だけです。小数点以下はありません。例えば、1を10で割ると0になります。
次は、while文で「numが0より大きいなら繰り返し」です。
numが0より大きい(1234になっている)ので繰り返すことになり、また
tmp = tmp *10 + num % 10;
を実行します。
tmpは5になっているので10倍して50、それにnum(1234)を10で割った余り4を足し、足した54をtmpに戻します。
次に
num /=10;
を実行します。
numは1234なので、10で割った商123がnumの新しい値になります。
これを「numが0より大きい間、繰り返し」すると
tmp=0、num=12345
↓
tmp=5、num=1234
↓
tmp=54、num=123
↓
tmp=543、num=12
↓
tmp=5432、num=1
↓
tmp=54321、num=0
となり、numが0になって繰り返すのをやめた時、tmpは54321になっています。
そして、最後に
return tmp;
として、54321をmainに返します。
mainに帰って来ると、前述の9.~11.の処理で
反転した値は54321です。
と表示されます。
>参考書はなぜ別個と書いてるのかわかりません。
「別の場所にある、同じ名前の変数は、同姓同名の赤の他人」なので「別個」です。
すごく、丁寧に教えていただいて>_< こんなにたくさん説明を書いていただいて、すごく解りやすかったです!!
本当にありがとうございます!! <(_ _)> <(_ _)> <(_ _)>
もっとC言語の勉強頑張ります!!
ありがとうございました!!!!!!!!!!!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# C言語でif文が予想と違う動きをする件について7 4 2023/03/20 00:26
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C pointer? or... 2 2022/03/29 00:47
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# C言語 3 2022/10/04 15:07
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「指定されたキャストは有効で...
-
比較回数と交換回数表示について
-
C言語での引数の省略方法
-
複数桁10進数の*桁目だけを抽出...
-
#define _CRT_SECURE_NO_WARNIN...
-
std::set<int> で、ある値が何...
-
C言語で三目並べをするプログラ...
-
商と剰余を同時に求める(C言語)
-
if と配列の組み合わせ
-
【C++】関数ポインタの使い方
-
並列プログラミングのπ計算につ...
-
c言語
-
HANDLEて何ですか?
-
read関数をノンブロッキングで...
-
卒業研究でよく分からないとこ...
-
DLLをGetProcAddress()で実行で...
-
GlobalAllocの変数を関数に引き...
-
シグマ公式・・・C言語
-
ファイルから読みこむ方法
-
c言語の問題です
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
「指定されたキャストは有効で...
-
C言語 配列と関数の練習問題
-
複数桁10進数の*桁目だけを抽出...
-
(int *)の意味
-
if と配列の組み合わせ
-
ラップ関数とはどんなものですか?
-
卒業研究でよく分からないとこ...
-
【C++】関数ポインタの使い方
-
c言語
-
足して100になるような乱数のア...
-
C言語初心者です、、、お助けく...
-
数字列を3桁ごとにカンマで区切...
-
C言語 エラーの原因がわからな...
-
実数の整数部,小数部の取得
-
課題でつまってます・・・
-
商と剰余を同時に求める(C言語)
-
C言語の配列をC++のvectorに高...
-
std::set<int> で、ある値が何...
おすすめ情報