Problem z pętlą, oraz warunkiem isdigit()

0

Witam, mam następujący problem.
Stworzyłem mikroskopijny program, który ma za zadanie sprawdzać czy input jest liczbą, a jeśli nie - to o tym usera poinformować i wrócić do początku programu.
Oto kod:

#include <stdio.h> 
#include <stdlib.h> /*for atof*/
#include <ctype.h>

int main()
{
	double c, d;
	printf("please enter a number\n");
	c = getchar();
	do {
	if (isdigit(c)) 
		printf("thanks for the number\n");
	else
		printf("please enter a number\n");
	printf("press r to repeat\n");
	fflush(stdin);
	d = getchar();	
	} while (d == 'r');
	return 0;			
}	 

Niestety obecnie pętla robi jeden ruch i wychodzi z programu. Co mam zrobić, żeby działało?
Zauważyłem również, że po dodaniu sprawdzającego printf, aby się upewnić, że liczba jest prawidłowo odczytana, wyświetla on zupełnie inną liczbę niż ta podana...

1
scanf
0

Zmodyfikowałem getchar na scanf, niestety nadal nie działa:

 #include <stdio.h> 
#include <stdlib.h>
#include <ctype.h>

int main()
{
	double c, d;
	printf("Please enter a number\n");
	scanf("%lg", &c);
	printf("ur number is %g", c);
	do {
	if (isdigit(c)) 
		printf("Thanks for the number");
	else
		printf("It is not a number. Please enter a number");
	printf("Press r to repeat\n");	
	scanf("%lg", &d);
	} while (d != 'r');
	return 0;			
}	

Program zwraca, że wpisana liczba nie jest liczbą (!) Wobec czego wchodzi w nieskończoną pętlę z instrukcją z else.
Co robię źle?

1

Twój program ma głównie taki problem, że funkcja isdigit przyjmuje za argument int, ale ten int, to jest liczba reprezentująca znak ASCII, czyli jak podasz z klawiatury 0, to tam trzeba podać kod zera, czyli najprościej

isdigit('0'); 

Wtedy kompilator sobie ten kod wyciągnie (jeśli dobrze pamiętam to ten kod jest 48, ale pewności nie mam. W necia na pewno można znaleźć).
Poza tym linijka

scanf("%lg", &d);

gdzie d jest typu double, a potem sprawdzanie

 while (d != 'r');

też nie jest najlepszym pomysłem, bo typ znakowy do double trochę niechętnie się przypisuje, tym gorzej z porównywaniem tych typów.

Ja zrobiłem sobie taką funkcję, która wczytuje z klawiatury znaki i zapisuje do tablicy char[], a potem, znak po znaku sprawdza, czy na każdej pozycji jest liczba, a właściwie przerywa sprawdzanie ze stosownym komunikatem, jeśli napotka jakiś znak który cyfrą nie jest:

	const int numberLength = 20;
	char number[numberLength] = { '\0' };

	do
	{
		printf("Podaj liczbe, albo 'q' zeby wyjsc: ");
		if(scanf_s("%s", number, numberLength) == 0)
		{
			fflush(stdin);
			printf("! Podano zbyt dlugi tekst.");
			getchar();
			break;
		}
		for(int i = 0; i < numberLength && number[i] != NULL; i++)
		{
			if(!isdigit(number[i]) && number[i] != '.')
			{
				printf("%s nie jest liczba\n", number);
				break;
			}
		}
	
	}while(number[0] != 'q'); 

Dawno nie pisałem w C++, więc być może ten problem da się rozwiązać prościej i szybciej, mi pierwsze co przyszło do głowy, to taki kod.
Program ma delikatną wadę, a mianowicie rozpoczęcie wprowadzania od 'q' przerywa program, niezależnie co po tym się wprowadzi. Ale nie jest to chyba najistotniejsze.

0

Bardzo dziękuję za pomoc. Mam jednak kilka pytań, zaznaczę je jako komentarze przy linijce:

Lena(R) napisał(a):
	const int numberLength = 20;
	char number[numberLength] = { '\0' }; /*po co inicjalizować tylko jeden element tablicy jako \0 a resztę jako zera w domyśle*/

	do
	{
		printf("Podaj liczbe, albo 'q' zeby wyjsc: ");
		if(scanf("%s", number, numberLength) == 0) /*tutaj scanf pobiera tylko number, czemu więc dopisałeś numberLength ?*/
		{
			fflush(stdin);
			printf("! Podano zbyt dlugi tekst."); /*czy ten komunikat jest poprawny?; przecież scanf z tym warunkiem z if, będzie = 0 wtedy gdy input nie będzie stringiem?*/
			getchar();
			break;
		}
		for(int i = 0; i < numberLength && number[i] != NULL; i++) /*!= NULL czy != 0 powinno być ?*/
		{
			if(!isdigit(number[i]) && number[i] != '.')
			{
				printf("%s nie jest liczba\n", number);
				break;
			}
		}
	
	}while(number[0] != 'q'); 
1

odpowiem w komentarzach

Pole napisał(a):

Bardzo dziękuję za pomoc. Mam jednak kilka pytań, zaznaczę je jako komentarze przy linijce:

Lena(R) napisał(a):
	const int numberLength = 20;
	char number[numberLength] = { '\0' }; /*po co inicjalizować tylko jeden element tablicy jako \0 a resztę jako zera w domyśle*/ // w zasadzie nie ma to sensu, rownie dobrze mozna napisac char number[numberLength] = {}; domyslnie reszta elementow bedzie zerami. Natomiast zapis: char number[numberLength]; juz tego nie zapewnia (nie wiesz jakie beda wartosci)

	do
	{
		printf("Podaj liczbe, albo 'q' zeby wyjsc: ");
		if(scanf("%s", number, numberLength) == 0) /*tutaj scanf pobiera tylko number, czemu więc dopisałeś numberLength ?*/ // powinno nie byc drugiego elementu, a jeszcze lepiej gdybys zastapil to %20s lub fgets-em (zabezpieczenie przed buffer overflow)
		{
			fflush(stdin);
			printf("! Podano zbyt dlugi tekst."); /*czy ten komunikat jest poprawny?; przecież scanf z tym warunkiem z if, będzie = 0 wtedy gdy input nie będzie stringiem?*/ // ten komunikat nastapi tylko i wylacznie gdy nie bedzie zadnych niebialych znakow na wejsciu - tak czy siak jest zle
			getchar();
			break;
		}
		for(int i = 0; i < numberLength && number[i] != NULL; i++) /*!= NULL czy != 0 powinno być ?*/ // null jest rownowazne 0, ale prawidlowo powinno byc 0 lub '\0', NULL jest typu void*
		{
			if(!isdigit(number[i]) && number[i] != '.')
			{
				printf("%s nie jest liczba\n", number);
				break;
			}
		}
	
	}while(number[0] != 'q'); 

1 użytkowników online, w tym zalogowanych: 0, gości: 1