c言語でint配列をdoubleに変換する方法と結果の誤差について

このQ&Aのポイント
  • c言語でマイコンプログラムを作成し、int型の配列をdoubleに変換する方法について説明します。
  • プログラムを記述してテストした結果、期待した結果とは異なる値が出力される現象が発生しました。
  • Visual Studio 2013 C++で同様のプログラムを実行すると、正しい結果が得られたため、原因はプログラムの問題ではなくマイコンのコンパイラのバグの可能性があります。
回答を見る
  • ベストアンサー

c言語でint配列をdoubleに変換

c言語でマイコンプログラムを作成しています. int型の配列をdoubleに変換するために以下のプログラムを記述し,テストしました. int a[4] = {0,0,1,8}; char s[4]; double d; char *temp; sprintf(s,"%d%d%d%d",a[0],a[1],a[2],a[3]); //文字列charをdoubleに変換 d = strtod(s,&temp); 望む結果は 18 ですが,なぜか上記結果は 1800 となりました. 試しに int a[4] = {1,2,3,4}; と,1234と表示されました. 上記より,出力値が左詰めのようになっています. 試しにVisual Studio 2013 C++で同様のプログラムを実行すると,所望の結果を得ることが出来ました. プログラムがおかしいのでしょうか?それともマイコンのコンパイラのバグでしょうか? お分かりになられる方がいらっしゃいましたら,ご教授宜しくお願い致します.

質問者が選んだベストアンサー

  • ベストアンサー
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.4

> char s[4]; > sprintf(s,"%d%d%d%d",a[0],a[1],a[2],a[3]); こういうケースだと一般的には sprintf() じゃなく snprintf() 使うんだが、 char s[5]; snprintf(s, sizeof(s), "%d%d%d%d",a[0],a[1],a[2],a[3]); それかコスト的には for (i = 0; i < 4; i++) s[i] = a[i] % 10 + '0'; s[i] = '\0'; みたいにするか、そもそも strtod() 使う必然なければ直接 d = a[0] * 1000 + a[1] * 100 + a[2] * 10 + a[3]; でいいんだが? もちろん適時キャストしたりループ使ってもいいし、二桁以上あるなら対応するようにしてだけど。

con014057
質問者

お礼

ご回答ありがとうございます. snprintfはコンパイル時にリンクエラーが発生したため,使用しておりませんでした.コンパイルはマイコンのIDEで行っています. 皆様にご回答いただけるのを待っている間に d = a[0] * 1000 + a[1] * 100 + a[2] * 10 + a[3]; 上記と同様のプログラムで所望の結果は出せたのですが,やはりなぜstrtodで左詰めになるのかが気になります. 皆様のアドバイスを反映させても直らないので,一度マイコンメーカーに問い合わせてみたいと考えます.

その他の回答 (3)

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.3

プログラムがおかしいです。 Visual Studio 2013 C++では正常動作しているように見えてるだけです(本当は正常動作していないということ) >char s[4]; >sprintf(s,"%d%d%d%d",a[0],a[1],a[2],a[3]); sにNUL文字分の領域が確保されていませんのでバッファーオーバーランしてます。

con014057
質問者

お礼

ご回答ありがとうございます. char s[5]にして試行致しましたが,同じ結果になってしまいます.

回答No.2

すいません、あと、やはり、ビッグエンディアンと、リトルエンディアンの違いかと思います

con014057
質問者

お礼

ご回答ありがとうございます. 一度,桁が逆になっているのでは?と考え sprintf(s,"%d%d%d%d",a[0],a[1],a[2],a[3]); を sprintf(s,"%d%d%d%d",a[3],a[2],a[1],a[0]); にして試行しましたが,数値が逆になって左詰めになるだけでした.

回答No.1

tempは、ポインタ型変数だけの宣言で、 領域は、確保してないので、 temp に mallocして、メモリ確保しないと、ngでは?

con014057
質問者

お礼

ご回答ありがとうございます. 試しにmalloc処理を記述致しましたが,同じように左詰めで表示されます. temp = (char*)malloc(sizeof(s)); d = strtod(s,&temp); 上記がテストコードです.

関連するQ&A

  • c言語 int型の数字をchar型の配列に

    c言語についてです。 int型の数字をchar型の配列に入れたいです。 関数に対してint型の数字を文字列として渡し、 関数内でchar型の配列に格納したいです。 例として、 a(char a[]){  ~~  ~~ } int main(void){ int x = 5678;  ~~  a(x); } とできるようにしたいです。 しかしこれだと5678という値がそのままchar型の一つの配列に入る?ため正しくないです。 欲しい結果としてはちゃんとa関数内で、 a[1] = '5' a[2] = '6' a[3] = '7' a[4] = '8' となってほしいです。 もともと渡す値が”5678”となっていれば結果は正しく出るのですが、 渡す値がint型と決まっているためどうにかして5678を”5678”とすればいいのではないかと考えています。 つまり5678を単純に文字列に変換すればいいのでしょうか? またプログラム内ではsprintfやatolを使用しないで実現させたいです。 難しいかもしれませんがお願いします。 なんだか説明が下手ですみません。 お願いいたします。

  • C言語のint型の配列が分かりません

    #include<stdio.h> int main(void) { int str[ ]={0,1,2} printf("%s\n", str); return 0; } というプログラムをC言語でつくってみましたが動きません.(012と表示されて欲しかったのですが) int str[ ]={1,2,3}の部分をchar str[ ]={'0','1','2'}とすれば動きます. そこで質問なのですが, printf("~%s~", (配列名));  はchar型の配列にしか適応できないのですか? ※追記 puts関数の定義は int puts (const char *str); であるそうなので char型の仮引数にはchar型のアドレスを渡さなければいけません. ではprintf関数の定義は一体どんなものなのですか?

  • C言語でintをdoubleに

    C言語でプログラミングを書いています。 10問の問題の正解数に応じて正答率を出すプログラムを書いているのですが、正解数を数えるものをintで定義(seikaiとする)し、正答率の計算結果を出すものをdoubleで定義(rituとする)しました。 seikaiをインクリメントで数え ritu=seikai/10*100 という計算をしました。このrituを%fで表示させようとしても正しく表示されません。intで定義したものを計算に用いて、その計算結果をdoubleで定義したもので表示することはできないのですか?? また、自分で調べたら、ritu=(double)seikai/10*100とやるというものがありましたが、”(double)”を使わずに計算を反映させることはできませんか?

  • c言語でintをchar*に代入

    c言語を用いてマイコンにシリアル通信経由で値を書き込もうとしています. PCからAscii(Aの場合は0x41)でマイコンにデータを送信し,マイコンで static int receivedUART[30]; 上記の変数に格納後し,書き込みのコマンドだと判断した場合に, char *kWifiSsid の変数に書き込みたいと考えています. 以下の関数を作成しました。 void setSSID(int *k){ char ssid[30] = {0}; for(int i = 0;i < SSID_LENGTH;i++){ char t; if(*k == 10){ Serial.println("brek"); break; } t = (char)*k; //最初のに2要素はコマンドのため無視 if((i != 0) && ( i != 1)){ ssid[i-2] = t; } ++k; } kWifiPass = ssid; } 上記の関数の引数にはreceivedUARTを指定しています. しかし,上記ではうまくkWifiPassが書き換えられませんでした. どのように改良すればintの値をchar*に書き込めますでしょうか?

  • char型・int型を相互変換させるプログラミング

    今、C++で2つのPC間で数値データの送受信を出来るようにしようと思い、実際にデータを飛ばせるところまで来たのですが、送れるデータの型はchar型のみであるとのこと。 ですので、intの値を一旦charにして送り、送った先でまたintにしたらいいかなと考えてプログラミングしました。 簡単にできると思ったのですが、上手くいきません・・・。プログラムのどの部分が間違っているのでしょうか? 一人では、これ以上悩んでも好転しないので、皆さんのご指導をお願いします 以下プログラム抜粋、このプログラムでは型変換がおこなわれているかの確認ができればいいので、それのみでプログラミングしています =================================================== #include <stdio.h> #include <stdlib.h> #include <string> #include <iostream> int main() { int a=123; char *b=new char; int c=1; //変換部分 *b=(char)a; std::cout<<"int→char>>>"<< c << "\n"; //逆変換部分 d=atoi(c); std::cout<<"char→int>>>"<< d << "\n"; } ======================================================

  • D言語の連想配列

    D言語で以下のプログラムが動いてくれません。 なにがおかしいのでしょうか。 int main(char[][] args) { int[char[]] a; a["abc"]=1; a["def"]=2; a["ghi"]=3; char[][] x=a.keys; for(int i=0;i<x.length;i++) printf("%s\n",x[i]); return 0; } 実行結果 Error: Access Violation

  • C言語 ソートについて

    #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { } bool is_at(char c) { } void justify(char line[], int n) { } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; } 上の雛形を使って文字列lineに含まれる@以外の文字を文字列の前の方に詰めていくプログラミングを作るという問題を解いていたのですが下のプログラミングまでは出来たのですが最後のjustifyの部分がわかりません 良ければ解答をお願いします #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { char temp = *a; *a = *b; *b = temp; } bool is_at(char c) { if(c == '@') { return true; } else { return false; } } void justify(char line[], int n) { for(int i=0;i<n-1;i++) { } } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; }

  • char型+char型ってint型? if(char型==int型)?

    C言語の「汎整数拡張(インテグラルプロモーション)」というものに関するものだと思います。 char型とchar型を加えた結果は、char型でしょうか。それともint型でしょうか。 (下のプログラムの printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ という部分の結果は4なので、int型と考えるべきなのかな。) 私は、char型とint型の加算の結果はint型だと思っていましたが、 char型とchar型の加算の結果はやはりchar型だと思っていました。 (それが間違えているのでしょうか。) if(a[0]==i) /* char型とint型の比較(?) */ の部分では、左辺はchar型、右辺はint型ですが、このように型の違う変数を比較しても文法上構わないのでしょうか。 (私は、「比較は必ず型の同じもの同士でしかできない」と思っていました。) 左辺はchar型のように見えて、じつはint型ですか。 #include <stdio.h> int main(void) { char a[4]; int i=77; printf("sizeof(int)は%d\n", sizeof(int)); printf("sizeof(char)は%d\n", sizeof(char)); printf("sizeof('M')は%d\n", sizeof('M')); printf("sizeof(a[0])は%d\n", sizeof(a[0])); a[0]='M'; a[1]=7+6; a[2]=a[0]+a[1]; printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ printf("sizeof(+a[0])=%d\n", sizeof(+a[0])); if(a[0]==i) /* char型とint型の比較(?) */ puts("a[0]==i"); else puts("a[0]!=i"); return(0); } ちなみにワーニングもエラーもなんにもでません。

  • C言語の配列について

    main() { int i; double min=100; double A[4]={50,2,1,3}; for(i=0; i<4; i++) {if(A[i]< min) min=A[i];} printf("%lf",min); } このようなプログラムを組んで配列Aの要素の最小値を求めています。 上記のプログラムで最小値はもとまるのですが、最小値を取るときの番地??(A[?]=1の?の値のことです。上記プログラムではA[2]=1なので2です。)をとりだしたいのですが、良い方法はないでしょうか?? アドバイスお願いします。

  • c言語の境界調整について

    c言語の境界調整について 下記の質問プログラムのp=(int *)s; の境界調整は、intは、偶数の倍数で、charは、1バイトなので 先頭アドレスは、int, charも同じであるので配列全部0となるのでしょうか、    よろしくお願します。 *質問プログラム char s[4] = {1,2,3,4} ; int *p ; main() p=(int *)s;; *p=0 ; printf("%d %d %d %d\n",s[0],s[1],s[2],s[3];

専門家に質問してみよう