ID登録せずに、無料で質問できる♪ 教えて!gooアプリ>>

入出力のときはJISの文字コード表の値が使われ、それ以外の計算などにおいては通常の2進数が使われるとのことですが、その変換はどのように行うのでしょうか。

テキストには「1~9の文字には16進数の(0030)を減算」「A~Fの文字には(0037)を減算」と書いてあります。

例えば
’5’は内部コードでは(0035)、
16進数の数値では(0005)
数値と文字コードの差は16進数で(0030)

というのは理解できます。

ただアルファベットになると理解できません。

例えば
’A’は内部コードで(0041)
16進数の数値では(000A)
数値と文字コードの差は16進数で(0037)

なぜここで(0037)になるのでしょうか・・。
(0041)を(0037)で減算し、(000A)になるまでの過程を教えてください。

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

A 回答 (2件)

文字→数値変換ですね。


説明が面倒ですが、内容はごく単純です。頭をやわらかくして。

0 = 文字コード(0030) - (0030)
1 = 文字コード(0031) - (0030)
2 = 文字コード(0032) - (0030)
5 = 文字コード(0035) - (0030)
9 = 文字コード(0039) - (0030)

ここで、A = 文字コード - 0030 と同様にやりたいところですが、駄目です。
文字コード表を見ればわかる通り、1~9の文字コードとA~Fの文字コードは離れているので。(連続値として変換できない)
A~Fは基準点になる0030という数値が変わってきます。

A = 文字コード(0041) - (0041) + (000A)
B = 文字コード(0042) - (0041) + (000A)
F = 文字コード(0046) - (0041) + (000A)

この、-0041+000A を計算してまとめると、-0037

A = 文字コード(0041) - (0037)

となります。

こんな手法プログラム作成時に本当にやるのか!と言われそうですが、
使う人は使いますし、知っておいて損はないです。
    • good
    • 0
この回答へのお礼

非常に分かりやすくて助かりました!

基本情報も無事高得点も取れて、たまたまこの文字コードに関する問題も出ました!
ありがとうございました!

お礼日時:2014/10/23 12:52

>数値と文字コードの差は16進数で(0030)


>というのは理解できます。

0035 - 0005 = 0030

>なぜここで(0037)になるのでしょうか・・。

0041 - 000A = 0037 (10進だと、65 - 10 = 55 )

全く同じ構造です。
    • good
    • 0
この回答へのお礼

ありがとうございました!

お礼日時:2014/10/23 12:52

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

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

QCASLII:文字列→数字への変換の原理

CASLIIにおいて
文字列を数字へ変換する場合、000FでAND演算をしますよね?この方法で変換が行なえることはわかるのですが、なぜ000FでAND演算をすると変換されるのか、その原理が分かりません。
ご教授のほどお願い致します。

Aベストアンサー

数字の文字列表現は、16進表記では
0が0x30、1が0x31...9が0x39
となりますので、上位4ビットをクリアして、下位4ビットを維持すれば数値に変わります。

Qアセンブラ言語の数字を数値に変換するプログラム

LD GR3,GR1 ;GR3にGR1の数字を入れる。
AND GR3,=#000F ;数字を数値に変換

というアセンブラのプログラムがあったのですが、なぜGR3と16進数#000Fの論理積をとることで数字を数値に変換できるのでしょうか。

それと、ここでいう数字、数値の違いとは、数字の1はコンピュータ上では
49という数値に変換される(アスキー文字)という認識でよろしいでしょうか。

Aベストアンサー

2進数で表したときの下4桁だけが残ることになるからです。

アスキーコードでは、数字の「1」は、10進で49、16進で31です。
16進の31を2進数に直すと、0011 0001です。
これと16進のOF、つまり2進の0000 1111と論理積をとると、0000 0001となり、数値の1になります。

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む

Q構造体の初期化のmemsetの第三引数

memset(&lvitem, 0, sizeof(LVITEM));
memset(&lvitem, 0, sizeof(lvitem));
LVITEMに特化した質問ではなく構造体の初期化について、この2つの書き方によるソース管理やコンパイルでのメリットとデメリットを教えてください。

Aベストアンサー

(1)memset(&lvitem, 0, sizeof(LVITEM));
この書き方は、構造体LVITEMを初期化しているんだな、と分かりやすい。
(2)memset(&lvitem, 0, sizeof(lvitem));
この書き方はとにかく変数lvitemを初期化するんだな、という感じだが、型が分からないので宣言しているところを参照しなければならない。
それともう一つ、ただ単に何回も初期化するんでなければ、こういう書き方もできる。
(3)LVITEM lvitem = {0};

結局どれがいいのかといえば、個人的にはケースバイケースですねえ。初期化を1回すればいいような感じなら(3)、構造体名を明示した方が調べる手間がなくなるようなら(1)、そうでなければ(2)を使います。
コンパイルでのメリット、デメリットは特にないんじゃないかなあ。アセンブラがまだ全盛だった頃ならともかく、いまじゃどのコンパイラだって最適化オプションで同じようなコードはくでしょう。
気にするほどでもないと思うけど…

Qソケット通信内 read関数について

現在C言語にソケット通信を作成しているのですが、read関数内の作成でつまずいています。
ご存知でしたら教えてください。

自分なりに調べた結果read関数の戻り値は受信した
バイト数、毎回指定サイズ受け取るとは限らないと
いうことでした。

そこでread関数を無限ループで回し
指定サイズ受信したら、ループを抜ける使用にしたのですが、受信バイトが0だった場合はどうすればよいのでしょか?
よくサンプルなどでは、0だったらエラーと判断し、すかさずbreakしているのですが、一度でも0バイトを受信すると、それ以降は1バイト以上受信出来ないものなのでしょうか?
もし出来ないのなら一度でも0を受信したら、breakしようと思っています。
出来るのでしたら、タイマー設定をし、指定受信バイトに満たなくても一定時間が過ぎたらループから抜ける使用にしたいと考えています。
そのほか良い方法があれば教えてください。

分かりずらい説明になってしまいましたが、宜しくお願い致します。

Aベストアンサー

selectの戻り値が1となったのならば一歩前進です。
あとは、FD_ISSET()して期待通りのソケット番号にデータきていれば受信できると思います。

ところで今回のソースでFD_SET()のところはどうなっていますか?
selectでいつも0となるのはFD_SETがちゃんとできていないような気がします。
前回と今回のソースで差分をチェックしてみてはどうでしょうか。

がんばってください!


あと、ほかに参考になりそうなページをのせてみます。
「selectを使う」の項目が役立ちそうです。fdという変数にaccept()した戻り値を入れるようにすればいけます。

参考URL:http://www.ops.dti.ne.jp/~allergy/socket/socket.html

Qリスト構造のソートで悩んでます。。。

リスト構造のソートで悩んでます。プログラムの内容はファイルからデータをリスト構造の構造体に読み込み、名前順にソートし結果を表示する。というものです。データの追加や削除はできるのですがソートとなると頭が混乱してしまいお手上げ状態になってしまいました。。。。。
読み込み用のデータとプログラムソースを以下に記載するのでどなたか良きアドバイスをお願いしますm(_ _)m

○データ

Sakuragi
16
Rukawa
16
Miyagi
17
Akagi
18
Mitsui
18

○ソース
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MENBER 5

typedef struct data{
char name[BUFSIZ];
int age;
struct data *next;
}LIST;

LIST *newLIST(void);
LIST *sort(LIST *);

int main(int argc,char *argv[]){

FILE *fp;
LIST *p;
LIST *np;
LIST *npb;
LIST *head;

char namae[BUFSIZ];
int toshi,i;

if((fp=fopen(argv[1],"r"))==NULL){
printf("no file\n");
exit(1);
}

head = newLIST();
npb =head;

for(i=0;i<MENBER;i++){
np = newLIST();
fscanf(fp,"%s %d",namae,&toshi);
strcpy(np->name,namae);
np->age = toshi;

npb->next =np;
npb = np;
}

sort(head);

for(p=head->next;p != NULL;p=p->next){
printf("%s\t%d\n",p->name,p->age);
}

for(p=head->next;p != NULL;p=np){
np = p->next;
free(p);
}

fclose(fp);
return(0);
}

LIST *newLIST(){
LIST *p;
p = (LIST *)malloc(sizeof(LIST));
p->next = NULL;
return(p);
}

LIST *sort(LIST *head){
}

リスト構造のソートで悩んでます。プログラムの内容はファイルからデータをリスト構造の構造体に読み込み、名前順にソートし結果を表示する。というものです。データの追加や削除はできるのですがソートとなると頭が混乱してしまいお手上げ状態になってしまいました。。。。。
読み込み用のデータとプログラムソースを以下に記載するのでどなたか良きアドバイスをお願いしますm(_ _)m

○データ

Sakuragi
16
Rukawa
16
Miyagi
17
Akagi
18
Mitsui
18

○ソース
#include <stdio.h>
#include <std...続きを読む

Aベストアンサー

ソートするには「リストの順を入れ替える」か「リストの順は変えずにデータを入れ替える」と言う処理が必要です。

第1案 リストの順を入れ替える

リストの順を入れ替えるには、各項目のnextメンバを入れ替えます。

例えば
A→B→C→D→E
の状態でBとDを入れ替えるには
「Bを指す、A->next」と「Dを指すC->next」を入れ替え
「Bの次を指す、B->next」と「Dの次を指す、D->next」を入れ替え
と言う2つの「入れ替え」を行わなければなりません。

「B」を参照している時に「Bを指す、A->next」を知るには「Bの前は何か?」を知る必要があります。

リストの項目が少ないならば、先頭から順にサーチしていけば良いですが、項目が増えればサーチに時間が掛かり、現実的ではありません。

また、nextメンバの入れ替えが煩雑になり、あまり適切とは言えません。

第2案 データの実体を入れ替える

入れ替えの際にnextメンバを変更せず、nameメンバの内容、ageメンバの内容を入れ替えます。

この場合、ソート後に一番末尾になる項目が先頭にある、と言う場合、データの実体の入れ替えが何回も発生します。

もし「データの実体サイズ」が大きいと、メモリアクセスが膨大に発生し、実用にならない速度になります。

第3案 リストの順、データの実体は入れ替えず、リストからデータへの参照のみ入れ替える。

データ構造体とリスト構造体を分離します。

typedef struct data_t {
char name[BUFSIZ];
int age;
} DATA;

typedef struct list_t {
DATA *data;
LIST *next;
} LIST;

void swapLIST(LIST *p1,LIST *p2)
{
DATA *tp;
tp = p1->data;
p1->data = p2->data;
p2->data = p1->tp;
}

LIST *newLIST(){
LIST *lp;
DATA *dp;
lp = (LIST *)malloc(sizeof(LIST));
if(lp==NULL) return(NULL);
dp = (DATA *)malloc(sizeof(DATA));
if(dp==NULL) {free(lp); return(NULL);}
lp->data = dp;
lp->next = NULL;
return(lp);
}

void sort(LIST *top){
LIST *p1;
LSTT *p2;
for(p1=top;p1->next!=NULL;p1=p1->next){
for(p2=p1->next;p2!=NULL;p2=p2->next){
if(strcmp(p1->data->name,p2->data->name) > 0) swapLIST(p1,p2);
}
}
}

int main(int argc,char *argv[]){

FILE *fp;
LIST *p;
LIST *np;
LIST *head;

char namae[BUFSIZ];
int toshi,i;

if((fp=fopen(argv[1],"r"))==NULL){
printf("no file\n");
exit(1);
}

head = NULL;
np = NULL;

for(i=0;i<MENBER;i++){
p = newLIST();
if(p==NULL) break;/*メモリ不足*/
if(head==NULL) head=p;/*最初の1個目*/
if(np!=NULL) np->next =p;/*1つ前があるなら、1つ前のnextをpに繋げる*/
fscanf(fp,"%s %d",namae,&toshi);
strcpy(p->data->name,namae);
p->data->age = toshi;
np=p;
}

sort(head);

for(p=head;p != NULL;p=p->next){
printf("%s\t%d\n",p->data->name,p->data->age);
}

for(p=head;p != NULL;p=np){
free(p->data);
np = p->next;
free(p);
}

スワップ・ソートを行う場合、2つのリストのdataメンバのみ入れ替えれば良いので、かなり処理が軽く、この方法が一番現実的です。

なお、最初に確保するデータが無駄になっているので改良してあります。

ソートするには「リストの順を入れ替える」か「リストの順は変えずにデータを入れ替える」と言う処理が必要です。

第1案 リストの順を入れ替える

リストの順を入れ替えるには、各項目のnextメンバを入れ替えます。

例えば
A→B→C→D→E
の状態でBとDを入れ替えるには
「Bを指す、A->next」と「Dを指すC->next」を入れ替え
「Bの次を指す、B->next」と「Dの次を指す、D->next」を入れ替え
と言う2つの「入れ替え」を行わなければなりません。

「B」を参照している時に「Bを指す...続きを読む

Qファイル名である文字列からbasenameを取得したい

ファイル名である文字列からbasenameを(スマートに)取得したいです。
Perlでは何も考えなくてもできたのですが、C(もしくはC++)では次のようなやりかたしか思いつきません。
これでできているので問題ないのですが、何だかモヤモヤします。
また、このやり方では拡張子はピリオド含めて4文字であること前提なのもモヤモヤの原因です。
Perlのようにもっとスマートなやりかたはないでしょうか?

---------------------------------
char filename[] = "test.dat";
char basename[128];

strncpy(basename, filename, strlen(filename)-4);
basename[strlen(filename)-4] = '\0';
---------------------------------

Aベストアンサー

拡張子がないとか、base自体に.を含むとか、考えると、例えばVCなら_splitpath関数を使うのが一番スマートかも。

C++ならstd::string::find_last_ofで.を探して、
std::string::substrやiterator等の組み合わせで部分文字列を抽出するとか。

Q数字以外が入力されたらエラー文を出したい。

scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、無限ループが発生してしまいます。
エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを作りたいのですが、どうすれば出来るでしょうか。

Aベストアンサー

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を strtod() 関数で整数に変換します。
・このときグローバル変数の errno を調べて ERANGE なら整数値のオーバーフローが起きたとか、
 第2引数で私のポインタに変換できなくなった位置をセットしますので、このポインタが \0 文字
 以外なら数字以外(アルファベットや記号)が混ざっていることになります。
・下にそのサンプルを載せます。

サンプル:
char buff[ 256 ];
char *argp;
int value;

// 文字列で入力
scanf( "%s", buff );
value = strtol( buff, &argp, 10 ); ←10進数で変換

// ここでチェック
if ( (errno != ERANGE) && (*argp != '\0') ){
 printf( "変換不可能な文字が入力されています。\n" );
 exit( 1 );
}

その他:
・上記のサンプルを使うには errno.h をインクルードして下さい。
 このヘッダに ERANGE 定数が定義されています。
 あと stdlib.h もインクルードしないと strtol() 関数が利用できません。
・以上。下の『参考URL』もどうぞ。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/strtol.html

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を str...続きを読む

Q文字列を後ろから1文字ずつ表示する

初歩的なプログラミングです。
C言語の勉強中で、タイトルの通りの
プログラムを作りたいのですが、
何かヒントを頂けないでしょうか。

自分で書いてみて失敗したのは下記の
通りです。

char s[11];
int i=0;

printf("文字列入力(10文字以内-->)");
gets(s);
printf("s=%s",s);

while(s[i]!='\0'){
i++;
}

while(i=0){
printf("%c\n",s[i-1]);
i--;
}

宜しくお願いします。

Aベストアンサー

最後の表示部分のwhileの条件がおかしいですね。

while(i=0){
printf("%c\n",s[i-1]);
i--;
}

では、iに0を代入した真偽を見て、真ならループする様になっています。

while(i>0){
printf("%c\n",s[i-1]);
i--;
}

でうまくいくでしょう。

Q漢字のソートについて

住所録ソフトを作っています。

名字を漢字のままあいうえお順にソートしたいのですが、
常套手段があるのでしょうか?

Aベストアンサー

> strcmpだとどうしてまったく並び変わらないのでしょう?

strcmp の場合でも,まったく並び変わらないということはないと思うのですが。
状況がよく分からないのでとりあえず,
実験用に作ったコードと実行結果を載せときます。
試してみてください。

#include <stdio.h>
#include <stdlib.h>
#include <mbstring.h>
#include <string.h>

int comp(const void *x, const void *y)
{
// return _mbscmp(*(unsigned char**)x, *(unsigned char**)y);
 return strcmp(*(char**)x, *(char**)y);
}

int main(int argc, char* argv[])
{
 char *list[] = {
  "東京", "大阪", "神奈川", "愛知", "埼玉",
 };
 const int n = sizeof(list) / sizeof(list[0]);

 /* ソート */
 qsort(list, n, sizeof(list[0]), comp);

 /* 表示 */
 for (int i=0 ; i<n ; i++) {
  puts(list[i]);
 }
 return 0;
}

/* 実行結果 */
愛知
埼玉
神奈川
大阪
東京

/* 環境 */
Windows 2000 SP4, VC++ 6.0 SP5

> IMEの入力時に読みを取ることをVC++で実現するにはどうすれば良いのでしょうね?

や,だから #6 で示した URL に,
http://www.geocities.co.jp/SiliconValley-Oakland/1865/visualc/NoryImm.html
すぐに動かせるサンプルがあるのにぃ。

参考URL:http://www.geocities.co.jp/SiliconValley-Oakland/1865/visualc/NoryImm.html

> strcmpだとどうしてまったく並び変わらないのでしょう?

strcmp の場合でも,まったく並び変わらないということはないと思うのですが。
状況がよく分からないのでとりあえず,
実験用に作ったコードと実行結果を載せときます。
試してみてください。

#include <stdio.h>
#include <stdlib.h>
#include <mbstring.h>
#include <string.h>

int comp(const void *x, const void *y)
{
// return _mbscmp(*(unsigned char**)x, *(unsigned char**)y);
 return strcmp(*(char**)x, *(char**)y);
...続きを読む


人気Q&Aランキング