文字列と配列、関数について

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

文字列と配列、関数について

#1

投稿記事 by しろ » 15年前

こんにちは。昨日の投稿に続けての質問になります。

どうも文字列の扱いに自信がなく(「やさしいC」という本を読みましたが、いろいろと説明が載ってない!)、以下の質問をさせていただきます。ちょっと長くなってしまいますが、お許しください。

http://karetta.jp/book-node/game-programming/235064

に以下のプログラムが記載されています。

-----

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

//SHIFT_JISの場合,上位バイトが0x81~0x9F、0xE0~0xFCの範囲に収まる

//code が日本語であるか判定する
//戻り値 1:日本語 0:日本語ではない
int isJapaneseCharacter(unsigned char code)
{
if( (code >= 0x81 && code <= 0x9F) ||
(code >= 0xE0 && code <= 0xFC) ) {
return 1;
}
return 0;
}

int main()
{
char check_first[3] = "え";
char check_second[3] = "下";
char check_third[3] = "h";

printf("「え」の場合, %d\n", isJapaneseCharacter( check_first[0] ) );
printf("「下」の場合,%d\n", isJapaneseCharacter( check_second[0] ) );
printf("「h 」の場合,%d\n", isJapaneseCharacter( check_third[0] ) );

return 0;
}

-------

質問1

char check_first[3] = "え";
char check_second[3] = "下";
char check_third[3] = "h";



char check_first[2] = "え";
char check_second[2] = "下";
char check_third[1] = "h";

でも問題ないでしょうか?(「え」と「下」は2バイト文字、「h」は1バイト文字なので、という理解です)

--------

質問2

isJapaneseCharacter( check_thire[1] )でcheck_first[0] をcodeに渡している。
つまりcode='h'となっている。

ここで理解できないのが

code >= 0xE0という表記です。そもそも0xE0というのはポインタを表している(のだろう)と思うのですが、codeはあくまでcode='h'であり、ポインタを表すものではないような気がします。

質問3、たとえば以下のプログラムを作成したとき

---------------



#include <stdio.h>

void bcd(char *c){

printf("%s",c);
    printf("%p",&c[0])

}

int main(void)
{
char a[/url]="hello";

bcd(a);


return 0;
}


-----------------
これは配列a[/url]の先頭のポインタを引き渡すことでcを配列a[/url]とみなすんですよね(みなすという言い方はおそらく間違っていると思いますが、うまい表現が思い浮かびませんでした)。

(ちなみにちょっと話がそれますが「やさしいC」には配列とポインタが「密接な関係」にあるとき、ポインタを配列として扱うことができるとありました。「密接な関係」を参考所内で定義していないのでいったいなんのことなのかさっぱりでしたが、まぁ上のような感じで理解しています)

話がごちゃごちゃしてきましたが、要は質問2の部分がわかりません。参考書にあんまり詳しく載っていないこともあり、文字列についての理解があやしく、質問3も果たして自分の理解があっているのか疑問で質問させていただきました。

よろしくお願いいたします。

toyo

Re:文字列と配列、関数について

#2

投稿記事 by toyo » 15年前

回答1
" "で囲まれた文字列は最後に文字列の終わりを示すナル文字('\0')が存在します
"え", "下"は3バイト、"h"は2バイトの領域が必要です
char check_first[2] = "え";
        char check_second[2] = "下";
        char check_third[1] = "h";
は問題ありです。

回答2
0xE0はポインタではありません。
単なる整数の16進表記です。
(code >= 0xE0 && code <= 0xFC)

(code >= 224 && code <= 252)
と同じです。

回答3
確かに関数の引数に配列を渡すとポインタになりますが
配列とポインタはまったく別物と考えた方がいいと思います。
C言語ではこの辺の理解が一番難しい部分ではあります。

たかぎ

Re:文字列と配列、関数について

#3

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

シフトJIS限定であれば、

> char check_first[2] = "え";
> char check_second[2] = "下";
> char check_third[1] = "h";

これでも問題ないといえばないのですが、わかっていてやるならよいのですが、そうでなければ避けた方がよいでしょう。
シフトJISに決め打った最適化も然りです。
できれば、

char check_first[/url] = "え";
char check_second[/url] = "下";
char check_third[/url] = "h";

このようにする方が無難です。

しろ

Re:文字列と配列、関数について

#4

投稿記事 by しろ » 15年前

ご回答いただき、ありがとうございます。

>toyoさん

char型を16進数表記するとはいったいどういうことでしょうか?

これはchar a='c';のような文字だけではなく
char a="hello"などとした場合も同じようにaを16進数表記できるということでしょうか?
あと、上記のプログラムのように不等号をchar型の16進数表記したものに使っても問題ないですか?

(不等号は単なる「数字」の大小だけではなく、char型の16進数した場合の「数値」でも使用してOKということでしょうか?)

>toyoさん、たかぎさん

char check_first[/url] = "え";
char check_second[/url] = "下";
char check_third[/url] = "h";

と書く表記方法ですが、よくキーボードからの打ち込んだ文字列を格納する場合

char a[100];

などとして、「文字を多めに打ち込んでも問題ないように」と参考書等に書いてありますが、
a[/url]のようにすれば、どんなときでも問題ない、ということでしょうか?

本によっては結構混在しているのですが、使い分けについては特に記載がなかったもので……

(おそらくは)初歩的な質問(であろう)ばかりで申し訳ございません。よろしくお願いいたします。

たかぎ

Re:文字列と配列、関数について

#5

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

> a[/url]のようにすれば、どんなときでも問題ない、ということでしょうか?

そんなことはありません。
配列に書き込む場合は、必要な大きさを確保してください。
ただ、どんなに大きめに確保しても、あふれる可能性は常にあります。
結局は配列のサイズが足りない場合の処理も書かないといけませんので、極端に小さい場合を除けば、実行速度とメモリ使用量の効率に関わる問題でしかありません。
(初学者が勉強している間は、そこまで気を使わなくてもよいのかもしれませんが...)

toyo

Re:文字列と配列、関数について

#6

投稿記事 by toyo » 15年前

char型は確かにcharacter(文字)で誤解を招くことがありますが実体はint型と同じ整数型の一種です
1バイトが8ビットの環境では符号つきchar型は-128から127までの整数を扱えます
昔のコンピュータの世界では英数文字その他で127文字もあれば事足りたので文字を扱う型にchar型と名前をつけただけだと思います
char a = 'c';
は人間にわかりやすく文字で書いているだけでコンピュータにとっては'c'もただの整数としか認識してないのです
char a = "hello"
は型が違うのでエラーになります(整数型にポインタを代入している)

char check_first[/url] = "え";
のように宣言と同時に初期化をする場合、配列の数を指定しないとコンパイラが必要な分だけ自動的に確保してくれます
長い文字列で初期化するときいちいち文字数を数えなくていいし数え間違えてバグることもありません。

たかぎ

Re:文字列と配列、関数について

#7

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

> char a = "hello"
> は型が違うのでエラーになります(整数型にポインタを代入している)

未定義の動作になる場合もありますが(ならない場合もあります)、エラーになるとは限りませんね。
# C++なら、コンパイルエラーになりますが...

しろ

Re:文字列と配列、関数について

#8

投稿記事 by しろ » 15年前

>たかぎさん、とよさん

ご教授ありがとうございます。

・配列に書き込む場合は、必要な大きさを確保
・それ以外に配列に文字列を代入する場合は、a[/url]のように自動的に確保してもらう

という認識でいいわけですね。

なおchar a = "hello" は書き間違いでした。
(あと"hello"はポインタなんですね!)

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

たかぎ

Re:文字列と配列、関数について

#9

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

> (あと"hello"はポインタなんですね!)

違います。
"hello"はchar[6]という配列型です。
配列型は、多くの演算において、暗黙的にポインタ型に変換されるというだけのことです。

しろ

Re:文字列と配列、関数について

#10

投稿記事 by しろ » 15年前

なるほど!

理解できました! 重ね重ねありがとうございます!

閉鎖

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