質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.07%

int型をchar型に変える

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 169

Jhon_McClane

score 44

前提・実現したいこと

通信の課題です。
読み込んだ10進数の数字文字列を2進数で表した数値8桁に変換しサーバに送信する。
2進数は上位ビットを0でパディングする。

int型をchar型の配列に格納し、sprintfで送るメッセージを完成させたいです。

発生している問題・エラーメッセージ

passing argument 1 of sprintf makes pointer from integer without a cast

該当のソースコード

char binary[8];
read( soc, buf, 1024 );//char型配列で送られてきた数字
x = atoi(buf);//int型に変換し整数値にする
//2進数に変換する処理
for( i=0; i<8; i++){
   sprintf( binary[i],"%d", x%mypow(2,i+1)/mypow(2,i));//ここでエラー
}
sprintf(buf,"RESULT %s",binary);



int mypow(int base,int index){//指数の計算
  int result,i;
  for( i=0; i<=index; i++ ){
    if( i == 0)
     result = 1;
    else
      result = base*result;
  }
  return result;
}

試したこと

(char)でキャストしたがエラーは回避されなかった。
また、2進数16を整数値のようにint型で1111とあらわそうと考えたが、意味が違ってくると思い作るのをやめました。

補足情報(FW/ツールのバージョンなど)

VirtualBox

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

はじめにコンパイルエラー等

  • x,iの宣言がない。mainが書かれていないので省略されていると思うがコンパイルエラーになるので回答者に対して不親切。
  • binary[8]はSegmentation faultの危険がある。8文字確保したいならヌル文字分を含めて[9]にしなければならない。

本題

10進数の数値xをn進数の数字列に置き換える定石は、

  • x と n の剰余を求める(x % n)
  • x を n で除算しその整数位を新しいxとする(x = x / n)

を繰り返すことです。
下の桁から求まるので、2進数8桁で求めるならbinary[7]からスタートです。

for(int i = 7; i >= 0; i--){
  binary[i] = '0' + (x % 2);  // 2で割った余りを代入。このような文字の代入法は覚えておくと役に立つ!!
  x = x / 2;  // x を 2で割る
}
binary[8] = '\0';  // 最後にヌル文字を入れるのを忘れずに‼


これなら特に気にすることなく0埋めも可能です。
sprintfもmypowも不要です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/11 00:39

    解決しました、ありがとうございます。変数で使用した最低限のものは、宣言を書くようにします。ご指摘ありがとうございます。

    キャンセル

0

まずエラーが出ている部分について指摘すると、sprintf()関数の第一引数は文字配列(文字列)の先頭アドレスを与えるべきなのに文字を与えているのがエラーの原因です。
「binary[i]」→「&binary[i]」と修正すれば一応エラーはなくなると思います。

   sprintf( &binary[i],"%d", x%mypow(2,i+1)/mypow(2,i));

だたし、いくつか問題点があります。
sprintf()は文字配列に対して出力するため、文字列を1文字しか出力しない場合でも末尾に「\0」が付加されてしまいます。処理される内容を擬似的にコードで書くとこんな風に書き込まれる動作になります。

// ループ1回目のsprintf()
binary[0] = '1';
binary[1] = `\0';
// 2回目のsprintf()
binary[1] = '1';  /* ← 直前の'\0'を上書きしている */
binary[2] = '\0';
(略)
// 8回目のsprintf()
binary[7] = '1';
binary[8] = '\0'; /* ← binary配列の領域を越えた位置に書き込んでしまっている */


'\0'をループの次回で上書きしているのがちょっと気持ち悪いです。(動くことは動きますが)
問題なのはループ最後の'\0'の書き込みは配列の領域を越えた位置に書き込んでしまっていることです。

配列binaryは'\0'の領域1バイトを追加したほうが良いです。

char binary[ 8 + 1 ];


sprintf()のままでも動くことは動きますが、2進数文字列を作成する際に文字を直接書いたほうが良い気がします。
最後に末尾の'\0'を入れます。

for( i=0; i<8; i++){
   binary[i] = '0' + ( x%mypow(2,i+1)/mypow(2,i) );
}
binary[ 8 ] = '\0';

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/11 10:51

    わかりやすい説明ありがとうございます。原因が分かりすっきりしました。アドレスについてまだ理解が足りてないことが分かりました。
    アドレスを渡す際、配列の各要素を指定する際は[&]が必要で、全体を渡す場合、binaryと書くと先頭ポインタが渡されるため【&】をつけないという解釈であっていますか。

    キャンセル

  • 2020/07/11 14:05

    > アドレスを渡す際、配列の各要素を指定する際は[&]が必要で、全体を渡す場合、binaryと書くと先頭ポインタが渡されるため【&】をつけないという解釈であっていますか。

    はいそうです。
    1点補足すると、「binary」は「&binary[0]」と同じです。

    キャンセル

  • 2020/07/12 21:09

    ありがとうございます。勉強になりました。

    キャンセル

0

質問者のソースをある程度生かして書いてみた。
mainがないのでそこは適当にxを即値で設定し、sprintfもprintfにしている。
mypow(2, i)1 << iで計算できるので省略。

#include <stdio.h>

int main(void)
{
    char binary[9];
    int x = 127;

    for (int i = 0; i < 8; i++) {
        int mask = 1 << i; // 2^i の値
        binary[(8 - 1) - i] = (x & mask) ? '1' : '0';
    }
    binary[8] = '\0'; // 文字列終端

    printf("RESULT %s", binary);
    return 0;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/12 21:17

    (x & mask)
    ここの表現が何をしているのかよく分からないのですが
    教えていただけないでしょうか。
    3項演算子を使っていることは分かったのですが&当たりが分かりません

    キャンセル

  • 2020/07/12 21:26

    maskは1をiの値だけ上位ビットにシフトしたもので、1, 2, 4, 8, 16, 32, 64, 128の値のどれかになります。2進数の下位から数えた8ビット分の値ですね。
    & はビット演算のANDを行なうので、「x の値に maskのビットが立っているか(xを2進表現したさいに、そのビットの値が1かどうか)」を調べることができます。
    調べた結果が0でなければ、3項演算子の条件が成立したことになり'1'が、0の場合には条件が不成立で'0'が、binaryの対応する要素に格納されます。

    キャンセル

  • 2020/07/12 21:37

    ビット演算を書いたことがなかったので勉強になりました。
    2進数を考えるときなどはビット演算が使えるとわかりやすいと思いました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.07%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る