マイコンにて、
C言語で浮動小数点の数値を表示するプログラムを作成しているのですが、
PRINT_OUT("123.456");
のように、文字列を直接指定した場合は正しく表示されるのですが、
sprintf()関数を用いて、浮動小数点を文字列に変換した場合、
buf char[10];
sprintf(buf,"%lf",123.456);
PRINT_OUT(buf);
とした場合はプログラムが暴走?(恐らく配列破壊を起こしていると
思われますが、)してしまい、上手く動作しません。
(但し、整数の場合は正常に動作します。)
そこで、質問させていただきたいのですが、
"123.456"のように直接文字列を指定した場合と、浮動小数点123.456
をsprintf()関数を用いて文字列に変換した"123.456"の書式に何か
違いはあるのでしょうか?よろしくお願い致します。
No.1ベストアンサー
- 回答日時:
> sprintf(buf,"%lf",123.456);
まず、double型の書式指定は %lf ではなく %f です。
%lf を使った場合の動作は未定義ですので、何が起こっても不思議ではありません(C99対応の場合はOKです)。
また、PRINT_OUT関数の仕様が不明ですので、もしかするとそこに原因があるのかもしれません。
参考URL:http://www.kijineko.co.jp/tech/superstitions/pri …
この回答への補足
>>まず、double型の書式指定は %lf ではなく %f です。
>>%lf を使った場合の動作は未定義ですので、何が起こっても不思議では
>>ありません(C99対応の場合はOKです)。
そうだったのですね。%lfが標準だと勘違いしていました。
参考URLが参考になります。ありがとうございます。
>>また、PRINT_OUT関数の仕様が不明ですので、もしかすると
>>そこに原因があるのかもしれません。
PRINTOUT関数をもう少し調べてみます。
No.2
- 回答日時:
%lfを使うと結果の小数点以下は6桁になります。
123.456000
sprintfでbufに格納すると末尾の'\0'を含めて11文字になりますからbufの長さ10文字を超えます。
なので配列破壊を起こしていると思います。
sprintfを使う前に、printfで出力してみてはどうでしょうか?
この回答への補足
>>%lfを使うと結果の小数点以下は6桁になります。
>>123.456000
>>sprintfでbufに格納すると末尾の'\0'を含めて11文字になりますから
>>bufの長さ10文字を超えます。なので配列破壊を起こしていると思います。
やはり、配列破壊の可能性が高そうですね。
bufのサイズを20に変更した所、暴走はなくなりましたが、
PRINT_OUT関数で全く表示がされていないようです。
>>sprintfを使う前に、printfで出力してみてはどうでしょうか?
これに関しては、マイコン上では、直接指定はできないのですが、
試しにWindows上で試してみたところ、正常に動作はしているみたいです。
No.3
- 回答日時:
shirayukixさんへ。
マイコンですのでprintfは実装されていないか、特殊関数を用意しないと使えないと思います。
PRINT_OUT()がUARTを制御していてRS232Cの通信経由でターミナルソフトに文字列を表示する良くある仕組みだと思います。
暴走の原因は、shirayukixさんの言われる通り配列破壊で間違いないでしょう。
linuxbeginnerさんへ。
文字列は、文字列終端'\0'までを含んだ配列サイズを確保してください。
いちいち何文字か気にしているのが面倒であれば余裕を見たサイズで確保しましょう。
名前にLinuxとありますが、Linuxが乗るような32bitマイコンならメモリサイズの余裕があると思いますが。いや、その前にLinuxが乗っているならprintfぐらい使えるようになっているはずだから・・・。もっと小さいマイコンか?
この回答への補足
>>文字列は、文字列終端'\0'までを含んだ配列サイズを確保してください。いちいち何文字か気にしているのが面倒であれば余裕を見たサイズで確保しましょう。
今後は、余裕を持たせて取ることにします。
しかし、今回、サイズを20に変更したのですが、暴走は止まりましたが、
PRINT_OUT()関数で全く表示がされませんので、PRINT_OUT()関数に原因がありそうです。
整数値なら正常に表示されるのが謎ですが。
>>名前にLinuxとありますが、Linuxが乗るような32bitマイコンなら
>>メモリサイズの余裕があると思いますが。いや、その前にLinuxが
>>乗っているならprintfぐらい使えるようになっている
>>はずだから・・・。もっと小さいマイコンか?
使用しているのはH3048という16[bit]のマイコンです。
名前には、Linuxとありますが、これはユーザ登録した当初はLinuxを使って
いたためであり、今回の質問の件とは関係がありません。ややこしくてすいません。
No.4
- 回答日時:
おそらく暴走の原因は#2で指摘されている配列要素数の不足が原因でしょうね。
ただ、書式指定が間違っていると、本当に暴走してしまう実装も組み込みではときどき見かけます。また、sprintf関数自体がフリースタンディング環境ではサポートされないため、浮動小数点数が使えないことも普通にあったりします(浮動小数点周りのランタイムをリンクすると、非常にプログラムサイズが大きくなるので)。
その辺りも問題がないか調べてみてください。
PRINT_OUTに関しては、関数またはマクロの定義をよく調べることと、
char buf[] = "123.456";
PRINT_OUT(buf);
としたときに期待した結果になるかどうかを調べて、問題を切り分けることをお勧めします。
この回答への補足
>>ただ、書式指定が間違っていると、本当に暴走してしまう実装も
>>組み込みではときどき見かけます。また、sprintf関数自体がフリー
>>スタンディング環境ではサポートされないため、浮動小数点数が
>>使えないことも普通にあったりします(浮動小数点周りのランタイムを
>>リンクすると、非常にプログラムサイズが大きくなるので)。
そうですか。書式設定辺りに注意が必要そうですね。
また、確かにライブラリを読み込むとプログラムサイズが一気に大きくなりました。
>>char buf[] = "123.456";
>>PRINT_OUT(buf);
こちらの方法も試してみたいと思います。
ご助言、ありがとうございます。
No.5
- 回答日時:
H8ですね。
残念ながらルネサスはSH2とR8Cしか経験が無いんで経験からの話は出来なさそうです。結果を見る限り、私もsprintfの浮動小数点の実装が心配ですね。
bufの内容を1バイトづつターミナルに表示させてみてはどうでしょう。
sprintf(buf,"%lf",123.456);
for( i=0; i<20 ; i++ ) {
char dump[10];
sprintf(dump,"%02x:%c\n",buf[i],buf[i]));
PRINT_OUT(dump);
}
こんな感じで。
この回答への補足
>>sprintf(buf,"%lf",123.456);
>>for( i=0; i<20 ; i++ ) {
>>char dump[10];
>>sprintf(dump,"%02x:%c\n",buf[i],buf[i]));
>>PRINT_OUT(dump);
>>}
bufの内容を1文字ずつ表示するこちらの方法も試してみたいと思います。
ご助言、ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセル関数の変わった使い方 3 2022/05/13 17:12
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- Java Java 南京錠 2 2023/02/04 11:46
- Visual Basic(VBA) VBAで、特定の文字より後を削除して残った数値を文字列に変換と特定の文字より前も削除したい 3 2022/04/15 19:21
- Visual Basic(VBA) VBA初心者です 検索した数字の行に色をつける 5 2023/02/13 14:22
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- Visual Basic(VBA) EXCEL VBAで教えてください。 1 2022/12/22 04:20
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
- Visual Basic(VBA) 【再々投稿】VBAのプログラムで動作しなくて困っています 8 2022/10/14 09:06
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
_tcscpy_s(wcscpy_s)の第二引数...
-
TCL言語で文字列検索方法を教え...
-
C言語のコンパイル時に表示され...
-
プログラムによく出てくるst...
-
引用符と二重引用符
-
AnsiStringについて
-
C++で文字列の右端から特定の文...
-
%dなどの違い
-
数字の入った配列をファイルへ...
-
文字列の最後がNULL ?
-
C言語で、ワイド文字の表示がう...
-
K&R、p.107の演算4-12の問題の...
-
括弧が含まれる文字列の括弧の...
-
文字列にある特定文字の数
-
VBを2008を用いてCSVを取り込む...
-
nullと""、\\0とEOFの違いにつ...
-
VB6.0でのバイナリデータの扱い...
-
C++で入力した文字列から数字を...
-
fgetsで配列に数字を入れる。
-
VBA-DLLの引数受け渡しについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C++で入力した文字列から数字を...
-
nullと""、\\0とEOFの違いにつ...
-
プログラムによく出てくるst...
-
%dなどの違い
-
WSH(VBS)でJSONの文字列を読み...
-
TCL言語で文字列検索方法を教え...
-
C#でstringをポインタとして渡す
-
16進数を2文字ずつ配列に格納し...
-
_tcscpy_s(wcscpy_s)の第二引数...
-
C++で文字列の右端から特定の文...
-
シリアル通信で0x00を送信した...
-
VBA-DLLの引数受け渡しについて
-
数字の入った配列をファイルへ...
-
c#で他のアプリの文字入力フォ...
-
構造体→文字列→構造体 をする方法
-
Shift_JIS(16進)を文字に変換す...
-
バイナリファイル中の日本語文...
-
C言語の課題で困っています;
-
[C++]WCHARの1文字目しか表示で...
-
VB6.0でのバイナリデータの扱い...
おすすめ情報