🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

再帰

情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。

Q&A

解決済

3回答

3096閲覧

再帰処理でreturn文が実行されても、呼び出し元に帰らない。

Eisaku_Yoshida

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

再帰

情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。

0グッド

0クリップ

投稿2021/01/08 09:08

編集2021/01/08 09:16

アルファベットを表示する関数(printAlphabet)を再帰処理で呼び出してアルファベットを表示させたいです。
しかし、今、printAlphabet関数の中で、return文(③)が実行されているにもかかわらず、
main関数に戻りません。
よって、無限ループに陥っています。

理由がわかりません。
ご教授くださりますと、嬉しいです。
よろしくお願いいたします。

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5int printAlphabet(char *alphabet); 6 7// アルファベットの配列 8static char alhpabet[] = "abcdefghijklmnopqrstuvwxyz"; 9 10int main(void) 11{ 12 int iRet = 0; 13 iRet = printAlphabet(alhpabet); // ① 14 printf("%d\n", iRet); 15 return 0; 16} 17 18int printAlphabet(char *alphabet) 19{ 20 while(*alphabet != '\0'){ 21 printf("%c", *alphabet); 22 printAlphabet(++alphabet); // ④ 23 } 24 printf("\n"); // ② 25 return 0; // ③ 26}

terminal

1Thread 2 hit Breakpoint 1, main () at 問題6.c:10 210 **iRet = printAlphabet(alhpabet);** // ① 3(gdb) next 4 5Thread 2 hit Breakpoint 3, printAlphabet (alphabet=0x10000805a <alhpabet+26> "") 6 at 問題6.c:23 723 printf("\n"); // ② 8(gdb) next 9abcdefghijklmnopqrstuvwxyz 1024 return 0; // ③ ※これが実行された後、④の下に戻る。 11(gdb) print *alphabet 12$1 = 0 '\000' 13(gdb) next 14printAlphabet (alphabet=0x10000805a <alhpabet+26> "") at 問題6.c:21 // // 呼び出し元に戻った。(④) 1518 while(*alphabet != '\0'){ 16(gdb) next 17 18Thread 2 hit Breakpoint 3, printAlphabet (alphabet=0x10000805a <alhpabet+26> "") 19 at 問題6.c:23 2023 printf("\n"); 21(gdb) next 22 2324 return 0; // 呼び出し元のreturn文(③)→★想定では、ここでMain関数に戻って欲しい★ 24(gdb) next 25printAlphabet (alphabet=0x100008059 <alhpabet+25> "z") at 問題6.c:21 26(gdb) 27 28コード

●環境
Mac OS Big Sur
Ver.11.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

再帰を重ねてa~zを1文字ずつ表示してからヌル文字に達しても、すぐにmainに戻るわけではありません。これまでに呼ばれたprintAlphabetを一つずつ辿りながら戻ることになります。

その際、(すでに他の回答者の方が述べているように)if文で書かないと、「何もせずにただ戻る」動作になりません。

実際にはwhile文で書かれていて、しかも*alphabetはヌル文字ではないので、「何もせずにただ戻る」代わりに、「zを表示して再帰呼び出し」→「ヌル文字に達して戻る」→「yを表示して再帰呼び出し」→「zを表示して再帰呼び出し」→「ヌル文字に達して戻る」→「xを表示して再帰呼び出し」→「yを表示して再帰呼び出し」→「zを表示して再帰呼び出し」→「ヌル文字に達して戻る」(以下略)という動作になります。

おそらく、やりたいのはこういうことでは。

C

1#include <stdio.h> 2#include <string.h> 3 4int printAlphabet(char *str); 5 6int main(void) 7{ 8 char alhpabet[] = "abcdefghijklmnopqrstuvwxyz"; 9 int iRet = 0; 10 iRet = printAlphabet(alhpabet); 11 printf("\n"); 12 printf("%d\n", iRet); 13 return 0; 14} 15 16int printAlphabet(char *str) 17{ 18 if (*str != '\0') { 19 printf("%c", *str); 20 printAlphabet(++str); 21 } 22 return 0; 23}

投稿2021/01/08 09:58

Daregada

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Eisaku_Yoshida

2021/01/13 05:55

ご回答ありがとうございます! これまで呼び出されたprintAlphabet関数を一つずつ辿りながら戻っていくことは理解しました。 ただ、printAlphabet関数の引数はchar型のポインタ型なので、*str が'\0'になった時点で、呼び出されたprintAlphabet関数に戻っても、*strが\0なので、エラーが起きないと思うのですが。 それとも、引数に値が入るのは、関数がちゃんと呼び出された際であって、呼び出されたprintAlphabet関数に戻っても、その時のprintAlphabet関数の引数に入っているのは、そのprintAlphabet関数がきちんと呼び出された際に入ったアドレスだという認識で良いのでしょうか?
Eisaku_Yoshida

2021/01/13 06:09 編集

すみませんでした。自己解決しました。 今、xcodeでstep 実行して、呼び出し元のprintAlphabet関数を順にたどっていくと、 char *strの値が、順に呼び出し時の値で更新されているのを確認できました。 自己解決できました。ありがとうございます。 どうして、whileではダメで、if文ではいけるのか疑問だったのですが、 if文の場合は、下に処理が行くだけで、繰り返さないので、引数の値が呼び出し時の値で更新されていても、if文に入ることはもう無いので、return文で呼び出し元に戻るのだとようやく理解できました。 ありがとうございました!
guest

0

while(*alphabet != '\0'){

ここは while ではなく if とすべきでは?

投稿2021/01/08 09:25

fana

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Eisaku_Yoshida

2021/01/13 06:09

ご回答、ありがとうございます!
guest

0

C

1#include <stdio.h> 2 3void printAlphabet(const char* alphabet) { 4 if ( *alphabet == '\0') { 5 // 末尾に達したら改行しておわり 6 printf("\n"); 7 } else { 8 // 末尾じゃないならその文字を書き、 9 printf("%c", *alphabet); 10 // ひとつズラしてprintAlphabet 11 printAlphabet(++alphabet); 12 } 13} 14 15int main() { 16 printAlphabet("abcdefghijklmnopqrstuvwxyz"); 17 return 0; 18}

投稿2021/01/09 00:58

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問