みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

文字列や文字から整数への変換方法について

文字列(string型)や文字(char型)から整数(int型など)に変換
する時のルールがよく解りません。
たとえば、キーボードから数字を打って、その入力された数字を
数値として整数型の変数に代入したい場合のやり方です。

ちょっとプログラムを作ってみました。

using System;

class clmain
{
private static void Main()
{
Console.Write("1桁の整数を入れてね ");
char ch = char.Parse(Console.ReadLine());
int by1 = (int)ch;
int by2 = (int)char.GetNumericValue(ch);
Console.WriteLine("by1 = {0}, by2 = {1}, ch = {1}", by1, by2, ch);

Console.Write("整数を入れてね ");
string st = Console.ReadLine();
/* by = (int)st; コンパイルエラー */
int by3 = int.Parse(st);
Console.WriteLine("by3 = {0}, st = {1}", by3, st);
}
}

まず、char型からint型への変換では、
 int型変数=(int)char型変数;
はコンパイルは通りますけど、実行すると全く違った値が入って
しまいます。たとえば char型変数の値が "1" だと、int型変数には
49 が入ります。
int型変数 = (int)char.GetNumericValue(char型変数);
と書いてようやく、思い通りの動きをしてくれます。

また、string型からint型への変換では
 int型変数=(int)string型変数;
はコンパイルエラーになります。
int型変数 = int.Parse(string型変数);
とするとコンパイル出来て正しく動きます。


これで質問ですけど、
(1)なぜstring型とchar型で、int型への変換方法が違うのでしょうか?
(2)int型変数=(int)char型変数; とすると、上に書いたように、全く
違った(希望しない)値が代入されてしまいます。これは、どういう
動きをしているのでしょうか? また、これはコンパイルエラーに
なりませんけど、どういう時にこの書き方をするのでしょうか?

解る方、お願いします。

投稿日時 - 2008-12-18 16:41:03

QNo.4565582

暇なときに回答ください

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

→(1)について
 string型はchar型やint型とは違い「準備された型」だからです。
 言ってしまえば使いやすいようにカスタムしたchar型ということ。
 ゆえに変換するときにはカスタムした分別の動作が必要になり、それをしてくれるのがParseだという訳です。

→(2)について
 int型とchar型では中に入っているデータの「表現」が異なるからです。
 わかりやすく書けば、両方をのぞいた時同じデータが入っていたとしても
 int型は中に入っているデータそのものが見えますが、
 char型は中に入っているデータから得られた文字が見える。 一枚フィルタを挟んでいるわけです
 具体的には文字コードによる変換が、なされています。49→1 65→A
 参考:http://okuyama.mt.tama.hosei.ac.jp/unix/C/slide95-1.html
 
 なのでこれが正常で、エラーにはなりません。
 言ってしまえば文字も数字もデータとはいえ、「文字」というデータはありません。数字から成り立つデータにおいて文字を表現する場合、文字に数字をふりわけてそこから表示するしか無いわけです。
 で、char型はその振り分け後のものを表現する型なので、単純に中身をintに入れてやっても違う値になると。

 こんなところで少しは参考になりましたでしょうか?

投稿日時 - 2008-12-18 17:12:37

お礼

ありがとうございます。

準備された型、カスタムした型っていうのは、構造体型
(ConsoleKeyInfoのような)って意味でしょうか?

>int型は中に入っているデータそのものが見えますが、
>char型は中に入っているデータから得られた文字が見える。 一枚フィルタを挟んでいるわけです

これはつまり、例えば1を代入したとすると、int型の変数には
0x01 が入ってるけど、char型には"1"という文字を表すASCIIコードが
(16進イメージで言うと)入ってるということでしょうか。

全然プログラミングの基礎が解ってなくて、すみません(^^ゞ
ありがとうございます。

投稿日時 - 2008-12-19 15:05:54

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

No.1です。
No.1より
>>String型はchar型やint型のような単純な方とは内部構造が違っています。
>というのは、char型やint型はその変数の中身そのものを指すけど、
>string型はその文字列が置かれてるアドレスを指すっていうような
>意味でしょうか?(別の言語でいうポインタみたいな感じなんでしょうか。)
ポインタそのものではありません。
簡単に書くと、データの入っている場所を示すポインタや文字数などの情報がまとめて入っている構造体のようなものです。

No.2より
>これはつまり、例えば1を代入したとすると、int型の変数には
>0x01 が入ってるけど、char型には"1"という文字を表すASCIIコードが
>(16進イメージで言うと)入ってるということでしょうか。
これは若干認識が違います。
「1」を入力した場合に「数値」として取得すれば、「0x01」で「文字」として取得すれば「0x31」です。
scanf()の話がでましたので以下に簡単なサンプルを書きます(空白は全角スペースなので注意)
-----------------
 inti1, i2;
 charc1, c2;

 printf( "数値で取得 = " );
 scanf( "%d", &i1 );
 scanf( "%*c" );   // CR読み捨て
 c1 = (char)i1;   // int型の内容をchar型に入れる

 printf( "文字で取得 = " );
 scanf( "%c", &c2 );
 scanf( "%*c" );   // CR読み捨て
 i2 = (int)c2;   // char型の内容をint型に入れる

 //10進数と16進数で取得内容を表示
 printf( "i1 = %3d[0x%02x] c1 = %3d[0x%02x]\n", i1, i1, c1, c1 );
 printf( "i2 = %3d[0x%02x] c2 = %3d[0x%02x]\n", i2, i2, c2, c2 );
-----------------
これを実行して結果を確認してみてください。
(手抜きなので0~9の一桁以外入れないでください)

投稿日時 - 2008-12-19 16:30:00

ANo.3

char c;
int n;
scanf("%c", &c);
でcに1桁の数字('0'~'9')を入れて、それを1桁の数値(0~9)に変換したいのであれば、
n = c - '0';
とでもすればよいのではないでしょうか。

投稿日時 - 2008-12-19 00:08:51

お礼

scanfっていうのは??
と思ってネットで調べてみたら、
System.Console.Readと同じように、標準入力から文字列を受け取る
メソッドなんですね。

>n = c - '0';

明示的に計算をするわけですね。

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

投稿日時 - 2008-12-19 15:07:51

ANo.1

(1)
String型はchar型やint型のような単純な方とは内部構造が違っています。その部分は省きますが、
>int.Parse(string型変数);
でString型に格納されている内容をint(数値)に変換して渡しているからです。

(2)
記述に従った正しい動作です。
> int型変数=(int)char型変数;
は単純に「変数型を一致させている」だけです。
char型変数に入っている内容は「文字列」でしょうから「1」は「数値」ではなく「文字」です。
「1」の文字コードは「0x31」=10進数で「49」です。
「1」という数値が必要であれば、自分で数値への変化式を書くかatoi()等の関数を使用する必要があります。

投稿日時 - 2008-12-18 17:00:58

お礼

説明ありがとうございます。
私の理解力が足りなくて、レス出来るまで時間がかかってしまいました。

>String型はchar型やint型のような単純な方とは内部構造が違っています。

というのは、char型やint型はその変数の中身そのものを指すけど、
string型はその文字列が置かれてるアドレスを指すっていうような
意味でしょうか?(別の言語でいうポインタみたいな感じなんでしょうか。)

>「1」の文字コードは「0x31」=10進数で「49」です。

これはとてもよく解りました!
そういう代入をしてしまうんですね。
コンパイルの時に、せめて警告でも出して欲しいです(^_^;)

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

投稿日時 - 2008-12-19 15:01:00