- ベストアンサー
16進数の文字列
16進数の文字列をそれと同値な整数値へ変換する関数をかけという問題なのですが、 この場合文字列を読み込んで、例えば読み込んだ値がABだとした場合、 A*16の1乗+B*16の0乗 を計算する関数を作ればよいのだと思うんですが、 それぞれの値をべき乗する関数も必要になってくると考えています。 そこで問題なのですが、べき乗の関数を作ったとして、それぞれの値(こんかいはAとB)にそれぞれのべき乗した値をかけてやるには、どういった方法があるのでしょうか? 回答よろしくお願いします。
- みんなの回答 (9)
- 専門家の回答
質問者が選んだベストアンサー
#1です。 >ナル文字を使うと言うのが、あまり例題がなくわからなかったのですが、 Cの文字列操作の基本なので探せばいくらでもあると思います。プログラム中では'\0'でなく単に0と書かれているかもしれません。同じ値です。例えば、pがchar *だとして for( ; *p; ++p) putchar(*p); というのも0での文字列終端を調べてforループの終了条件としています。 >for文で、文字を検索しナル文字があれば、breakするループを作ればよいのでしょうか? それでいいと思います。 >もう少しプログラムが上達する方法と、 ある程度のレベルに達すれば他人の良く出来たプログラムを読むのがいいと思いますが、まだその域ではないようですね。当面は入門書のマスターでしょうか。 >この問題の大きな流れがあれば回答おねがいします。 文字列入力して、先頭からループで1文字ずつ調べながら値を16倍して足しこんでいくということでいいでしょうが、0-9A-Fa-f以外の文字があったらどうするかも考えねばなりません。
その他の回答 (8)
- arukamun
- ベストアンサー率35% (842/2394)
>unsignedというものが分からなかったので調べてみたのですが、符号なしとありました。 >これは、符号があればどうなるのでしょうか? 符号有りでつくるのであれば、文字列の桁数を固定する必要があります。 例えば2文字の16進数にするのであれば、ABは負の数ですね。 負の数である事の判定は先頭ビットが立っているか否かです。 >また、for文内の >for (i=0,j=strlen(x)-1,k=1 ;j>-1 ;j--,k*=16) >最後のk*=16なのですが、私の中では始めて見る書き方なのです。 >for文内に書いてもよいのですか? 書いても良いんですよ。 k *= 16 ; は k = k*16 ; と同じ意味です。 また16倍なので、 k = (k<<4); k <<= 4 ; というのも同じ事ですね。
お礼
i += (x[j]-'0')*k ; という部分を使わせていただいて、コンパイルしたのですが、16進数1111を入れてみたところ、17という値しか返ってきませんでした。 なぜなんでしょうか? 引き続き色々頑張ってみます。 お時間がありましたら、何か回答をいただけたらと思います。ありがとうございました。
- ara_ara
- ベストアンサー率35% (124/348)
#5です。 よくご自分のソースを見てください。 i,jが混同していたり、hexstrも未定義です。 あなたのソースの修正箇所を下記に示しますので考えてみてください。 ・int s[3]; → int s[4]; ・for(j=0;j<=3;j++) → for(i=0; i<4; i++) (i<=3 よりも i<4 とするのが普通です) ・for(n=0, i=0; i<strlen(hexstr); i++) { → for(n=0, i=0; i<4; i++) {
- notnot
- ベストアンサー率47% (4900/10358)
#1です。 >文字をキーボードから得るには、scanfを用いるのがよいのか、それともgetcharを用いるのがよいのかがわかりません。 普通は、fgets で1行入力します。 scanfは意図通り使うことが難しい関数なので初心者は使わないほうがいいでしょう。ちゃんとしたC入門書では「使ってはいけない関数」と説明してあるはずです。 >そして、関数に文字を渡すときは、配列にして渡すのが普通なのでしょうか? 16進2桁とか決まっているなら2個のintでもいいです。 int hex_to_bin(int x, int y) のような。 桁数が可変である場合は char [] で'\0'で終端した文字列形式を使うのが普通でしょう。
お礼
ナル文字を使うと言うのが、あまり例題がなくわからなかったのですが、 for文で、文字を検索しナル文字があれば、breakするループを作ればよいのでしょうか? 新しいことを知れば知るほど、この16進数の変換のプログラムの大きな流れがわからなくなってきます。 なにか、もう少しプログラムが上達する方法と、この問題の大きな流れがあれば回答おねがいします。 なんどもすいません。
- ara_ara
- ベストアンサー率35% (124/348)
>c-'0' と言う部分なんですが、 cは文字コードになっていることはわかりますよね。 '0'は、'0'の文字コード(ASCIIコードで0x30=48)です。 ASCIIコードでは、'0','1',...と並んでいるので'0'~'9'のコードなら そのコード(c)から'0'のコードを引くと文字を数値に変換したことになりますよね。 ・'0'-'0'=0 ・'1'-'0'=1 ... ・'9'-'0'=9 'A'~'F'の部分は自分で考えてください。(ほとんど同じですが)
お礼
'A'~'F'の部分は意味の理解し、自分なりのプログラムを作ってみたのですが、内容はara_araさんの内容と同じです。そこで、コンパイルしたところ int main(void) { int i,j,n; int s[3]; for(j=0;j<=3;j++) s[i]=getchar(); for(n=0, i=0; i<strlen(hexstr); i++) { n *= 16; n += hex2bin(s[i]); } ・・・ } の、n += hex2bin(s[i]); の部分で、s[i]が、引数として渡せないとエラーが出ます。 この部分をどういう風に書き換えれば、エラーがでずにコンパイルすることが出来るでしょうか? 何度もすいません。
- arukamun
- ベストアンサー率35% (842/2394)
整数値としか無かったので取り急ぎunsigned intで書いてみました。 unsigned int xtou(char x[]) { unsigned int i ; int j,k ; for (i=0,j=strlen(x)-1,k=1 ;j>-1 ;j--,k*=16){ if ( x[j] >= '0' && x[j] <= '9' ){ i += (x[j]-'0')*k ; } else if ( x[j] >= 'a' && x[j] <= 'f' ){ i += (x[j]-'a'+10)*k ; } else if ( x[j] >= 'A' && x[j] <= 'F' ){ i += (x[j]-'A'+10)*k ; } else { fprintf(stderr,"Error : xtou(\"%s\");\n",x); exit(1); } } return i ; }
お礼
どうもありがとうございます。 unsignedというものが分からなかったので調べてみたのですが、符号なしとありました。 これは、符号があればどうなるのでしょうか? また、for文内の for (i=0,j=strlen(x)-1,k=1 ;j>-1 ;j--,k*=16) 最後のk*=16なのですが、私の中では始めて見る書き方なのです。 for文内に書いてもよいのですか? もしよろしかったら、回答お願いします。 ありがとうございました。
- ara_ara
- ベストアンサー率35% (124/348)
こんな感じでどうでしょうか? (0-9、A-F以外が含まれる場合は省略しています) int hex2bin(char c) { if(('0'<=c) && (c<='9')) return c-'0'; if(('A'<=c) && (c<='F')) return c-'A'+10; return -1; /* 0-9,A-F でない */ } int main(void) { char hexstr[]="ABCD"; int i, n; for(n=0, i=0; i<strlen(hexstr); i++) { n *= 16; n += hex2bin(hexstr[i]); } ・・・ } 動かしていないので自信なしということにしておきます。
お礼
どうもありがとうございます。 ひとつ疑問におもったのが c-'0' と言う部分なんですが、以前にも何かの本でこのような部分があり、どういうことをしているのかが、わからなかったのですが、これはどういうことをしているのでしょうか? よろしかったら、回答おねがいします。
- BellBell
- ベストアンサー率54% (327/598)
ロジックを解析してみてください。 納得できれば、プログラムに起こすだけです。 関数開始 (文字列へのポインタを引数に渡す) 文字数だけループさせる i番目の文字を判定 '0'の場合0 '1'の場合1 '2'の場合2 ・・・ 'F'の場合15 X=(X * 16)+上で判定した数値 ループ終了 Xを返す 関数終了 ※Xは返り値を保存する変数 iはループ変数
お礼
文字を判定する場合、switch文を用いてcaseの分岐によってそれぞれに値を与える、と最初に考えついたのですが、みなさんの回答にあるように c-'0' といった式で繰り返し数値を与えるものが、もっとも効率のよいプログラムになるのでしょうか? もっと斬新な、方法があれば教えてください。 よろしくおねがいします。 どうもありがとうございました。
- notnot
- ベストアンサー率47% (4900/10358)
>べき乗の関数を作ったとして、それぞれの値(こんかいはAとB)にそれぞれのべき乗した値をかけてやるには、どういった方法があるのでしょうか? 単に * で掛ければいいと思うのですが、どのあたりが問題と思っているのでしょうか? 16進数 ABCD を A*16^3+B*16^2+C*16^1+D というのが質問中に書かれた方法ですが、 ((A*16+B)*16+C)*16+D というのがよくプログラムで使われる方法です。前者の方法に比べて 1) 16を掛けて足すという繰り返し処理でいい 2) 最初に全体の桁数を調べなくて良い という利点があります。
お礼
なるほど!という一言に尽きる回答をありがとうございました。 いざ、関数の中身がわかったところで、ソースを書いていたんですが、文字をキーボードから得るには、scanfを用いるのがよいのか、それともgetcharを用いるのがよいのかがわかりません。 そして、関数に文字を渡すときは、配列にして渡すのが普通なのでしょうか? なんどもすいません。よろしければ回答おねがいします。
お礼
今現在プログラミング言語C(バイブルと呼ばれているやつ)をしています。 一応、入門書を購入して、一通り読み終えてから、バイブルに挑戦しているのですが、この本は簡単な部類に入る本なのですか? 毎日頑張っていますが、なかなか進みません。 どうもありがとうございました。