C言語関係掲示板

過去ログ

No.259.入力文字列が数字以外のときは、エラーを繰り返す


No.1563

isdigit関数。。
投稿者---チェリー(2002/05/21 21:47:54)


入力した文字列strの文字列が数字以外のときは、エラー表示を繰り返すという処理を書きたいです。
演習2を参考にさせていただいたのですがよくわかりません。
if(isdigit((unsigned char))str[0])!=0)の部分、真・偽の判定とエラーフラグの立て方のを詳しく説明いただきたいです。



No.1566

Re:isdigit関数。。
投稿者---ともじ(2002/05/21 23:08:15)


こんばんは。

>入力した文字列strの文字列が数字以外のときは、エラー表示を繰り返すという処理を書きたいです。
>演習2を参考にさせていただいたのですがよくわかりません。
>if(isdigit((unsigned char))str[0])!=0)の部分、真・偽の判定とエラーフラグの立て方のを詳しく説明いただきたいです。

isdigitという関数は、引数が'0'〜'9'以外の時には0以外の値を返却
します。ですから、上記の場合、str[0]が'0'〜'9'のときに真になります。

この演習は、次の流れで実行されています。

(1) 入力文字列の先頭のチェック
  '+' か '-' か '0'〜'9' ならOK
 ◆'.' なら小数点とみなす
  ´以外はエラー
(2) 入力文字列の2つ目から最後までループしてチェック
  '0'〜'9'ならOK
 ◆'.' なら小数点とみなす
  ´以外はエラー
(3) 最終的なチェック
  '.' が0個なら整数
 ◆'.' が1個なら実数
  '.' が2個以上ならエラー

それから、実はキャストは不要に思い、先ほど削除してしまいました。
キャストはあってもなくてもかまわないと思います。



No.1567

Re:isdigit関数。。
投稿者---チェリー(2002/05/21 23:26:16)


丁寧な解説ありがとうございました。
かなり、初歩的な質問申し訳ありませんが、ひきつづき演習2で、
if ( isdigit((int)str[0])!=0) {
err=0;←ここは先頭文字が数字のときですよね?errが0
になりwhile(err!=0)を抜けてしまうと思うのですがフラグの返しとその判定がわからないので、教えてください。


No.1570

Re:isdigit関数。。
投稿者---ともじ(2002/05/22 00:12:32)


>丁寧な解説ありがとうございました。
>かなり、初歩的な質問申し訳ありませんが、ひきつづき演習2で、
> if ( isdigit((int)str[0])!=0) {
> err=0;←ここは先頭文字が数字のときですよね?errが0
> になりwhile(err!=0)を抜けてしまうと思うのですがフラグの返しとその判定がわからないので、教えてください。

チェリーさんが言っているプログラムは問2ですよね。
while(err!=0) ではなく while(err==0) ではありませんか。

No.1577

Re:isdigit関数。。
投稿者---チェリー(2002/05/22 06:56:49)


すみません。少し、演習2を変えさせていただいて、受け取った文字列の中に数字以外が入っているか、その数が負の数・5桁になるときは、エラー表示をしつづけるというプログラムを作ったのです。で、その自分のプログラムで、実行上、上手くエラー表示はできたとおもうのですが#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(void)
{
char str[128];
int i,err;
int year;
while(err!=0)
{
printf("エラー表示");
gets(str);
/* 先頭文字の判定 */
if ( isdigit((int)str[0])!=0) {
err=0;
}

else {
err=1;
}

/* 2文字目以降の判定 */
i = 1;
while (err==0 && str[i] != '\0') {
if (isdigit((int)str[i])==0) {
err++;
}
i++;
}
year=atoi(str);
if(year<0||year>9999)
{
err=1;
continue;
}

}
return(0);
}
エラーフラグの意味がわかりません…それとも、このプログラムはたまたま上手くいっただけなのでしょうか?

No.1578

Re:isdigit関数。。
投稿者---ともじ(2002/05/22 10:49:25)


>すみません。少し、演習2を変えさせていただいて、受け取った文字列
>の中に数字以外が入っているか、その数が負の数・5桁になるときは、
>エラー表示をしつづけるというプログラムを作ったのです。

数値のみのチェックをするのでしたら、先頭と2文字目以降の区別は
不要ですね。ご提示のプログラムのようにまずとりあえず入力をしてから
チェックをする場合は、do〜whileの方がすっきりすると思います。
それから、最初に
> int i,err;
> int year;
> while(err!=0)
としていますが、これですと、errが不定値のままwhileで判定して
いますので、errに0が入っていると、処理が行われません。
do〜whileを用いて少しすっきりさせたものを下に提示してみます。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
	char str[128];
	int i,err;
	int year;

	do {
		printf("年を入力してください : ");
		gets(str);
		i = 0;
		err = 0;
		/* 数値チェック */
		while (err==0 && str[i] != '\0') {
			if (isdigit(str[i])==0) {
				err++;	/* 数値以外はエラー */
			}
			i++;
		}
		/* 全部数値なら内容チェック */
		if (err == 0) {	
			year = atoi(str);
			if (year<0 || year>9999) {
				err = 1;	/* 負数、5桁以上はエラー */
			}
		}
		if (err != 0)
			printf("エラーです\n");
			
	} while (err != 0);	/* エラーならは再入力 */
	
	printf("year : %d\n",year);

	return(0);
}



No.1579

Re:isdigit関数。。
投稿者---チェリー(2002/05/22 16:18:08)


本当に、ありがとうございました。
エラーフラグの立て方と、whileの条件式の真偽の判定とを再度勉強して、説明いただいたソース実行させていただき、勉強します。なにぶん、質問が拙いために、ご迷惑おかけしました。。

No.1580

Re:isdigit関数。。
投稿者---チェリー(2002/05/22 17:32:27)


何度も申し訳ないです。
どうしても、エラーフラグとループがわかりづらくて、困ってます。
受け取った最初の文字列の先頭が0のとき、エラーで再入力を促したいのですが、以下自分が修正したプログラムでは、「09」と入力したとき、再入力を促せるのですが、その次に「1234」と入力すると、本当は、year:1234としたいのに、また、再入力になってしまいます…どうすればよろしいのでしょうか?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(void)
{
char str[128];
int i,err;
int year;

do {
printf("年を入力してください : ");
gets(str);

err = 0;
if(str[0]="0")←ここで、先頭文字が0のときは、再入力を促したいのですが
{
err=1;
}
i=1;
/* 数値チェック */
while (err==0 && str[i] != '\0') {
if (isdigit(str[i])==0) {
err++; /* 数値以外はエラー */
}
i++;
}
/* 全部数値なら内容チェック */
if (err == 0) {
year = atoi(str);
if (year<=0 || year>9999) {
err = 1; /* 負数、5桁以上はエラー */
}
}

} while (err != 0); /* エラーならば再入力 */

printf("year : %d\n",year);

return(0);
}


No.1581

Re:isdigit関数。。
投稿者---ともじ(2002/05/22 19:47:24)


こんばんは。

>受け取った最初の文字列の先頭が0のとき、エラーで再入力を促したい
>のですが、以下自分が修正したプログラムでは、「09」と入力したと
>き、再入力を促せるのですが、その次に「1234」と入力すると、
>本当は、year:1234としたいのに、また、再入力になってしまいます…

> if(str[0]="0")←ここで、先頭文字が0のときは、再入力を促したいのですが

""で囲むと、1文字でも文字列のことになり、アドレスを比較することに
なってしまいます。
if(str[0]=='0') に直してみてください。


No.1583

Re:isdigit関数。。
投稿者---チェリー(2002/05/22 20:32:41)


本当にありがとうございました。
char strなので、文字列だと思い""でくくったのですが、そういう意味だったのですね…ループが間違ってるのかと必死に考えました。本当に初心者で、お手数かけました。今、また、おしゃべり掲示板に書き込みしたかったのですが、サーバーの不具合かおしゃべり掲示板に書き込みできませんでした。。また、後日、改めて…

No.1582

Re:isdigit関数。。
投稿者---ジャスミン茶(2002/05/22 20:28:27)


はじめまして、ジャスミン茶です。
整理してコメントを入れておきました。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(void)
{
	char str[128];
	int i,err;
	int year;

	do {
		printf("年を入力してください : ");
		gets(str);				// 128文字を超えると困った事がおきます。

		err = 0;				// エラーフラグの初期化
		if(str[0]="0") {			// str[0]に0を代入。この式はエラーがでなければ真
			err=1;				// ちなみに"0"ではなく'0'です!
		}
		i=1;					// iの初期化
		while (err==0 && str[i] != '\0') {	// エラーが無い、かつ配列にNULLが無ければ実行
			if (isdigit(str[i])==0) {	// 数字以外を発見したらerr+1
				err++;
			}
			i++;
		}
		if (err == 0) { 			// エラーが無かったら
			year = atoi(str);		// 文字列に格納されたアスキー文字を変換
			if (year<=0 || year>9999) {
				err = 1;		// err = 1
			}
		}
	} while (err != 0);				// エラーがなくなるまで実行

	printf("year : %d\n",year);

	return(0);
}


これで分かりますか?
=と==の違いに注意してください。

No.1584

Re:isdigit関数。。
投稿者---チェリー(2002/05/22 20:35:58)


はじめまして、チェリーです。
コメントありがとうございました!!初心者なもので、皆様に大変初歩的な質問をして、お手数かけました…あなたさまのコメント参考にさせていただき、勉強がんばります!!

No.1585

Re:isdigit関数。。
投稿者---ジャスミン茶(2002/05/22 21:00:44)


いえいえ、あれで役に立つのなら…
私もまだまだ分からない事だらけですので。

ついでといってはなんですが自作の関数を書いておきます。
二つの引数に整数を代入しておくと、ユーザーが指定した範囲のみで数値(整数のみ)を入力する事が出来、
その数字を戻り値として返します。
scanfのエラーがイヤで作ったものです。
これは数字、エンター、バックスペース、マイナス記号しか使えません。
そしてエラーを出しませんので入力のチェックが不要になります。
一週間ほど前に書いたものなので、かなり汚い、かつ下手糞です。

今回のようなケースでは役に立つかもしれません。
すぐ下のマクロのMAXとMINを1, 9999(逆でも良い)として置くとチェリーさんの書いたものと同じような事が出来ます。
printf("%d", input_number(1, 9999));
みたいに使います。

何かの参考になるかも知れません。
#include <stdio.h>
#include <conio.h>
#define MAX -5000
#define MIN 50000

int string_to_int(char *, char);
int input_number(int, int);

main()
{
	int i, n = MAX, m = MIN;

	printf("Input number (%d - %d): ", m, n);
	i = input_number(MIN, MAX);
	printf("\n\n\"Input_number\" returns %d", i);
	getch();
	exit(-1);
}

int input_number(int min, int max)
{
	char key, flag=0;
	int x=0,y=0;
	int a;
	char buf[11];
	buf[0]=0;

	if (min > max) {
		a = min;
		min = max;
		max = a;
	}
	if (min>0) {
		x=min;
	}
	if (max<0) {
		y=max;
	}
	for (;;) {
		key = getch();
		switch (key) {
			case 8:
				if (flag==0)
					continue;
				if (flag==2 && buf[0]==0) {
					flag--;
					buf[flag] = 0;
				}
				flag--;
				buf[flag] = 0;
				printf("\b \b");
				continue;
			case 13:
				if (buf[0]==48)
					break;
				if (flag<=1)
					continue;
				if (string_to_int(buf,flag)>=min&&string_to_int(buf,flag)<=max)
				break;
			case '-':
				if (min<0 && flag==0) {
					buf[0] = '-';
					flag++;
					printf("-");
				}
				continue;
			default:
				if ( (key>=48) && (key<=57) ) {
					if (buf[0]==48)
						continue;
					if ( (flag==0) && (key==48) ) {
						if ( (min>0) || (max<0) )
							continue;
						buf[0] = 48;
						printf("0");
						flag++;
						continue;
					}
					if ( (flag==1) && (buf[0]=='-') && (key==48) )
						continue;
					if (flag==0 && buf[0]==0) {
						if (max<0)
							continue;
						flag++;
					}
					if (max<0&&flag==0)
						continue;
					buf[flag] = key-48;
					flag++;
					if ( (string_to_int(buf, flag)+x<min) || (string_to_int(buf, flag)+y>max) ) {
						buf[flag-1] = 0;
						flag--;
						continue;
					}
					printf("%c", key);
				}
				continue;
		}break;
	}
	if (buf[0]==48)
		buf[0]=0;
	return string_to_int(buf, flag);
}

int string_to_int (char *buf, char flag)
{
	char x;
	int y;
	int w;
	for (x=0, y=1, w=0; x+1<flag; x++, y*=10) {
		w = w + buf[flag-x-1]*y;
	}
	if (buf[0] == '-')
		w *= -1;
	return w;
}


戻る


「初心者のためのポイント学習C言語」 Last modified:2002.06.28
Copyright(c) 2000-2002 TOMOJI All Rights Reserved