NULLを認識しません。

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

NULLを認識しません。

#1

投稿記事 by hiro » 18年前

はじめまして。
下記のプログラムでNULLを認識してプログラムが入力行数を出力して終わるようにしたいのですが、
NULLを認識せずいつまでもループになってしまいます。
どこがわるいのでしょうか?
#include <stdio.h>
main()
{
char a[81];
int n = 0;
while(gets(a) != NULL)
{
n++;
puts(a);
}
printf("\n lines = %d\n",n);
}

box

Re:NULLを認識しません。

#2

投稿記事 by box » 18年前

> NULLを認識せずいつまでもループになってしまいます。

Windowsをお使いでしたら、Ctrl+Z で入力を終了させてください。

hiro

Re:NULLを認識しません。

#3

投稿記事 by hiro » 18年前

boxさん
返答ありがとうございます。
こちらも、Ctrl+Zで止めていました。
プログラム的にはどうでしょうか?

hiro

Re:NULLを認識しません。

#4

投稿記事 by hiro » 18年前

先の返信でマークを雑談にいれていました。
どなたかプログラムの悪いところを教えてください。

Justy

Re:NULLを認識しません。

#5

投稿記事 by Justy » 18年前

どなたかプログラムの悪いところを教えてください。
 NULLを認識していないとのことでしたが、特に悪いところは見あたりません。
 正しく gets()の戻り値の NULLを認識しています。
 だから Ctrl+Zでループをぬけることができるわけで。

hiro

Re:NULLを認識しません。

#6

投稿記事 by hiro » 18年前

justyさん
返答ありがとう御座います。
てっきり、入力を何もせずにエンターキーを返せば終わるものと思っていました。
エンターキーで終わる方法はないのでしょうか?

Justy

Re:NULLを認識しません。

#7

投稿記事 by Justy » 18年前

 なるほど。ではこうして見てください。
[color=#d0d0ff" face="monospace] while(gets(a) != NULL) 
    {
        if(!strlen(a))
            break;
        n++; 
        puts(a); 
    }[/color]

GPGA

Re:NULLを認識しません。

#8

投稿記事 by GPGA » 18年前

では私はこんなプログラムで。
char* p;
    while ((p = gets(a)) != NULL && *p != '\0')
    {
        n++; 
        puts(a); 
    }
 

hiro

Re:NULLを認識しません。

#9

投稿記事 by hiro » 18年前

justyさん
GPGAさん
いろいろと考えて頂きありがとうございます。
正常に動作致しました。

さらに、頂いた返事をもとに内容を考えてみました。

justyさんの回答では、NULLは無くても良いと分かりましたので下記のようにプログラムを変更しました。

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

main()
{
char a[81];
int n = 0;
while(!!strlen(gets(a)) != '\0')

{
n++;
puts(a);
}
printf("\n lines = %d\n",n);
}


また、GPGAさんに頂いた回答についても、同様にNULLの部分がいらないように思えたので下記のように変更してみました。

#include <stdio.h>

main()
{
char a[81];
int n = 0;
char* p;
while((p = gets(a)) && *p != '\0' )

{
n++;
puts(p);
}
printf("\n lines = %d\n",n);
}

結局、どちらについてもNULLは無くなってしまいました。
(プログラムの'\0'の部分をNULLにすると参照の型が違うと言うワーニングメッセージがでます。)

別に作ったデータファイルの内容を参照するプログラムではNULLは正常に動きましたが、キーボード入力ではなぜ正常に動かないのでしょうか?

NULLの扱い方についてさらに教えて頂ければ幸いです。

keichan

Re:NULLを認識しません。

#10

投稿記事 by keichan » 18年前

NULLの使い方というよりはgets関数の使い方をきちんと確認してください。

MSDNでは
> gets関数は、stdin標準入力ストリームから行を読み取り、bufferに格納します。行は最初の改行文字(\n)までのすべての文字で構成されています。
> その後、getsは、改行文字をnull文字(\0)に置換してから行を返します。

とあります。
NULLが必要なのはgetsではなくfgetsの方だと判断できますね^^

GPGA

Re:NULLを認識しません。

#11

投稿記事 by GPGA » 18年前

> NULLの部分がいらないように思えたので
NULLチェックがなくなると Ctrl+Z で終了させることが
できなくなってしまいますが、いいのでしょうか?

> (プログラムの'\0'の部分をNULLにすると参照の型が違うと言うワーニングメッセージがでます。)
'\0'とNULLは別物です。

NULLは大抵の処理系では以下のように宣言されています。
#define NULL ((void *)0)

一方 \0 は文字列の終端コードです。
gets関数はエラーの場合はNULLを返しますが
正常終了したときは引数と同じポインタを指します。
つまり

p = gets(a);

が正常終了した場合、

p == a

が成り立ちます。
何も入力せずにENTERを押した場合、a[0]に 終端コードである '\0' が入ります。

a[0] == *(a + 0) == *a == *p

なので、whileのチェックで

*p != '\0'

の一文を入れているわけです。

> 別に作ったデータファイルの内容を参照するプログラムではNULLは正常に動きましたが、キーボード入力ではなぜ正常に動かないのでしょうか?
それは fgets関数を使用したプログラムですか?
そうである場合、fgets関数はファイルの終端に来た場合にNULLを返すからです。
キーボードからの場合、通常の入力では終端というものがありません。
Ctrl+Zが押されたときが、終端と考えてください。

管理人

Re:NULLを認識しません。

#12

投稿記事 by 管理人 » 18年前

きっとhiroさんは終端コードを「ヌル文字」と習ったのでNULLと混合しているのではないでしょうか。
ヌル文字である\0は間違うようなら「終端コード」「終端記号」と呼ぶといいと思います。

http://www.bohyoh.com/CandCPP/C/Library/gets.html

この辺を見ると、関数の値が何が返ってくるのかよくわかります。

hiro

Re:NULLを認識しません。

#13

投稿記事 by hiro » 18年前

keichanさん
GPGAさん
管理人さん
なんとなく分かった気がしてきました。
どうも、NULLとNULL文字を同じものとして、使い方を誤解していたようですね。
いろいろとありがとうございました。
これからも宜しくお願い致します。

閉鎖

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