関数の戻り値

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
メッセージ
作成者
卓漏
記事: 32
登録日時: 2005年11月30日(水) 06:38
お住まい: 静岡県の田舎町

関数の戻り値

#1 投稿記事 by 卓漏 »

下のようなプログラムを作ったのですが、
関数内では、正しく値を表示できるのですが、
関数から戻ってきた値が正しく表示されません。
誰か教えてください。

コード: 全て選択


Print makePtr(x)
End

Function x() As *char
    Dim Str$ As String
    /* 何らかの処理 */
    Print Str$
     x = StrPtr(Str$)
End Fuction
[/code]
C1000
記事: 185
登録日時: 2006年5月07日(日) 17:16
お住まい: 宮城県
連絡する:

Re: 関数の戻り値

#2 投稿記事 by C1000 »

エラーなどがでていたらここに書いてください。
あとコードのミスを発見したので書いておきます。

コード: 全て選択

Print MakeStr(x)
End

Function x() As *char
    Dim Str$ As String
    /* 何らかの処理 */
    Print Str$
     x = StrPtr(Str$)
End Function
卓漏
記事: 32
登録日時: 2005年11月30日(水) 06:38
お住まい: 静岡県の田舎町

#3 投稿記事 by 卓漏 »

エラーは出ないのですが、文字化け状態で表示されます。

あと、コードをミスしていましたが、それが原因ではありません。(恥)
C1000
記事: 185
登録日時: 2006年5月07日(日) 17:16
お住まい: 宮城県
連絡する:

#4 投稿記事 by C1000 »

StrPtrは簡単に言うとString型をBytePtrに変換する関数なので*charではなくBytePtrにしてみてください。(*charってABで定義無いような気が・・・)
最後に編集したユーザー C1000 [ 2006年6月07日(水) 20:41 ], 累計 1 回
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#5 投稿記事 by イグトランス »

xの呼び出しに関数呼び出しの()がありませんが書き写し間違いでしょうか。

String型は文字列のメモリの管理をしてくれますが,ポインタ型はそうではありません。
そのため,関数xを抜ける際に変数Str$の中身の文字列のメモリが解放されてしまっています。

特に事情が無ければxがString型を返すようにすれば良いのですが,そうできない事情でもあるのでしょうか?
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

#6 投稿記事 by NoWest »

この問題は関数をよく理解していないとやってしまうポカの1つです。

まずはローカル変数とグローバル変数についてよく理解してください。
関数内で宣言された変数はローカル変数ですよね。
ローカル変数は基本的に関数を抜けた時点で消滅しますので
消滅する変数へのポインタを関数の戻り値に指定するとどうなるか考えてみてください。

P.S.
イグトランス様に先を越されたようですね。

イグトランス様が仰っているのは

コード: 全て選択


Function x() As String
    Dim Str$ As String
    /* 何らかの処理 */
    Print Str$
    x=Str$
End Function
ってことです。

どうしてもポインタを返したいなら

コード: 全て選択


Function x() As *Char
    Dim pStr As *Char
    pStr=calloc(256)
    /* 何らかの処理 */
    Print MakeStr(pStr)
    x=pStr
End Function
この場合、x()関数が返したポインタをfree()で解放しないといけなくなります。
cdecl形式の関数であればスタックは呼び出し側が始末するので
後で解放しなくてもよいものができそうですが。。。
最後に編集したユーザー NoWest [ 2006年6月07日(水) 20:51 ], 累計 3 回
C1000
記事: 185
登録日時: 2006年5月07日(日) 17:16
お住まい: 宮城県
連絡する:

#7 投稿記事 by C1000 »

自分もポカしてましたね(恥)直し方はわかりましたがわりと簡単なのでここには書きません。
卓漏
記事: 32
登録日時: 2005年11月30日(水) 06:38
お住まい: 静岡県の田舎町

#8 投稿記事 by 卓漏 »

BytePtr型を使ってもだめだったので、
「NoWest」さんのコードを参考にして、「String型」から強引に「*char型」に変換する関数(StrToChar)を作って組み込んだところ、問題が解決しました。

コード: 全て選択


Print MakeStr(x) 
End 

Function x() As *char 
    Dim Str$ As String 
    /* 何らかの処理 */ 
    Print Str$ 
     x = StrToChar(Str$)
End Function 

Function StrToChar(Str$ As String) As *char
	Dim I As Integer, Max As Long
	Dim pStr As *char

	Max = Len(Str$)

	pStr = calloc(Max + 1)

	For I = 1 To Max
		pStr = Asc(Mid$(Str$, I, 1))
	Next I
	
	StrToChar = pStr
End Function
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#9 投稿記事 by イグトランス »

コード: 全て選択

For I = 1 To Max
    pStr = Asc(Mid$(Str$, I, 1))
Next I

この部分はもっと簡単に,これだけで済みます。そしてこの場合callocはmallocで置き換えられます。

コード: 全て選択

memcpy(pStr, StrPtr(Str$), Max + 1)


また,callocで確保したメモリはfreeで解放すべきです。

コード: 全て選択

Print MakeStr(x)
End

これを(たとえば)こうします。

コード: 全て選択

Dim pStr As *Char
pStr = x()
Print MakeStr(pStr)
free(pStr)

End

もう1度言いますが,私なら関数xがString型を返すようにします。
こんなfreeしなければならないなんて面倒くささは受け入れられませんから。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

#10 投稿記事 by NoWest »

私もどうしてポインタを返す関数を作りたいのか知りたいですね。

自分だけで使う関数なら、ポインタを返す関数を作ってもよいと思いますが
他の人に公開するライブラリの一部などであれば勿論のこと
「3日も経てば他人のソース」という格言のように自分でも混乱しかねません。

文字列操作の関数であれば外部から目的の文字列バッファを引数に与えてやるのが
基本だと思います。
卓漏
記事: 32
登録日時: 2005年11月30日(水) 06:38
お住まい: 静岡県の田舎町

#11 投稿記事 by 卓漏 »

> 私もどうしてポインタを返す関数を作りたいのか知りたいですね。

↑作った理由は、たいした理由では無いです。
昔、研究していた「スパゲッティプログラム」と「プログラム方言」を、もう一度、初めから研究するためです。
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#12 投稿記事 by konisi »

研究対象がスパゲッティプログラムか。どういうレポート結果になったの?
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
卓漏
記事: 32
登録日時: 2005年11月30日(水) 06:38
お住まい: 静岡県の田舎町

#13 投稿記事 by 卓漏 »

>研究対象がスパゲッティプログラムか。どういうレポート結果になったの?

↑痛いところを衝かれました。実言うと、レポートとかは残っていません。

昔、「スパゲッティプログラム」を研究していたのですが、仕事で忙しくなり、
挫折したためです。
でも最近、プログラムの「方言」が、「スパゲッティプログラム」を生み出す原因のひとつになっていそうだな・・・・。と思ったので、また一から研究を始めたわけです。

と言うか、レポートとか文学は苦手です。
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#14 投稿記事 by konisi »

CやJavaを始めとするほとんどの高水準言語にはスパゲッティープログラムの元になるgoto文が用意されてます。

覚えてる限りでは、COBOL(事務処理系)やForTran(科学技術系)等のやつらでgoto文あるいは同等の働きをする文が用意されていたような・・・。


低水準言語なら、アセンブリ言語ならjmpとかマシン語なら0xE9~0xEBと0xFFがgoto文と同じ働きをします。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#15 投稿記事 by イグトランス »

そんなCとかJavaとか持ち出さなくても,Goto付きのプログラミング言語なら目の前にあるでしょう,Basicが。
そういえば最近めっきりGotoを使う機会がありませんね。それでよいのでしょうけど。

PS 記念すべき400件目の投稿になりました。これからもみなさんよろしくおねがいします。
返信する