変数に文字を代入できません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
細胞

変数に文字を代入できません

#1

投稿記事 by 細胞 » 13年前

c言語のアドレスや文字列について勉強しようと思い、いろいろなサイトから、プログラムをコピペしたりして遊んでいたのですが、少しわからないところがありました。

ーーーーー変数aに文字を代入してprintfで表示させるプログラムーーー
#include <stdio.h>

int main(){
char a;
a = 'む'; /* aに'む'を代入 */
printf("%c\n",&a);
return 0;
}

ーーーーーーーーー実行結果ーーーーーーーーーーー

続行するには何かキーを押してください . . .
ーーーーーーーーーーーーーーーーーーーーーー

ほかの文字を試してみたのですが、でたらめな文字ばかりが出てきます。
どういうことなのか教えてください。よろしくおねがいします。

OSはwindousで
visual c++を使っています

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 変数に文字を代入できません

#2

投稿記事 by softya(ソフト屋) » 13年前

幾つか問題があります。
・コンパイラや環境に依存しますが、文字コードとして、ただcharだけの場合は英数字=1バイト文字しか扱えませんので漢字のような多バイト文字は扱えません。
・文字表示なのにアドレスを渡しています。変数をそのまま書いてください。

英数字なら問題ありませんので、下記のようにしてみてください。

コード:

#include <stdio.h>
int main(){
	char a;
	a = 'm'; /* aに'm'を代入 */
	printf("%c\n",a);//aの文字を表示
	return 0;
}
codeタグをご利用下さい。ソースコードが見やすくなります。
詳しくはフォーラムルールを御覧ください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

たかぎ
記事: 328
登録日時: 13年前
住所: 大阪
連絡を取る:

Re: 変数に文字を代入できません

#3

投稿記事 by たかぎ » 13年前

やりたいことは、もしかしてこういうことなのかも知れませんね。

コード:

#include <stdio.h>
#include <locale.h>

int main(){
  wchar_t a;
  a = L'む';	 /* aに'む'を代入 */
  setlocale(LC_CTYPE, "");
  printf("%lc\n",a);
  return 0;
}

細胞

Re: 変数に文字を代入できません

#4

投稿記事 by 細胞 » 13年前

つまり、全角文字は2バイト使うから、char型の1バイトしか代入できない変数に代入できないということですね。

あと、これでもできました。

コード:

#include <stdio.h>

int main(){
        char* a;	//ポインタ変数
        a = "む";		/* aに'む'のアドレスを代入 */
        printf("%s\n",a);
        return 0;
}

box
記事: 2002
登録日時: 13年前

Re: 変数に文字を代入できません

#5

投稿記事 by box » 13年前

a が char 型の配列である場合はどうなるでしょうか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

細胞

Re: 変数に文字を代入できません

#6

投稿記事 by 細胞 » 13年前

返信ありがとうございます。(お礼いうの忘れていました)

えーとですね、さっき自分がやったのが、aをポインタ変数にして、’む’のアドレスを代入したのに対して、
aをchar型の配列ってことは、1バイトのchar型変数を置くメモリが、複数確保されたってことですよね

コード:

#include <stdio.h>

int main(){
        char a[10];	//配列変数
        a[0] = 'S';		/* aに'A'を代入 */
        a[1] = 'O';		/* aに'A'を代入 */
        a[2] = 'N';		/* aに'A'を代入 */
        a[3] = 'G';		/* aに'A'を代入 */

        printf("%c%c%c%c\n",a[0],a[1],a[2],a[3]);
        return 0;
}
1バイトの配列でも、ひらがなや漢字などの2バイトの文字は扱えないですよね?

ここまでのことに間違えてることがあったら教えてください。お願いします

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 変数に文字を代入できません

#7

投稿記事 by softya(ソフト屋) » 13年前

細胞 さんが書きました:1バイトの配列でも、ひらがなや漢字などの2バイトの文字は扱えないですよね?

ここまでのことに間違えてることがあったら教えてください。お願いします
多バイト文字を扱う方法の一つがたかぎさんが示されたワイド文字を使う方法です。
あと2バイトと決め付けられているみたいですが、文字コードによっては2バイト以上の文字コードもあります。
例えば、UNICODEとSJISは2バイトですがUTF-8は2バイトを超えることがあります。UNICODEの場合は1バイトの文字コードがありません。

ちなみに上のコードは下記のようにすれば文字列として出力できます。

コード:

#include <stdio.h>
 
int main(){
        char a[10]; //配列変数
        a[0] = 'S';     /* aに'A'を代入 */
        a[1] = 'O';     /* aに'A'を代入 */
        a[2] = 'N';     /* aに'A'を代入 */
        a[3] = 'G';     /* aに'A'を代入 */
        a[4] = '\0';	/* 文字列終端	*/
 
        printf("%s\n",a);
        return 0;
}
マルチバイト文字の漢字は次のように代入できます。

コード:

#include <stdio.h>
 
int main(){
        char a[10]; //配列変数
        a[0] = ('む'>>8)&0xff;     /* aに'む'の上位バイトを代入 */
        a[1] = ('む')&0xff;     /* aに'む'を下位バイトを代入 */
        a[2] = '\0';    /* 文字列終端  */
 
        printf("%s\n",a);
        return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

box
記事: 2002
登録日時: 13年前

Re: 変数に文字を代入できません

#8

投稿記事 by box » 13年前

細胞 さんが書きました: 1バイトの配列でも、ひらがなや漢字などの2バイトの文字は扱えないですよね?
1バイトの配列、っていうのが何を指してるのかよくわからないですが、
char a[10];
という配列があるとして、softyaさんが書かれた(ビットシフトあたりは、しきいが高そうな感じがしますね)
のとは別の方法で、配列aに「む」を入れるにはどうすればよいか、
書籍やネットの情報をあさってみてはどうでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

細胞

Re: 変数に文字を代入できません

#9

投稿記事 by 細胞 » 13年前

char a='A'; は、変数aを宣言して'あ'を代入するということになってるけど、
実際は、メモリのどこかに1バイト確保して、'あ'の文字コードを代入して、aという名前でアクセスできるようにした。

char a[3];なら、メモリに間隔を置かずに、並べて、3バイト確保して、それぞれa[0]と、a[1]と、a[2]の名前でアクセスできるようにした。

という理解でいいですか?

もし、メモリのことを意識できなかったとしたら、
変数というものは数字や文字を入れる箱で、配列変数は、その箱を数字をつけて、たくさん作るという理解だったとしたら、

コード:

#include <stdio.h>
 
int main(){
        char a[10]; //配列変数
        a[0] = ('む'>>8)&0xff;     /* aに'む'の上位バイトを代入 */
        a[1] = ('む')&0xff;     /* aに'む'を下位バイトを代入 */
        a[2] = '\0';    /* 文字列終端  */
 
        printf("%s\n",a);
        return 0;
}
a[0]とa[1]は別々のものだから、この↑プログラムを見て、「'む'の文字コードを2分割して、2つの箱に入れても、バラバラになってprintf命令が正しく機能しないんじゃない?」ということになりますよね

box
記事: 2002
登録日時: 13年前

Re: 変数に文字を代入できません

#10

投稿記事 by box » 13年前

細胞 さんが書きました:char a='A'; は、変数aを宣言して'あ'を代入するということになってるけど、
実際は、メモリのどこかに1バイト確保して、'あ'の文字コードを代入して、aという名前でアクセスできるようにした。
'A'
の話をしてるんだか
'あ'
の話をしてるんだか
よくわからないので退散します。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 変数に文字を代入できません

#11

投稿記事 by softya(ソフト屋) » 13年前

配列は連続したメモリ空間にアクセスできるという規則というか規約があります。なので、char型配列は文字列を格納する事が出来ます。
改めて定義すると
・charは英数字は1文字を格納するための変数です。
・char型配列は英数字が複数連続した文字列を格納する事が出来ます。
・文字列は'\0'で終っていなくてはいけません。'\0'が文字列の終りとして判断されるためです。
なので、"aaa"と書いた場合も"aaa\0"と書いた物とみなされます。

で、Windowsに限定すると英数字は1バイトの文字コードです(コンピュータ・システムによっては1バイトでないシステムが存在します)。
マルチバイト文字(SJIS)では、漢字は2バイトの文字コードです。
'む'と書いた場合は実は2バイトの文字コードとしてちゃんと定義されていますが、
a[0] = ’む';
と書くと上位1バイトが捨てられて下位バイトだけ代入されます。charは1バイトですからね。
なので私は明示的に
a[0] = ('む'>>8)&0xff; /* aに'む'の上位バイトを代入 */
a[1] = ('む')&0xff; /* aに'む'を下位バイトを代入 */
と書きました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

たかぎ
記事: 328
登録日時: 13年前
住所: 大阪
連絡を取る:

Re: 変数に文字を代入できません

#12

投稿記事 by たかぎ » 13年前

若干softyaさんに補足すると...
softya(ソフト屋) さんが書きました:・文字列は'\0'で終っていなくてはいけません。'\0'が文字列の終りとして判断されるためです。
なので、"aaa"と書いた場合も"aaa\0"と書いた物とみなされます。
(C++ではなく)Cの場合はちょっと違います。

コード:

char s[3] = "aaa";
と書くと、末尾にナル文字は付加されません。
これをどう扱うかは、プログラムしだいです。
softya(ソフト屋) さんが書きました:で、Windowsに限定すると英数字は1バイトの文字コードです(コンピュータ・システムによっては1バイトでないシステムが存在します)。
全角英数字のようなものは別ですが、基本実行文字集合に属している文字であれば、処理系によらずchar型の正の範囲に必ず収まります(ただし、非標準処理系の場合は知らない)。

閉鎖

“C言語何でも質問掲示板” へ戻る