scanf()で数字(文字列)を入力し、それをdataという場所に16進数(数値)で格納したいのです。
例えば、
scanfで「3b」と入力したら、dataには、「0x3b」が格納されているようにしたいのですが、どのようにしたらいいのか教えてください。よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (5件)

sprintf()関数でOKです。


data = sprintf("%0x",scanfで取得した変数名※1);
で良いかと思います。
※1scanfで取得した変数はchar型が前提です。
詳しくはC,VC++のprintf文等の書式にあります。
    • good
    • 0

scanf() でやるとしたら、こうなります。



  int data;

  scanf("%x", &data);
    • good
    • 0

とりあえずstrという配列に文字列が入っているるとして。



dataがlongの場合:
data = strtol(str, NULL, 16) ;

dataがlongで無い場合はキャストしてください。

strtol()は便利な関数で、最後の引数に基数を指定できます。
16と書けばstrを16進文字列として変換します。
最後の引数には2~36までの数値を指定できます。

入力(=strの内容)が"0xab"のようなパターンの場合は最後の引数に0を指定すれば、いわゆる「C言語の10進16進8進表記」を認識して変換してくれます。

ホントは2番の引数もNULLじゃ無い方が良いのですが、エラー処理が必要ないみたいなので割愛します。
    • good
    • 0

こんにちは。

itohhといいます。

「0x3b」と4バイトの文字列で格納するのではなくて1バイトの16進数で格納したいのですね?

過去に2回ほど似たようなことにアドバイスしました。
そちらは、参考にならないですか?
http://oshiete1.goo.ne.jp/kotaeru.php3?q=175147
http://oshiete1.goo.ne.jp/kotaeru.php3?q=214994

参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=175147,http://oshiete1.goo.ne.jp/kotaeru.php3?q=214994
    • good
    • 0

 変数 data の型はなんでしょうか?



 int 型や long 型で宣言してある場合には、atoi 関数や atol 関数が使えます。
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qfor文内でscanf関数により配列に数値を格納することについて

プログラミング初心者です。
よろしくお願いします。

◎1------------------------------------
#include<stdio.h>
int main(void)

{
int i,dt[3];

for(i=0;i<3;++i){

printf("dt[0]=%d\n",dt[0]);
printf("dt[1]=%d\n",dt[1]);
printf("dt[3]=%d\n",dt[3]);

scanf("%d",&dt[i]);

printf("i=%d\n",i);
puts("");

if(dt[i]==0){
break;
}
}
printf("dt[0]=%d\n",dt[0]);
printf("dt[1]=%d\n",dt[1]);
printf("dt[2]=%d\n",dt[2]);
printf("dt[3]=%d\n",dt[3]);
printf("i=%d\n",i);
puts("");

i=1;

while(1){
printf("%d ",i);

if(1000<i){
break;
}
i*=2;
}
puts("");

return 0;
}
----------------------------------------
◎2------------------------------------
#include<stdio.h>
int main(void)

{
int i,dt[2];

for(i=0;i<3;++i){

printf("dt[0]=%d\n",dt[0]);
printf("dt[1]=%d\n",dt[1]);
printf("dt[2]=%d\n",dt[2]);

scanf("%d",&dt[i]);

printf("i=%d\n",i);
puts("");

if(dt[i]==0){
break;
}
}
printf("dt[0]=%d\n",dt[0]);
printf("dt[1]=%d\n",dt[1]);
printf("dt[2]=%d\n",dt[2]);
printf("i=%d\n",i);
puts("");

i=1;

while(1){
printf("%d ",i);

if(1000<i){
break;
}
i*=2;
}
puts("");

return 0;
}
----------------------------------------

以上2つのプログラムについて疑問があります。
まず◎1については、あえて添え字のdt[3]の値を見てみようと思ったら、iの値が入っているとわかりました。
しかし、何故添え字の番号の配列にiの値が入っているのかがわかりません。

次に◎2ですが、3回目のループで、添え字の番号の配列自身に入力した数値を格納すると、iと添え字番号配列に入力した数値が入っていました。
何故このようになっているのか疑問です。

以上のような疑問があります。
添え字の番号の配列とiが何か関連があるようですがいまいちわかりません。
教えていただけると嬉しいです。

プログラミング初心者です。
よろしくお願いします。

◎1------------------------------------
#include<stdio.h>
int main(void)

{
int i,dt[3];

for(i=0;i<3;++i){

printf("dt[0]=%d\n",dt[0]);
printf("dt[1]=%d\n",dt[1]);
printf("dt[3]=%d\n",dt[3]);

scanf("%d",&dt[i]);

printf("i=%d\n",i);
puts("");

if(dt[i]==0){
break;
}
}
printf("dt[0]=%d\n",dt[0]);
printf("dt[1]=%d\n",dt[1]);
printf("dt[2]=%d\n",dt[2]);
printf("dt[3]=%d\n",dt[3]);
printf("i=...続きを読む

Aベストアンサー

そのコンパイラがiとdt[ ]を連続して確保しているためでしょう
たまたまdt[3]に当たる位置に変数iがあったというだけと思われます
環境が違えば別の結果になるでしょうし
配列の要素をオーバーして書き換えて別の変数を壊すバグもあります

変数の宣言を
int i,dummy1,dummy2,dummy3,dt[3];
に変えたら結果も変わりませんか

Q数値連続入力プログラムでの配列に格納される文字について

--------------------------------------------------------
#include<stdio.h>
int main(void)
{
   double sum=0.0;
   double dt,x
   int ret,n;
   char ss[80];

   ret=scanf("%lf",&dt);

   while(1){
      if(ret==1){
         x=sum;
         sum+=dt;
         n=getchar();
        if(n=='\n'){
           printf("入力された数値=%f\n");
           puts("");
           sum=sum;
        }
        else{
         printf("正しく入力してください\n");
         puts("");
         gets(ss);
         sum=x;
         dt=0.0;
        }
      }

      else if(ret!=0){
         gets(ss);
         dt=0.0;
         printf("正しく入力してください\n");
         puts("");
      }

      else if(ret==EOF){
         break;
      }

      ret=scanf("%lf",&dt);
   }
      printf("合計=%f\n",sum2);
      return 0;
}
--------------------------------------------------------

前回、「scanfの入力をgets関数で読み捨てることについて」というタイトルで数値連続加算のプログラムを作り、皆様からいろいろとアドバイスを受けた者です。

いろいろとプログラムを改良し、「Ctrl+Z」の入力でプログラムを終了しようとし、後、前のプログラムでは「10abc」などと打ち込んでも「10」は読み込んでしまうので、「10abc」などと打ち込んだ時点で、エラー表示をさせるようにしました。

ここで疑問なのですが、例えば、
-------
enter
enter
abc
-------
と入力した場合、改行文字が配列ssに格納され、いろいろと複雑になってしまうのかと思ったのですが、ssにはしっかり「abc」だけが格納されていました。

以上のプログラムに不備がないかも含めて、何故そうなるのか教えていただけると嬉しいです。

--------------------------------------------------------
#include<stdio.h>
int main(void)
{
   double sum=0.0;
   double dt,x
   int ret,n;
   char ss[80];

   ret=scanf("%lf",&dt);

   while(1){
      if(ret==1){
         x=sum;
         sum+=dt;
         n=getchar();
        if(n=='\n'){
           printf("入力された数値=%f\n");
           puts("");
           s...続きを読む

Aベストアンサー

>ここで疑問なのですが、例えば、

「scanfは、先頭にある空白や改行を読み飛ばしてから、指定の数値を読もうとする」ので
enter
enter
で入れられた改行2つは、scanfが読み飛ばします。

で、scanfが最初の改行を読み飛ばした後で「a」を見付けるので、その「a」は「まだ読んで無い事にして」から、0を返します。

入力バッファには「abc」+「改行」が残っています。

次に「getsは改行まで読み込んで、読み込んだ改行を文字列の終端記号の'\0'に書き替えてから戻って来る」ので「abc\n」を読み込み、\nを\0に書き替えて「abc\0」がssの中に入ります。

ここで問題になるのが「scanfは、先頭にある空白や改行を読み飛ばしてから、指定の数値を読もうとする」と言う部分。

なのでscanfを使う限り「enterだけの入力」で「正しく入力してください」とエラー表示する事は出来ません。

その部分を修正したのが、以下のプログラムです。

#include <stdio.h>

int main(void)
{
 char ss[256];
 double sum=0.0,dt;
 int ret;
 char c;
 char *p;
 for (;;) {
  // scanfは使わないで、とにかく1行全部をssに入力する
  p = gets(ss);

  // Ctrl+Zが入力されたらgetsはNULLを返すので終了する
  if (p == NULL) break;

  // 入力したssから、数値と、数値の直後の文字を取り出す。
  ret = sscanf(ss,"%lf%c",&dt,&c);
  // 改行のみの入力なら「ssが空っぽ」なのでretはEOFになる。
  // 数値だけの入力なら、後ろの%cが入力されないのでretは1になる。
  // 数値以外の入力なら、retは0になる。
  // 数値の後ろに何か余計な物があったらretは2になる。

  // 数値だけ入力したかどうか調べる。
  if (ret == 1) {
   // 数値だけ入力した。
   printf("入力された数値=%f\n",dt);

   // 数値だけ正しく入力したので、sumにdtを足す。
   sum += dt;
  } else {
   // 何も入力せずにEnterだけ押したか、数値以外を入力したか、余計な物を入力した。

   // エラー表示する。
   printf("正しく入力してください\n");
  }
 }
 printf("合計=%f\n",sum);
 return 0;
}

で、これでOKかと言うと、そうじゃない。

この「修正版プログラム」で、以下のように入力してみよう。

1a
1b
1c
1d
1e
1f
Ctrl+Z

結果は

1a
正しく入力してください
1b
正しく入力してください
1c
正しく入力してください
1d
正しく入力してください
1e
入力された数値=1.000000
1f
正しく入力してください
^Z
合計=1.000000

となる。なぜか「1e」だけ「1」として入力され「正しい入力」と判断されてる。

実は、scanfの%lfは「仮数部+e+指数部」と言う入力を許しているのだ。

例えば「120」は「1.2×10の2乗」なので、入力時に「1.2e2」と入力しても良い。

上記の「1e」は「1×10の0乗で、eの後ろの0が省略されてて、1e0と入力した」と認識されてしまう。

「10の0乗」は「1」なので「1×10の0乗」は「1×1」なので、結局は「1」になってしまう。

こういう「意図しない入力を除外したい場合」は「scanfする前に、自前で、入力した文字列が正当か調べる必要」がある。

>ここで疑問なのですが、例えば、

「scanfは、先頭にある空白や改行を読み飛ばしてから、指定の数値を読もうとする」ので
enter
enter
で入れられた改行2つは、scanfが読み飛ばします。

で、scanfが最初の改行を読み飛ばした後で「a」を見付けるので、その「a」は「まだ読んで無い事にして」から、0を返します。

入力バッファには「abc」+「改行」が残っています。

次に「getsは改行まで読み込んで、読み込んだ改行を文字列の終端記号の'\0'に書き替えてから戻って来る」ので「abc\n」を読み込...続きを読む

Q【C言語】二重forループ内でscanfを使ってchar型変数に数値(

【C言語】二重forループ内でscanfを使ってchar型変数に数値(%d)を入力すると、きちんとループ処理されないのはなぜ?

プログラムを下に用意しましたのでご覧下さい。
二重forループ内で入力を繰り返すプログラムです。
ついでに i j の値を出力するようにしました。


-----------------プログラム----------------
int main (void){
char input = 0; // 入力値 char型にするとforループでインクリメントエラー(int型にすると問題ない)
int i = 0, j = 0;

, printf("数値を入力して下さい。('-1' で入力終了)\n");

for( i=0 ; i<3 ; i++ ){ // i がちゃんとインクリメントされない
for( j=0 ; j<3 ; j++ ){
scanf("%d", &input); // char 型変数に %d で入力すると、i がきちんとインクリメントされない
printf("[i][j] = [%d][%d]\n", i, j);

if( input == -1 ){
printf("入力を終了します。\n");
break;
}
}
if( input == -1 )
break;
}
return 0;
}
----------------------------------------

---------実行結果(入力値はchar型)---------
数値を入力して下さい。('-1' で入力終了)
1 2 3 4 5 6 7 8 9
[i][j] = [0][0]
[i][j] = [0][1]
[i][j] = [0][2]
[i][j] = [0][0]
[i][j] = [0][1]
[i][j] = [0][2]
[i][j] = [0][0]
[i][j] = [0][1]
[i][j] = [0][2]
-1
[i][j] = [16777215][0]
入力を終了します。
----------------------------------------

----------実行結果(入力値はint型)----------
数値を入力して下さい。('-1' で入力終了)
1 2 3 4 5 6 7 8 9
[i][j] = [0][0]
[i][j] = [0][1]
[i][j] = [0][2]
[i][j] = [1][0]
[i][j] = [1][1]
[i][j] = [1][2]
[i][j] = [2][0]
[i][j] = [2][1]
[i][j] = [2][2]
----------------------------------------


ご覧の通り、char型変数に値を入力しているために、forループで i がきちんとインクリメントされません。
入力値は -128~127 の値しか想定していないので、メモリの消費を少しでも抑えようと思いchar型で宣言したのですが、思わぬ所でおかしな挙動が起こってしまいました。
int型で宣言すればいいだけなのですが、なぜこんな挙動になるのか知りたいです。
よろしくお願いします。

【C言語】二重forループ内でscanfを使ってchar型変数に数値(%d)を入力すると、きちんとループ処理されないのはなぜ?

プログラムを下に用意しましたのでご覧下さい。
二重forループ内で入力を繰り返すプログラムです。
ついでに i j の値を出力するようにしました。


-----------------プログラム----------------
int main (void){
char input = 0; // 入力値 char型にするとforループでインクリメントエラー(int型にすると問題ない)
int i = 0, j = 0;

, printf("数値を入力して下さい...続きを読む

Aベストアンサー

scanfのマニュアルをよくよんでください。
フォーマット%dが要求するのはint型へのポインタです。

例え、実際にはchar型へのポインタであったとしても、きっちりint型の分の領域にデータが書き込まれます。その場合、char型より大きい分は変数の領域の外へ書き込まれることになります。

今回は、そのあふれた先が変数iの領域だったので、iが異常な値になったのでしょう。

Q小数点つきの数値を文字列として読み込み、浮動小数点数値として出力

タイトルの通りです。
小数点以下は6桁までです。
ヒントでいいんで教えてもらえるとありがたいです。
よろしくおねがいします。

Aベストアンサー

入力の方は回答が出てるようなので、
出力の方を。

小数点以下を6桁にしたいんですよね。
printfで%.6fとかやるといいと思います。
ご存じかもしれませんが、
ファイルに出したいならfprintf、
文字列にしたいだけならsprintf、
です。

Q文字列配列をサブルーチンにアドレス渡ししてscanf入力

main関数内で
char strarray[3][21]
という文字列配列を宣言し、
サブルーチンvoid input(・・・)内でscanfを使って
strarray[0]~strarray[2]の各行に入力を行うとします。
ここでポインタを引数としてstrarrayをmainとinputで共有する場合、
strarrayに関して以下の項目はどう記述すればよいのでしょうか?

1)inputを宣言する際の仮引数の書式
2)main内でinputを呼び出す際の引数の書式
3)input内でscanfする際の引数の書式

いろいろ組み合わせを試してはみたのですが、
どうにもSegmentationFaultを回避できません。
いい加減混乱してきたので、そろそろすっきりと整理したいと思っています。
よろしくお願いします。

…まあ「構造体使えばいいじゃないか」と言われてしまえばそれまでなのですが…

Aベストアンサー

まず、配列とポインタの関係から説明します。

C 言語の場合、配列はコンパイラによって、その「先頭要素を指すポインタ」に読み替えられます。

つまり、int hoge[10]; と定義した配列に対して、式の中で hoge と書くと、これは int*型の変数として扱われて、それは &hoge[0] と同じ意味になります。
# 一部例外はあります。
# たとえば、sizeof(hoge) とした場合、ポインタサイズではなくて、配列のサイズが
# 取得できます。

で、これをそのまま配列の配列に適用してみれば良いわけです。

どうなるかというと、char piyo[3][10]; と定義した変数に対して、式の中で piyo と書けば char(*)[10]型の変数として扱われて、それは &piyo[0] と同じ意味になります。

char(*)[10] 型と書きましたが、これは「char型配列(要素数10)を指すポインタ型」のことです。
配列を指すポインタ型の変数を定義する場合には、次のように書きます。
char (*p_piyo)[10];

つまり、piyo はもともと「char型配列(要素数10)の配列(要素数5)」だったわけですよね。
これが、コンパイラによって「char型配列(要素数10)を指すポインタ」として扱われるようになるわけです。

注意点としては、この配列→ポインタの読替え規則は再帰的には行われないことですね。
どういうことかというと、配列の配列は、ポインタのポインタにはならず、配列のポインタにしかならない、ということです。

さて、前置きが長くなりましたが、話を etendard さんのご質問に戻します。

1) これまでの話で、char strarray[3][21] に対してコンパイラが読み替える等価な型が char (*str_ptr)[21] となることはおわかりいただけると思います。

関数の引数に配列を渡す場合は、必ずポインタに読みかえられますので、仮引数の宣言もポインタに読み替えられた方の型で書くことになります。
# というよりも、配列を渡すことができないので、配列の先頭要素を指すポインタを
# 渡している、という言い方のほうが正しいのですけどね。

つまり、プロトタイプは

void input( char (*str_ptr)[21] );

のようになります。
できれば、配列の要素数も一緒に渡せるようにするのが良いでしょう。

その場合は、こんな感じです。

void input( char (*str_ptr)[21], int num );

2) 関数コールする場合は次のようにします。

input( strarray );

要素数付きの場合は、次のようにします。

input( strarray, 3 );

要素数付きにしたほうが良い理由は、ポインタに読み替えられた方の配列の要素数が、関数に渡らないためです。

標準関数では、gets() なんかはその典型ですよね。
# バッファオーバーランの原因となるということで、WARNING を吐くコンパイラも
# あるとか。。。

それに対して fgets() は文字列の数も渡せるので、より安全だといえます。
要するに、それと同じことです。

3) input() の中で scanf() する場合には、次のようにすれば良いです。

for ( i=0; i<3; i++ )
{
scanf( "%s", str_ptr[i] );
}

# なぜこれで良いのかは、よく考えてみてください。

同様に、要素数付きの場合には次のようにします。

for ( i=0; i<num; i++ )
{
scanf( "%s", str_ptr[i] );
}

ちなみに、関数の仮引数の場合に限り、ポインタ宣言と配列宣言は同じ物になります。
# というよりも、いずれもポインタ宣言になります、といった方が正しいです。

つまり、以下の表記はいずれも同じ物になります。

void input( char (*array_ptr)[21] );
void input( char array_ptr[][21] );
void input( char array_ptr[3][21] );

ただし、3番目の表記をした場合であっても、[3] の部分の要素数は無視されます。
# コンパイラが勝手にポインタに読み替えてしまいますからね。

宣言や定義について、このような読替えが起こるのは関数の仮引数宣言の場合だけです。
通常の、宣言や定義ではこのような読替えは起こりませんのでご注意ください。

かなり長くなってしまいましたが、こんな感じでいかがでしょうか。

まず、配列とポインタの関係から説明します。

C 言語の場合、配列はコンパイラによって、その「先頭要素を指すポインタ」に読み替えられます。

つまり、int hoge[10]; と定義した配列に対して、式の中で hoge と書くと、これは int*型の変数として扱われて、それは &hoge[0] と同じ意味になります。
# 一部例外はあります。
# たとえば、sizeof(hoge) とした場合、ポインタサイズではなくて、配列のサイズが
# 取得できます。

で、これをそのまま配列の配列に適用してみれば良いわけです。

どうな...続きを読む


人気Q&Aランキング

おすすめ情報