C言語関係掲示板

過去ログ

No742 getcharは何故int 型を返すか

[戻る] [ホームページ]
No.9237

getcharについて
投稿者---あわ(2003/09/08 22:37:46)


ネット上で下のようなソースがあったのですが
getcharを使う場合はint 型で宣言しなければならないと
講座に書いてあったと思うのですが、このプログラムでは
char型で宣言しています。これはどういうことなのでしょうか?
このプラグラムは文字を入力して、例えば0を入力するとmを出力
1を入力するとnを出力させるというプログラムです。
どうかご教授お願いします。

#include <stdio.h>

int main (void)
{
    char *src = "0123456789ABCDEFGHIJ";
    char *des = "mno9pqrs4tuv0wxyABCD";
    char c, *p;
    int  i, find;

    while ((c = getchar()) != EOF) {
        i = 0;
        p = src;
        find = 0;
        while (*(src + i)) {
            if (c == *(src + i)) {
                find = 1;
                putchar(*(des + i));
                break;
            }
            i++;
        }
        if (! find)
            putchar(c);
    }
}



No.9238

Re:getcharについて
投稿者---YuO(2003/09/08 22:56:03)


>ネット上で下のようなソースがあったのですが
>getcharを使う場合はint 型で宣言しなければならないと
>講座に書いてあったと思うのですが、このプログラムでは
>char型で宣言しています。これはどういうことなのでしょうか?

たぶん,書いた人が無知なのでしょう。
原因不明の状況に陥りたくなければ,int型で宣言しておくのが無難です。

ここにも理由が書いてありますし,
C FAQ 12.1 : http://www.catnet.ne.jp/kouno/c_faq/c12.html#1
にも書いてあります。

ネット上のソースは玉石混交ですので,鵜呑みにするのは危険です。


No.9239

Re:getcharについて
投稿者---あわ(2003/09/08 23:20:08)


ありがとうございました。
大学関係のページだったことと、以前にもcharを使っているのを
みたことがあったので、charを使わないといけない場合もあるのかと
思ってしまいました。

No.9240

Re:getcharについて
投稿者---mtk(2003/09/08 23:27:41)


>char型で宣言しています。これはどういうことなのでしょうか?

良くないと思います。
次のプログラムを見れば、理由が良く分かります。

#include <stdio.h>

int main(void)
{
    int ___EOF = -1;
    unsigned char c = ___EOF;

    if (c == ___EOF)
        puts("true");
    else
        puts("false");
    return 0;
}



No.9241

Re:getcharについて
投稿者---あわ(2003/09/09 00:03:33)


char型だとダメな例を示してくれてありがとうございました。

No.9242

Re:getcharについて
投稿者---かずま(2003/09/09 00:10:39)


while の != EOF が正しく評価されるためには、int c; でないといけません。

しかし、c == *(src + i) が正しく評価されるためには、

(char)c == *(src + i) または
c == (unsigned char) *(src + i) または
c == *(unsigned char *)(src + i) または
c == *((unsigned char *)src + i) または
c == *(src + i) & 0xFF と書かないといけない場合があるでしょう。

文字コードがシフトJIS で、char *src = "アイウエオ...."; の場合などがそうです。

*(src + i) は間違いではありませんが、src[i] と書くほうが見やすくないですか。


No.9245

Re:getcharについて
投稿者---mtk(2003/09/09 13:54:37)


http://www.linux.or.jp/JM/html/LDP_man-pages/man3/getchar.3.html

上から抜粋
fgetc(), getc(), getchar() は文字を unsigned char として読んで,
int にキャストして返すか、ファイルの終りを EOF として返すか、
エラーを返す。

なぜ、char で読み込まないのでしょうか?そうすれば、かずまさんの
おっしゃっている事をプログラマは考えずにすみますのに。

知っている人がいれば教えてください。

No.9246

Re:getcharについて
投稿者---mtk(2003/09/09 13:59:26)


>知っている人がいれば教えてください。

すみません。分かりました。

EOF は負の汎整数型定数だそうです。

No.9258

Re:getcharについて
投稿者---かずま(2003/09/10 14:10:23)


> EOF は負の汎整数型定数だそうです。

EOF を使わなければ、char c; でもかまわないでしょう。
#include <stdio.h>

int main (void)
{
    char *src = "0123456789ABCDEFGHIJ";
    char *des = "mno9pqrs4tuv0wxyABCD";
    char c;
    int i;

    while (c = getchar(), !feof(stdin)) {
        for (i = 0; src[i] && c != src[i]; i++) ;
        putchar(src[i] ? des[i] : c);
    }    
    return 0;
}


No.9276

Re:getcharについて
投稿者---mtk(2003/09/10 20:20:59)


すみません。言葉足らずな質問でした。

自己レス
>なぜ、char で読み込まないのでしょうか?そうすれば...

というのは、かずまさんへではなくて標準ライブラリ(getchar)へ言ったものでした。

ところで、feofでの判定を使えば、戻り値を気にしなくてもいいですね。
これからはこれを使います。



No.9277

Re:getcharについて
投稿者---mtk(2003/09/10 20:49:59)


>ところで、feofでの判定を使えば、戻り値を気にしなくてもいいですね。
>これからはこれを使います。

エラーの時も EOF を返すのでやっぱりやめます。(たまには使うかも)

No.9247

Re:getcharについて
投稿者---YuO(2003/09/09 14:37:54)


>上から抜粋
>fgetc(), getc(), getchar() は文字を unsigned char として読んで,
>int にキャストして返すか、ファイルの終りを EOF として返すか、
>エラーを返す。
>なぜ、char で読み込まないのでしょうか?そうすれば、かずまさんの
>おっしゃっている事をプログラマは考えずにすみますのに。

前に挙げたC FAQに理由が書いてありますが……。

char型が8bit/符号無しの処理系を考えます。
ついでに,文字コードとしてISO-8859-1を考えます。

まず,char型が表せる値は0x00〜0xFFです。
次に,文字コードが利用する値も,0x00〜0xFFです。
従って,unsigned char型を返すと,EOFが何れかの文字と重なってしまいます。

なので,int型を戻り値として利用する必要があるのです。


まぁ,これも不完全といえば不完全ですが……。
例えば,intが16bitの時に文字コードとしてUTF-16を使うと,
char型も16bitになるので,上記と同じことが起こり得ます。
まぁ,UTF-16の場合は0xFFFFのように使っていない文字コードがあるので,
それをEOFに割り当てる,という手段がありますが。