ページ 1 / 2
関数の戻り値
Posted: 2006年6月07日(水) 20:05
by 卓漏
下のようなプログラムを作ったのですが、
関数内では、正しく値を表示できるのですが、
関数から戻ってきた値が正しく表示されません。
誰か教えてください。
コード: 全て選択
Print makePtr(x)
End
Function x() As *char
Dim Str$ As String
/* 何らかの処理 */
Print Str$
x = StrPtr(Str$)
End Fuction
[/code]
Re: 関数の戻り値
Posted: 2006年6月07日(水) 20:12
by C1000
エラーなどがでていたらここに書いてください。
あとコードのミスを発見したので書いておきます。
コード: 全て選択
Print MakeStr(x)
End
Function x() As *char
Dim Str$ As String
/* 何らかの処理 */
Print Str$
x = StrPtr(Str$)
End Function
Posted: 2006年6月07日(水) 20:32
by 卓漏
エラーは出ないのですが、文字化け状態で表示されます。
あと、コードをミスしていましたが、それが原因ではありません。(恥)
Posted: 2006年6月07日(水) 20:38
by C1000
StrPtrは簡単に言うとString型をBytePtrに変換する関数なので*charではなくBytePtrにしてみてください。(*charってABで定義無いような気が・・・)
Posted: 2006年6月07日(水) 20:40
by イグトランス
xの呼び出しに関数呼び出しの()がありませんが書き写し間違いでしょうか。
String型は文字列のメモリの管理をしてくれますが,ポインタ型はそうではありません。
そのため,関数xを抜ける際に変数Str$の中身の文字列のメモリが解放されてしまっています。
特に事情が無ければxがString型を返すようにすれば良いのですが,そうできない事情でもあるのでしょうか?
Posted: 2006年6月07日(水) 20:41
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形式の関数であればスタックは呼び出し側が始末するので
後で解放しなくてもよいものができそうですが。。。
Posted: 2006年6月07日(水) 20:46
by C1000
自分もポカしてましたね(恥)直し方はわかりましたがわりと簡単なのでここには書きません。
Posted: 2006年6月07日(水) 22:35
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
Posted: 2006年6月07日(水) 23:02
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しなければならないなんて面倒くささは受け入れられませんから。
Posted: 2006年6月08日(木) 14:31
by NoWest
私もどうしてポインタを返す関数を作りたいのか知りたいですね。
自分だけで使う関数なら、ポインタを返す関数を作ってもよいと思いますが
他の人に公開するライブラリの一部などであれば勿論のこと
「3日も経てば他人のソース」という格言のように自分でも混乱しかねません。
文字列操作の関数であれば外部から目的の文字列バッファを引数に与えてやるのが
基本だと思います。
こんな感じ [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
#N88BASIC
Dim buf[256] As Char
lstrcpy(buf,"ABABABA")
AtoB(buf)
Print MakeStr(buf)
'アルファベットの大文字Aを大文字Bに置換する関数
FUnction AtoB(lpstr As *Char) As *Char
If lpstr=NULL Then Exit Function
AtoB=lpstr
Dim cnt=0 As DWord
While AtoB[cnt]<>0
If AtoB[cnt]=Asc("A") Then AtoB[cnt]=Asc("B")
cnt++
Wend
End Function
Posted: 2006年6月08日(木) 19:25
by 卓漏
> 私もどうしてポインタを返す関数を作りたいのか知りたいですね。
↑作った理由は、たいした理由では無いです。
昔、研究していた「スパゲッティプログラム」と「プログラム方言」を、もう一度、初めから研究するためです。
Posted: 2006年6月08日(木) 21:29
by konisi
研究対象がスパゲッティプログラムか。どういうレポート結果になったの?
Posted: 2006年6月08日(木) 22:50
by 卓漏
>研究対象がスパゲッティプログラムか。どういうレポート結果になったの?
↑痛いところを衝かれました。実言うと、レポートとかは残っていません。
昔、「スパゲッティプログラム」を研究していたのですが、仕事で忙しくなり、
挫折したためです。
でも最近、プログラムの「方言」が、「スパゲッティプログラム」を生み出す原因のひとつになっていそうだな・・・・。と思ったので、また一から研究を始めたわけです。
と言うか、レポートとか文学は苦手です。
Posted: 2006年6月09日(金) 23:19
by konisi
CやJavaを始めとするほとんどの高水準言語にはスパゲッティープログラムの元になるgoto文が用意されてます。
覚えてる限りでは、COBOL(事務処理系)やForTran(科学技術系)等のやつらでgoto文あるいは同等の働きをする文が用意されていたような・・・。
低水準言語なら、アセンブリ言語ならjmpとかマシン語なら0xE9~0xEBと0xFFがgoto文と同じ働きをします。
Posted: 2006年6月10日(土) 00:49
by イグトランス
そんなCとかJavaとか持ち出さなくても,Goto付きのプログラミング言語なら目の前にあるでしょう,Basicが。
そういえば最近めっきりGotoを使う機会がありませんね。それでよいのでしょうけど。
PS 記念すべき400件目の投稿になりました。これからもみなさんよろしくおねがいします。