質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.35%
C

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

Q&A

解決済

5回答

6569閲覧

c言語で、関数から文字列を返す方法がわかりません。

K.M.PEANUTS

総合スコア40

C

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

0グッド

1クリップ

投稿2021/07/07 00:36

c

1char* str { 2 return "文字列を返します。"; 3} 4 5int main(void) { 6 char a[10]; 7 strcpy(a, str()); 8 printf("%s", a); 9}

上のコードは極端な例ですが、ある関数から文字列を返してmain関数内で表示するプログラムを書きたいです。しかし上のコードだとzsh trace trap ./a.outというエラーが出てしまいうまく行きません。
どのように書き直せば良いでしょうか? ちなみに、strに引数を持たせるのは無しで、引数は無しでお願いします。

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

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

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

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

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

BeatStar

2021/07/07 00:51

エラーが出るならメッセージぐらい提示しましょう。 今回はなんとなくわかりますが、 場合によってはまったくわかりません。 エラーメッセージは怒声でも罵声でも罵倒でもハラスメントでもなく、 コンパイラ等からのメッセージです。 つまり、今の状態は『相手の話を聞かずに逆ギレしている人』です。 そんな人はコミュニケーションなんて取れませんよね。 なので、メッセージぐらい読みましょう。
BeatStar

2021/07/07 00:52

しかも、『関数の書き方』すら満足に書けていません。
neconekocat

2021/07/07 00:54

内部でmallocすれば出来ますけど極めて"危険"ですよ。
kaina

2021/07/07 00:59

関数の戻り値をstrcpy関数を使用してコピーしようとした意図はなんでしょうか? 教本やWeb等で調べてもそのような戻り値の受け取り方は書いて無いはずですが。
fana

2021/07/07 01:04

(別にコピーしたっていいんじゃない?)
K.M.PEANUTS

2021/07/07 01:06

”上のコードだとzsh trace trap ./a.outというエラーが出てしまい”はエラーメッセージではないのですか?そうだと思って記載してしまいました。 これは即興で作ったコードなので、本来のコードではstrcpyが必要なものもreturnしています。(char*型変数と、文字列のreturnをif文の場合によって分けるコードです。) 例のコードが下手くそですみません。。
maisumakun

2021/07/07 01:09

> ”上のコードだとzsh trace trap ./a.outというエラーが出てしまい”はエラーメッセージではないのですか?そうだと思って記載してしまいました。 それで特に問題ないです。
kaina

2021/07/07 01:11

fanaさんへ いや、別にいいんですが、何故そんな変則的なやり方をしようと思ったのか理由が分からなかったので。 char *a = str(); 単純に↑でやれば分かりやすいし、何故そうしなかったのかなと。
fana

2021/07/07 01:23

コード提示する際に要らないところを除去した結果がこの形になっている,ってだけなんじゃないかな. つまり本物のコードでの関数呼び出し部分がこの形(strcpy)で書かれていて,以降にコピーしたデータをいじくり回すような続きの処理が存在しているのでしょう. (何故か文法上必要な部分までも除去されてるから,少なくとも本番コードがそのまま示されているわけではないことは想像できる) コピー処理が問題を起こしているように見えるけども「そもそも何でコピーしたし?」というのは突っ込み方が違うような.
K.M.PEANUTS

2021/07/07 01:28

kainaさんへ strcpyでコピーすることと、char*型変数に代入すること、char型配列に代入することの違いがよくわかっていませんでした。ご指摘ありがとうございました。 初心者は、よくわからないで使っていることが多いです。 そこにstrcpyを使った理由はなんですか?と聞くのは意味のない質問です。『strcpyではなくchar *a = strと書けばうまくいく』というのを後出しではなく最初に言っていただければ、初心者もなぜその書き方ならうまくいくのかを調べることができ、理解を深めることができます。これからもよろしくお願いします。
maisumakun

2021/07/07 01:36 編集

> そこにstrcpyを使った理由はなんですか?と聞くのは意味のない質問です。 いえ、「なにかの意図を持って書いていたけど、その意図を実現するには別な方法が良かった」のような場合に、その質問から掘り下げることができます(回答者からすれば、「わからずに書いているかどうか」も聞かなければわからないのです)。
fana

2021/07/07 01:33

問題を起こしている処理がある →なんかわかんねぇけど,この処理自体を抹消するぜ! →当然ながら問題が消えた →ヨシ! って話でOKなんすか? (いや別に満足ならそれでいいのだが)
kaina

2021/07/07 01:43

う~ん、なんというか勉強の仕方を変えたほうが良いような。 K.M.PEANUTSさんの過去の質問を軽く見てみたのですが、課題で与えられた 問題を解くことが目的になっていて何故そのような書き方をすれば良いかということが 理解出来ないまま進めているように見えます。 課題のプログラムを作成することを目的にしては本末転倒です。 例えば今回の質問であればC言語における関数の呼び出し方、戻り値の受け取り方を 教本で1からきちんと理解出来ていれば自己解決出来た問題かと思います。
K.M.PEANUTS

2021/07/07 01:44

fanaさんへ 僕が質問内容は関数から文字列を返す方法だったので、とりあえず質問内容の結果が求められたところで終了しました。『なぜ先程のコードがエラーだったのか』は別の質問になってしまうと思うので、改めてstrcpyやchar型変数の違いを調べて、それでもわからなかったらまた質問させていただこうと思ってます。
neconekocat

2021/07/07 01:49

質問者さんが自分の質問の意味を理解していないのが問題なんですが・・・ まぁクローズするなら止めませんが。
fana

2021/07/07 01:53

> 本来のコードではstrcpyが必要なものもreturnしています。(char*型変数と、文字列のreturnをif文の場合によって分けるコードです。) という話の具体的なところが示されていないので, ココで言うところの「文字列を返す」ってのは何だろうね? っていう根本があやふやなままに思える. > char *a = str(); という,なんともヤバそうな雰囲気をまとったコードで本当に大丈夫なのか?っていう.
K.M.PEANUTS

2021/07/07 02:00 編集

kainaさんへ 課題を通して自分の理解できていないところを発見し、その都度調べている状況です。ちなみに授業では演習問題が複数題出題され、初めて使う関数なども自分で調べて問題を解かされますし、とくに模範解答も配られず、勝手にやっといてねみたいなスタイルのFランです。 本は新明解を使いました。勉強法を考え直したいと思いますご指摘ありがとうございます。
K.M.PEANUTS

2021/07/07 02:56

radianさんへ それは違うと思います。非推奨なのはあくまで"丸投げ"であって、実際にコードを書いてつまずいたところで質問するのはいいはずです。そのためにわざわざコード例を作り(これが下手でしたが)、わからないところを抜粋して質問したのですが、これもだめなのですか?ちなみに提出するものでもありません。学習目的でやっています。
neconekocat

2021/07/07 03:19

学習目的でやっているということなら、str関数を以下のように書き換えて実行してみるといいでしょう。 char * str() { char s[100]; strcpy(s, "文字列を返します。"); return s; }
退会済みユーザー

退会済みユーザー

2021/07/07 03:37

つまづくというのは、ネットや本で調べまくってデバッグしても解決しないようなレベルだと思います。この質問はそこまで試行錯誤したようには全く見えません。
K.M.PEANUTS

2021/07/07 04:27

neconekocat さん コード例ありがとうございます! 一応実行結果は正しく動作しましたが、コンパイル時にwarningでaddress of stack memory associated with local variable 's' returnedと表示されました。これは、関数内で定義したchar型配列をreturnしているのがあまり良くないということでしょうか?
neconekocat

2021/07/07 04:33

それは運悪く、正しく動作しているように見えてるだけです。 関数を抜けた時点で変数はスコープを外れるので値は不定となります。 なんならその領域を再利用される危険もあります。
K.M.PEANUTS

2021/07/07 04:43

radianさん > つまづくというのは、ネットや本で調べまくってデバッグしても解決しないようなレベルだと思います。 あなたの感覚で喋ってますか??? 学校が出題してきた問題を質問したから怒ってるのですか? 質問のレベルが低いから怒ってるのですか? 書籍に書いてある問題で質問した場合はいいのですか? 出題元と質問にどのような関係があるのですか?
fana

2021/07/07 04:51

> スコープを外れるので値は不定となります。 × スコープを外れるので 〇 生存期間がおわるので
退会済みユーザー

退会済みユーザー

2021/07/07 05:40 編集

別に怒ってはいませんが、もし色々試行錯誤した上での質問であれば、誤解されないような質問文に編集してください。(〇〇という記事を読み、〇〇のサンプルコードを試したが、〇〇という部分が理解できなかった等) コンパイルすら通らないコードがポンと置いてあるだけだと、丸投げなんだろうなぁと判断せざるを得ないです。 出来れば、下記リンクのページの内容に一通り目を通してください。 [質問するときのヒント] https://teratail.com/help/question-tips
kazuma-s

2021/07/07 08:17 編集

"文字列を返します。" は静的なオブジェクトであり、生存期間はプログラム開始から終了までです。 自動変数と勘違いしているコメントをしている人はもっと勉強してください。
neconekocat

2021/07/07 08:23

kazuma-sさん 私に対するコメントかな? 質問者が本来のコードではstrcpyが必要なものもreturnしていますと言っているのでそれは無理だよって言ってるだけですけども
fana

2021/07/07 08:52

生存期間の話は > neconekocat 2021/07/07 12:19 からの流れで出てきているんだが.
guest

回答5

0

文字列リテラルだけを返すのなら、関数 str のように単純にreturnして大丈夫です。(返り値の型は const char* がいいだろうとか str の後に(void)が無いとかの問題はありますが)

文字列リテラルではない文字列を返すなら、一般的には snprintf()strcpy_s() のように結果を入れるバッファとバッファのサイズを引数として渡します。

引数で指定できない場合は、

  • strdup() のように、malloc()した領域を返して呼び出し側で free() してもらう
  • スレッドセーフである必要がないのであれば、大域変数の配列や static な局所変数の配列に文字列を格納してそのアドレスを返す。

などが考えられます。


クラッシュしているのは、a[10] のサイズが足りないからです。文字コードが UTF-8 だとすると、9 * 3 + 1 で28バイトは必要です。

投稿2021/07/07 01:01

編集2021/07/07 07:09
int32_t

総合スコア21695

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

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

rubato6809

2021/07/07 06:52

> クラッシュしているのは、a[10] のサイズが足りないから 私の見立ても同じです。 質問者は char a[10]; を char a[60]; 位に修正して試してみるべきだと思います。 ただし修正は他にも必要で #include <stdio.h> #include <string.h> の2行を追加したうえで、 「char* str {」 を 「char* str(void) {」 としなくてはなりません。 質問のコードはコンパイルが通らないので「zsh trace trap ./a.outというエラーが出てしまい…」となる以前の話です。質問する時に、ここで手書きしたからでしょう。 そうではなく、実際にコンパイルしたソースコードをコピペすればよかったのです。 基礎を学んでいる段階の人が、ここで手書きするなど、10年早い(実際は1年位かなw)。
guest

0

質問に対する回答ではないですが、すんごい気になったので衝動的(?)に書いています。


まず、プログラミングは「こう書けばいい」ではないです。

プログラムは魔法でもなんでもなく、人間が現実世界でやっていることを逐一指示されながら処理しているだけの代物である』です。

コンピュータの歴史を学べばわかります。

※ 以下の歴史はあくまで概要レベルで、所々間違っている可能性があります。(趣味&独学なので)
詳しい事はご自分で調べてください。

元々は軍事利用でした。

たとえば弾道計算や暗号解読とかです。

暗号解読とかは人間が手作業でも一応できます。

ですが非効率ですし、現実的ではないです。

暗号方式や時代によっては、たかだか『Hello』の5文字ですら、
1週間とか1カ月はかかります。
(厳密にはそこまでかからなくとも、「非効率だなぁ」と感じる程度にはかかる)

ましてや戦時中。
情報と速度が重要な局面でちんたらと暗号解読しているのは非効率にもほどがあります。

そこでコンピュータに任せようという発想に。

でも機械は0と1からなる機械語(machine language)しか認識できません。

1100111000101101010110101100111011010101...

のような感じですね。(あくまでイメージ)

人間にとっては面倒なのでアセンブラとかのような、比較的人間の言語に近い言語が開発されました。

でも問題があったので、C言語とかのような構造化プログラミングとかが開発されましたが
まだ問題があったので、Javaとかそういうオブジェクト指向の言語が開発され……

というような感じです。

つまり、「人間が面倒だと思う処理」を『現実世界でやっている手順を独自の書き方』で書き下しているだけです。

創作料理のレシピを書く感じでしょうか。

なので、

そこにstrcpyを使った理由はなんですか?と聞くのは意味のない質問です。『strcpyではなくchar *a = strと書けばうまくいく』というのを後出しではなく最初に言っていただければ、

は根本から考え方が間違っていて、ともすれば逆ギレです。

それに、回答者は質問者と同じ環境にある……わけじゃないです。

提示された情報からしか読み取れません。

質問者さんは他人の考えや感情を本人から言われなくてもすぐにわかるのでしょうか。

もちろん仕草(鼻の上を掻くとか、口元を隠すとか、眉を顰めるとかのような)とかで判断することは出来ますが、そういう表面上に現れるタイプではなく、本当に見えない部分です。

対面してもこれです。

ましてやネットを介してのものであれば「わかるはずがない」です。

提示された情報からしか読み取れません。

それを『言わなくてもわかるだろ』はもはや暴言レベルです。

課題を通して自分の理解できていないところを発見し、その都度調べている状況です。ちなみに授業では演習問題が複数題出題され、初めて使う関数なども自分で調べて問題を解かされますし、とくに模範解答も配られず、勝手にやっといてねみたいなスタイルのFランです。 本は新明解を使いました。勉強法を考え直したいと思いますご指摘ありがとうございます。

いや、Fランとか関係ないです。

独学もほぼ同じ。
むしろ独学の場合は『ネタ自体も自分で仕入れないといけない』です。

学校とかの場合は学校側とかが「これやってきてね」とやっているだけマシです。

関数は学ぶものではないです。

公式リファレンスとかがあるので、それで調べます。
(C言語の場合は公式としては無いようだが、有志が色々出しています)

例: 例1

英単語とかと一緒です。

「僕、学校でその単語習っていないからわかんないの~」なんて言いますか? 会話時に?

単なる言い訳にしか見えません。

本当に会話したいなら辞書を引くなりして調べます。

最近ならGoogleとかで検索かけても普通に出てきます。

それは違うと思います。非推奨なのはあくまで"丸投げ"であって、実際にコードを書いてつまずいたところで質問するのはいいはずです。そのためにわざわざコード例を作り(これが下手でしたが)、わからないところを抜粋して質問したのですが、これもだめなのですか?ちなみに提出するものでもありません。学習目的でやっています。

それなら「質問方法を工夫すべき」でしょ?

いくら初心者だからと言って、工夫できないわけではないです。

たとえば、「どんなふうに調べた」「参考にしたサイトのURL」
「自分なりのコード」(これはある……みたいだね)
「どうなれば正解なのか」「どうなってしまうのか」とかみたいなものを書くだけでもだいぶ印象が違います。

[質問例1] (自分なりのコード) とやりました。 (やりたいこと)をやりたいのですが、(エラーメッセージ)というエラーが出ました。 どうやればいいでしょうか。

と、

[質問例2] (自分なりのコード) とやりました。 (やりたいこと)をやりたいのですが、(エラーメッセージ)というエラーが出ました。 どうやればいいでしょうか。 試したこと: 1. コード上の問題だと思い、(自分なりに試したこと)としました → 結果は変わらず 2. コード上の問題だと思い、(試したこと)としました → そもそもコンパイル自体が通らない( エラーメッセージ ) 3. 環境の問題かと思い、(試したこと)としました → 結果は1と同じ

のようなもの、どちらが回答しやすいでしょうか。

プロだからと言って、すぐに答えがわかるわけではありません。

今回の場合は比較的わかりやすいものですが、物によっては1週間調べたら単にスペルミスだった……ということもあるのです。

でも質問例2 のように「試したこと」等を書くだけでも可能性を潰していけます。
「この可能性はないな、この可能性もない……とすると……もしかしてこれじゃないか?」と。

でも質問例1だと、「全ての可能性を考慮しなければならない」です。

もしかしたら環境(OSの設定とか) によるものかもしれない。
相当な数の可能性があります。

回答者はPCやケータイに一日中張り付いているわけじゃないです。
サポートセンターですら休みはあります。

ましてやプログラマやSEは「考える事」と「調べる事」が仕事です。
それなのに考えることも調べる事も放棄しているので、

『ggれ(ry』とかのような暴言チックなことも言われるのです。
(今回はそういうのは無いですが)

私は当人ではありませんが、

あなたの感覚で喋ってますか???

学校が出題してきた問題を質問したから怒ってるのですか?
質問のレベルが低いから怒ってるのですか?
書籍に書いてある問題で質問した場合はいいのですか?
出題元と質問にどのような関係があるのですか?

これは前提が違います。

出題元を提示すべきなのは、『欠けている情報がある』か「何となく前提である問題がおかしい」というとかの可能性もあるからです。

参考書や入門書とかはすべてが正しいわけではありません。
誤字脱字は当たり前のようにあります。

だから書籍でも『正誤表』とかが付いていたりするのです。

質問のレベルが低い事自体は問題ではありません。

問題なのは『質問方法を工夫しない事』です。

上で挙げた例(質問例2)のように、ほんのちょっとの工夫(工夫っていうレベルでもない)だけでも、
相当印象が変わりますし、質問者さんの力量もわかる。

単に『わからない』では、『何がわからないのかが不明瞭』です。

私ら回答者は質問者さんの先生でもないし、知人ですらないです。

先生ならその生徒の得意・不得意とかもわかっていることが多いです。
(つーか、わからないと教えられんだろ……)

でも回答者は赤の他人です。

提示された情報からしか読み取れません。

仮に調べた・試したとしてもそれは赤の他人のことなので『言われないと』わからないです。

書籍に載っている・載っていないではないです。

学校の課題について質問する事自体は問題ありません。
(後が面倒な気がしないでもないが、質問方法を工夫さえすればマシに見えるし)

問題なのは『質問方法を工夫しないこと』です。

※ 書いておきますが、私は怒ってはいません。あくまで意見を書いているだけです。

投稿2021/07/07 06:56

BeatStar

総合スコア4962

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

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

K_3578

2021/07/07 07:05 編集

(回答について思ったのでこのコメントも衝動的に書いてます。) teratailヘルプの「質問するときのヒント」に、書いてある内容がほぼ同義だと思います。 ヘルプすら自分から見ない、探さない人はよく「初心者だから、teratailを初めて使ったので」 と言いますが普通サービス利用するならガイドラインの一つぐらい探すと思うんですけどね。 自分自身の怠慢を「初心者」という言い訳で逃げないで欲しいものですが。
BeatStar

2021/07/07 07:13

> teratailヘルプの「質問するときのヒント」に、書いてある内容がほぼ同義だと思います ですね。 ですが、ここまで書かないとそもそも理解できないっていう人が多すぎるので…… わかりやすいエラーメッセージを読んでも『エラーが出た(泣』とかっていう風に思考停止したり、 エラーメッセージの意味はわかるけど『対処がわからない』(= 手取り足取り教えてもらわないとわからない) 人が多すぎです。 『変数 a 未定義』系のエラーが出たら「変数 a を定義すればいい」と言われないとわからないっていう感じの。 なので書きました。
guest

0

何でわざわざ「引数は無しね」とかいう縛りプレイしてるのかわからんですが,
何かもう面倒なので文字列はstructに包んだ形にして返す形にでもすればいいんじゃない?
「リテラルを指すポインタ値」を返すことに特別こだわる必要はないだろうし.

  • バッファサイズは{関数,関数呼び出し側}両者で既知だから,質問文がやってるようなバッファサイズ不足の問題とかは起きないっしょ.
  • メモリを動的確保 とかいう面倒な話もしなくていいっしょ
  • 受け取った文字列は常に「コピー品」になるから呼び出し側で好き勝手にいじくろうがOK

C

1#define XXXSTR_BUFFSIZE 10 2 3typedef struct XXXStr { char Str[XXXSTR_BUFFSIZE]; } XXXStr; 4 5XXXStr GetXXXStr() 6{ 7 XXXStr Ret; 8 strcpy( Ret.Str, "Catnap" ); 9 return Ret; 10} 11 12int main(int argc, char *argv[]) 13{ 14 XXXStr S = GetXXXStr(); 15 printf( "%s\n", S.Str ); 16 17 return 0; 18}

投稿2021/07/07 02:29

fana

総合スコア11996

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

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

neconekocat

2021/07/07 06:56

個人的にこのやり方好きです。 見た目はOOPチックなのにやってることは完全なディープコピーというギャップがいい。
fana

2021/07/07 07:09 編集

要素数が固定の配列データを受け渡すような場合には,私はこの方法を好みます. 特に配列が多次元で,関数の引数に渡すとかの場合, struct Matrix{ double V[3][3]; }; みたいなのを引数に渡す方がすっきりするとか思っています. (内側の配列変数の妥当な変数名って何だろう? という悩みは生じる)
guest

0

自己解決

『ある関数から文字列を返してmain関数内で表示するプログラムを書きたい』という希望は、strcpyではなくchar*型変数に直接代入することで解決しました。
strcpyを使わなければ不都合が起きると勘違いしていましたが、実際は使わなくても問題ありませんでした。

c

1strcpy(a, str());

c

1char *a = str();

と書き換える。
aの指している先は今後書き換えることのない文字列です。

投稿2021/07/07 01:30

編集2021/07/07 07:52
K.M.PEANUTS

総合スコア40

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

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

neconekocat

2021/07/07 01:38

いやあのそれ根本的な解決になってませんよ。 > 本来のコードではstrcpyが必要なものもreturnしています。 これ返せないし。
fana

2021/07/07 02:05

まぁ, ・関数の戻り値の型は char* なのであって ・それを受け取るための関数呼び出し側の記述を書く という話としては最も素直な形ではある. (その他のいろんな事柄については,ここではとりあえず考慮外である,とするならば)
fana

2021/07/07 03:16

低評価理由をちゃんとコメントして欲しい場面ですね. (この状況で無言低評価が2つ入ってると,まるで私たちが入れたかのように見えるね)
Zuishin

2021/07/07 03:43

低評価してないけど、どのような問題が解決したのかさっぱりわかりませんね。 「書き換えた」という作業のみ書かれていますが、この質問の主旨は、 > c言語で、関数から文字列を返す方法がわかりません。 で、問題点は、 > zsh trace trap ./a.outというエラーが出てしまいうまく行きません。 だったはずです。
fana

2021/07/07 04:46 編集

> 関数から文字列を返す っていう場合,いろいろと考えなきゃならないことがあると思うのね. ・そもそも「文字列」って何だろう?  C言語にはそのものズバリな「文字列」っていう型は無いわけだけど,じゃあ関数はどんな型を返すことになるのかな? ・ポインタを返すってことは,ポインタを介して「文字列」のデータにアクセスされるってことだ.そうすると  ・ポインタが指す先にあるデータを書き換えられるかもしれないが,それはOKなのかな?   ・ポインタがリテラルを指す可能性があるならまずいんじゃないのかな?   ・ポインタが指す先の領域の大きさを返された側では知る必要はないのかな? どうやって知るのかな?  ・ポインタが指す先の領域は,アクセスされる時点で有効である(存続している)必要があるんだけど,どうやってそれを担保するのかな? 等々. そこら辺の話を吟味した上で,「char *a = str(); でいいじゃん」っていう結論になってるなら良いんだけど. 「関数から文字列を返す」の実装として, 【戻り値が char* 型な関数】ってのは,結構な但し書きを添えてやる必要がある形だと思うよ.
fana

2021/07/07 04:40 編集

で,他の回答とか「質問への追記・修正、ベストアンサー選択の依頼」のところで malloc char* const char* 大域変数 関数内static変数 構造体 とかいういろんな話が出てきてるのは,こういった考慮事項をどうするのか?っていうのを考えたらいろいろな方法があり得るよね,っていうこと. なので,それぞれの方法の良し悪しとかを比較なり考えてみるなりすると良いと思う. 「引数無しで」というのが,課題で指定された条件なのだとしたら,そういった諸々を{考える,把握する}ことが狙いだろうと思う.
K.M.PEANUTS

2021/07/07 04:53

fanaさんたくさんの回答ありがとうございます。 いろいろ吟味しなくてはならないことがあるようですが、正直そこら辺の話はまだ聞いたことがなく、よくわかっていません。初学者でもその辺を全て理解しながら学習するものなのでしょうか?fanaさんがどのようにC言語を学んでいったかわからないのですが、自分の大学の授業、読んだ初心者向けの本には『細かい比較・起こり得ることへの対処』についてはまだ触れていません。どの段階で考慮に入れていくものなのか教えてください。
Zuishin

2021/07/07 04:54

> 初学者でもその辺を全て理解しながら学習するものなのでしょうか? 基礎なので当然です。
fana

2021/07/07 05:01 編集

> > 関数から文字列を返す > > っていう場合,いろいろと考えなきゃならないことがある ので,「せっかくだから俺は関数から文字列を返すぜ」っていう話に取り組む時点で,【理解しとく必要がある事柄】になります. つまり,前提知識なのであって,関数から文字列を返すような課題に取り組むよりも前の段階で学ぶべき事柄です. 仮に授業なりでいきなりこの課題が出たとしたら,「勝手に必要なことを勉強してこの課題をクリアしろ」ってことになりますかね.
dodox86

2021/07/07 05:12

私も本回答に低評価はしていませんが、正直、釈然としないものを感じた者のひとりです。 質問者さんを責めている訳ではなくて書くのですけれど、どうも誤解されていることにteratailは目の前の困ったことを解決してくれるただのQ&A、お助けサイトではないはずです。質問者さん側の事情があって、提案された多くの新しいことはまだ理解できないのでとりあえずスキップしたいと言うのは分からなくもないですが、それで話が終わるとあとで読んだ第三者にとってこの質問・回答は技術的に何ら価値の無いものになってしまうのです。反対に、その辺りを踏まえて質疑応答が重なれば質問内容自体が初心者・基礎的なことでも価値のあるものになるのだと思います。 [teratailについて知りたい] https://teratail.com/help#about-teratail > teratailは技術に興味のある人達が集まって、質問と回答を通してお互いに知識や情報を交換・共有する場所です。
neconekocat

2021/07/07 05:14

Cで文字列に関わる関数はほぼ全てが引数としてchar *ポインタを要求していることに疑問を持ちませんか? 今回の質問(引数なしで文字列を返す)というのはC言語ではなかなかに恐ろしい事を言っています。 初学者だから知らない分からない、では許されない領域に足を踏み込んでます。
K.M.PEANUTS

2021/07/07 05:22

> 基礎なので当然です。 まだその基礎を学んでる途中なのですが、、 あなたは初めからこれらのことについて全て考慮しながら関数を使っていたなら、素晴らしい勉強法だと思います。なにでこれらを知ったのか教えてほしいです。
退会済みユーザー

退会済みユーザー

2021/07/07 05:28 編集

そもそも、このサイトは一応エンジニア向けQ&Aサイトを謳ってるんですよね。 入門書レベルの基礎は出来ている前提なのです… 段階を踏んだ丁寧な指導を受けたいのであれば、Menta等のWebで先生をして貰うサービス等もありますので、そういったサイトを活用されてはいかがでしょうか。
Zuishin

2021/07/07 05:34

> 全て理解しながら学習するものなのでしょうか? への返信です。 「初心者は理解しなくて良いのではないか?」という疑問に見えるので、「初心者も当然理解すべきだ」と言っています。 基礎を学んでいる途中なら、後回しにせず学んでください。 このようなメモリの扱いは、基礎中の基礎と言っても過言ではありません。C 言語が難しいと言われるゆえんです。
Zuishin

2021/07/07 05:35

> なにでこれらを知ったのか教えてほしいです。 ちゃんとした入門書なら書いてあるはずです。
K.M.PEANUTS

2021/07/07 05:35

>>Cで文字列に関わる関数はほぼ全てが引数としてchar *ポインタを要求していることに疑問を持ちませんか? 今回の質問(引数なしで文字列を返す)というのはC言語ではなかなかに恐ろしい事を言っています。 初学者だから知らない分からない、では許されない領域に足を踏み込んでます。 これは学校の課題から抜粋してきたもので、本来はchar*型の関数で引数は構造体配列*が1つ、char*が1つ、intが2つの計4つで指定されているものです。しかし、引数のchar*が指している先の文字列を書き換えられないため(プログラムに不都合が起きる)、ある一部の場合で文字列を直接返さなければなりませんでした。 よく先生も『本当はこのプログラムあんまり良くないんだけど』と言いながら問題を出しているので、初心者が理解を深めるために実際はタブーなコードが使用されることも多々あることを知ってもらえたら幸いです。
dodox86

2021/07/07 05:38

> よく先生も『本当はこのプログラムあんまり良くないんだけど』と言いながら問題を出しているので、初心者が理解を深めるために実際はタブーなコードが使用されることも多々あることを知ってもらえたら幸いです。 そういうことがあるのは回答者側の多くは経験上知っているので、そのことを最初に断わりとして述べていたら話の成り行きはまた違っていたと思いますよ。
fana

2021/07/07 05:43

> 今回の質問(引数なしで文字列を返す)というのはC言語ではなかなかに恐ろしい事を言っています。 C言語の範疇でこれより面倒な話って何があるかな? って考えると なかなか思い当たらないなぁ……って感じですね.
退会済みユーザー

退会済みユーザー

2021/07/07 05:47 編集

正直なところ、課題を出した人に聞くのが一番いいと思いますけどね。授業でどこまで教えてるかと、課題の意図を一番理解している筈なので。 自分で調べたりコードを考えさせる事で授業を理解出来ているかの確認や、理解を深めたりするために課題を出している筈なので、課題のプログラムを動かす事を目的にしない方がいいです。そうじゃないと、何も理解出来ないまま、授業が先に進む事になります。
K.M.PEANUTS

2021/07/07 05:57

> そういうことがあるのは回答者側の多くは経験上知っているので、そのことを最初に断わりとして述べていたら話の成り行きはまた違っていたと思いますよ。 次からそうしようと思いました。ありがとうございます。
fana

2021/07/07 06:03

勉強目的で取り組んでいるなら,ここで出てきた単語の中に知らないものがあったならば,それは収穫ですよね. これらは必要な学習の筋道を示しているとも言えるわけで, リストアップしてかたっぱしから調べてみると良いんじゃないかな. (こっちも「生存期間」みたいな語を意図的に出している面もある)
Zuishin

2021/07/07 06:04

質問の補足があったとしてもこの回答は意味不明なので、まず何を質問しているのかからはっきりさせ、その回答となるように整えてください。
Zuishin

2021/07/07 06:42

難しければ問題点を整理しましょうか? まず質問は、 > c言語で、関数から文字列を返す方法がわかりません。 ですが、文字列の返し方について何も言及されていません。 ここで述べられているのは「返された文字列の扱いを strcpy を使わないよう変更した」ということだけです。これにより、質問と回答にズレが生じています。 これが一点。 また追記修正依頼では strcpy が必須と書いてあり、この方法では解決できません。 これが一点。 さらに、もう一つの問題は実行時エラーです。 これは strcpy の複写先のサイズが小さすぎたことにより起きています。 そのため、strcpy を使わなければ結果的にエラーは出なくなりますが、int32_t さんの書かれたように十分な大きさのバッファサイズをとることにより解決できます。 これが一点。 呼び出すと定数の文字列を返す関数を作るようなことは、特殊な用途を除いてまず無いと思いますが、それはそれとしてこの戻り値は fana さんの書かれたように「いつ解放されるかわからない」「書き換えてはいけない」などの問題点があり、書き換えることが考えられるなら strcpy を使うべきです。 これが一点。 このように「質問の答えになっていない」「質問の条件を満たしていないため解決できない」「アンチパターンである」などの複数の問題が含まれていて、今現在最も高評価されている int32_t さんの回答を排してベストアンサーに選ばれるようなものではありません。 低評価で当然だと思いますが、すでに複数の低評価がついていることから、私は低評価していません。 しかし、やり取りを見るとこのまま放置されそうな気がするので、どういう質問か(文字列の返し方が知りたいのか、エラーの修正がしたいのか、その両方か)が確定し、既存の回答よりも良質な回答に編集されるまで低評価することにします。
BeatStar

2021/07/07 07:09

他の方々もおっしゃっている通りです。 この"解決した方法"はあくまで今回のエラーを回避するだけの「場当たり的」で『根本的解決には至っていない』です。 私なら『なーんで、char* (ポインタ)で返すんだろう…』とか疑問に思いますし。 根本的解決をしていないから次も似たような問題に直面して『わからない』となるでしょうね。
K.M.PEANUTS

2021/07/07 07:55

> int32_t さんの書かれたように十分な大きさのバッファサイズをとることにより解決できます。 一瞬解決したように思えたのですが、同じ内容のエラーが表示されてしまいました。理由はまだわかっていません。
neconekocat

2021/07/07 07:57

十中八九、不定になった値をコピーしようとして膨大な文字列扱いになったんでしょうね と思ってたり
int32_t

2021/07/07 08:02

> 同じ内容のエラーが表示されてしまいました いま作業しているコードをそのまま質問文に入れたほうが良いです。 余計な情報がいっぱいあって長いコードは、大事な情報を削った短いコードより遥かにマシです。
BeatStar

2021/07/07 08:08

質問者さん。 int32_tさんが仰っているように『情報をちゃんと出しましょう』です。 提示されたコードだけだとわからないことがあります。 たとえば『提示されたコード"以外"での部分でエラーが発生している』とかです。
guest

0

大域変数に配列を確保して、関数内で返したい形に加工して、それのアドレスを返せばいいんじゃない?

投稿2021/07/07 01:15

WoodenHamlet

総合スコア306

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

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

fana

2021/07/07 01:34

関数内の static な配列とかでもいいかもですね.
WoodenHamlet

2021/07/07 02:05

そうですね。ただ、関数内の static な変数が外で弄られるかもしれない状態にするというのは、すこし好みが分かれる所かとは思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問