文字列変換DLL

[戻る]
Legolas 2004/01/26(月) 02:09:43
お世話になります。
レゴラスです。

intデータを文字列に変換するDLLを作っているのですが
値が空白で返ってきてしまいます。。
どなたかご教授お願いいたします。。

↓DLL側ソース

char *strValue(int vInt)
{
  char *sValue;
  sprintf(sValue,"d%",vInt);
  return sValue;
}


↓呼び出し側
int abc = 13;
char *test;
test = strValue(abc);


---
何か、根本的に書き方間違っているような
気もしますが。。(汗)
ほとんど自己流で書いています。。。
実はsprintfって使ってはダメ??(コンソールアプリだけ?)
すみません、、よろしくお願いいたしますm(__)m

!!! 2004/01/26(月) 03:03:53
> intデータを文字列に変換するDLLを作っているのですが
> 値が空白で返ってきてしまいます。。

あなたが所望する結果はどんなものですか?

13 という値の文字コードで表される文字?
それとも,"13" という文字列?


それから,

> 値が空白で返ってきてしまいます。。

これ,どうやって確認しましたか?
確認したソースコードも載せてください.


P.S.
> sprintf(sValue,"d%",vInt);

これって,sprintf(sValue,"%d",vInt);
                          ^^
のマチガイでは?
(ただの入力ミスかな?)

iijima 2004/01/26(月) 03:19:08
大きな間違いが2つと,小さな間違いが1つ.
小さな間違いから.

>   sprintf(sValue,"d%",vInt);
                   ~~~~ ここは,"%d"と書くべきです.

これを直しただけで,もしかしたら期待通りの動作をするかも知れません.
しかし,それで満足してはいけません.まだ大きな間違いが2つ残っています.

その1

>  char *sValue;
>  sprintf(sValue,"d%",vInt);

sValueはあるメモリのアドレスを指しますが,そこを先頭にした文字列を格納するメモ
リ領域は確保されていません.
sprintfで,確保されていない領域に不正に書き込んでしまいます.

    char sValue[ 100 ];
    sprintf( sValue, "%d", vInt );

これなら文字列用に100バイト確保したので,100以下の文字数なら安全です.

その2

まだ完全ではありません.
sValueはstrValue関数内のローカル変数ですから,それが指している文字列格納用のメ
モリ領域は,関数終了時に解放されます.
メモリアドレスが呼び出し元に返されてtestに代入されるので,そのメモリ領域が他に
使われる前であれば、testを使ってそこに残っているデータを参照できるかも知れませ
ん。
ただし、それはたまたまのことであり、そこのメモリ領域はいずれ別の用途に使われま
すから、その時に破綻します。
呼び出し側でも、文字列格納用のメモリ領域を確保し、それにコピーしてやる操作が必
要です。
例えば:

#include <stdio.h>
#include <string.h>

void strValue( int vInt, char* buff )
{
    char sValue[ 100 ];
    sprintf( sValue, "%d", vInt );
    strcpy( buff, sValue ); // 文字列コピー
}

    /* 呼び出し側 */
    int abc = 13;
    char test[ 100 ];      // 文字列格納のメモリ領域確保
    strValue( abc, test );


標準関数を使った操作ばかりですから、わざわざ関数を自作するまでもないように思い
ますが、練習にはなりますね。

Legolas 2004/01/27(火) 00:45:40
!!!さん、iijimaさん、レスありがとうございます。

d% → %d の間違いです。入力ミスでした。。

---

う〜ん。なるほど。。
といった感じです。
なんかC言語もJavaのような感じで書けるかなぁ〜と思って
たんですが、C++なら書けますが、C言語はまた違いますね。
混同しているようではまだ勉強が足りませんでした。。

結局どうしたかったかというと。
VC++のラウンジでこんなこと書くの失礼かと存じますが、
実はこういうことがしたかったんです。

↓↓
//Javaソース
import java.lang.*;

...

public String strValue(int vInt)
{
    return Integer.toString(vInt);
}

---
ただ上記は正しくはStringというObjectを返してますが、
これを単純に文字列(可変長の)を返したかったんです。
C++を使えば、CString?っていうのがあるみたいですが、
これをC言語でやるのは難しいんですかね。。

参照渡しではなくreturnで任意の長さの文字列へ変換
しようとしたら、C++で書くしかないんでしょうか。

もう少し調べてみます。
ありがとうございました〜

PS:
 といいつつ何かヒントがあれば教えてくださいw

PATIO 2004/01/27(火) 14:42:42
C言語でやるのであれば、関数内でメモリを確保して返すと言った事を
しないといけなくなるのではないかと思います。
桁数は、数値から計算できますから算出した桁数を使ってメモリを確保し、
確保したメモリに変換結果をセットして確保したメモリのアドレスを返せば、
実現可能でしょう。

問題なのは、確保されたメモリの後始末を関数の呼び出し側が行わなければ
ならない点です。
これによってメモリの解放漏れがおきやすくなるのは避けられません。
私が行った対策は、この関数から返却されたメモリはいらなくなったら
必ずこの関数で解放してくださいという但し書き付きで解放関数を作成して
セットで提供すると言う方法でした。
実際には解放する関数側は内部でfreeを呼んでいるだけでした。
単に注意を喚起すると言う意味合いでしかないので後ろ向きな対策ですね。

wood 2004/01/29(木) 07:57:33
あまり進められた方法ではないのですがグローバル変数を用意してそこから文字列を
取り出す方法もあるよ
変換関数は常に、グローバル変数に値変換を行い
取り出したいときは常に、そこだけ参照する
ただし使い方間違えると、あちこちで値のつぶしあいやってしまうので注意が必要です
けど

でも
こんな書き方もあるよね
char *strValue(int vInt,char *sValue)
{
  sprintf(sValue,"d%",vInt);
}


↓呼び出し側
int abc = 13;
char test[256];
test[0]='\0';
strValue(abc,&test);

tib 2004/01/29(木) 12:05:47
ブブー。

> sprintf(sValue,"d%",vInt);
→sprintf(sValue,"%d",vInt);

Legolas 2004/02/03(火) 02:07:41
[[解決]]
皆さんレスありがとうございます!

う=んなるほど。
だいぶC言語の面白さにハマってきました(笑)

私なりの答えとしてはPATIOさんのやり方でした。
ただ、やはりまだ考えが甘かったなぁと思ったのが
メモリ領域の開放ですよね。
これ全然考慮漏れでした。

とまぁ何だかんだで、まだまだ初心者ですが
もっと勉強して自分がプログラミングしていくうえで
どの手法が一番自分にあっているのか?
探っていきたいと思います。

皆さん本当にありがとうございました。
ひとまず[解決]とさせて頂きます。
失礼します

古いスレッドには追加発言できません。