Posted in: Různé, Studijní materiály, Vývoj počítačů

Ošetření uživatelského vstupu v C

Jak v C realizovat rčení Margaret Hamilton, že uživatelé chybují a počítače s tím musí počítat.

Základní ošetření pomocí IF a masky příkazu scanf

#include <stdio.h>

#include <stdbool.h> //umozni poutivat logicke funkce



void main()

{

    int celeCislo;

    do

    {

        printf("Zadej cele cislo: ");

        if (scanf("%d", &celeCislo) == 1)

        {

            break; //ukonci nekonecny cyklus

        }

        else

        {

            printf("Na vstupu neni cislo, opakuj zadani\n");

            getchar(); //snaze potvrzovaci enter z bufferu vstupu

        }

    } while (true);

    getchar(); //snaze potvrzovaci enter z bufferu vstupu

    printf("Zadane cislo je %d.", celeCislo);

    float DesetinnneCislo;

    printf("Zadane cislo je %d.", celeCislo);

    do

    {

        printf("\nZadej desetinne cislo: ");

        if (scanf("%f", &DesetinnneCislo) == 1)

        {

            break;

        }

        else

        {

            printf("Na vstupu neni cislo, opakuj zadani\n");

            getchar();

        }

    } while (true);

    getchar(); //snaze potvrzovaci enter z bufferu vstupu

    printf("Zadane cislo je %f.", DesetinnneCislo);

}

Přetypování ze stringu pomocí knihovních funkcí

#include <stdio.h>
#include <ctype.h> //validace datovych typu
#include <stdlib.h>
#include <string.h> //textove retezce
#include <stdbool.h> //datovy typ bool
#define BUFFER_SIZE 4096 //velikost bufferu

bool parse_int(char* string, int* integer)
{
	//na vstupu prijme string a vrati true a hdonotu integeru, pokud je stringem cele cislo
	//odmaze pripadne mezery a taby kolem cisla
	int i = 0; //idex pocatku retezce
	while (isspace(string[i])) //dokud je pred prvkem mezera, novy radek nebo tab
	{
		i++; //nastavi index na zacatek nejake hodnoty
	}
	int length = strlen(string); //ulozi delku retezce
	if (length == i)
	{
		return false; //reteezec byl prazdny, jen bile znaky
	}
	char integet_buffer[BUFFER_SIZE];
	int integer_chars = 0;
	//detekce zaporne hodnoty
	if (string[i] == '-')
	{
		integet_buffer[integer_chars] = '-';
		integer_chars++;
		i++;
		if (!isdigit(string[i])) //validace, zda je dalsi zank cislo
		{
			return false; //kdyz neni dalsi znak cislo, vracime false
		}
	}
	//nacteni ciselnych hodnot z retezce
	while (i < length && !isspace(string[i])) //doku i je mensi nez delka a zaroven nejde o mezeru
	{
		if (!isdigit(string[i])) //pokud znak neni cislo vrat false
		{
			return false;
		}
		//pokud jde o cislo, pridame jej do bufferu
		integet_buffer[integer_chars] = string[i];
		integer_chars++;
		i++;
	}
	//korektni ukonceni textoveho retezce
	integet_buffer[integer_chars] = '\0';
	*integer = atoi(integet_buffer); //vlastni konverze z retezce na cislo
	return true;
}

bool parse_float(char* string, float* desetinne)
{
	//na vstupu prijme string a vrati true a hdonotu float, pokud je stringem cele cislo
	//odmaze pripadne mezery a taby kolem cisla
	int i = 0; //idex pocatku retezce
	while (isspace(string[i])) //dokud je pred prvkem mezera, novy radek nebo tab
	{
		i++; //nastavi index na zacatek nejake hodnoty
	}
	int length = strlen(string); //ulozi delku retezce
	if (length == i)
	{
		return false; //reteezec byl prazdny, jen bile znaky
	}
	char desetinne_buffer[BUFFER_SIZE];
	int desetinne_chars = 0;
	//detekce zaporne hodnoty
	if (string[i] == '-')
	{
		desetinne_buffer[desetinne_chars] = '-';
		desetinne_chars++;
		i++;
		if (!isdigit(string[i])) //validace, zda je dalsi zank cislo
		{
			return false; //kdyz neni dalsi znak cislo, vracime false
		}
	}
	//nacteni ciselnych hodnot z retezce
	bool carka = false;
	while (i < length && !isspace(string[i])) //doku i je mensi nez delka a zaroven nejde o mezeru
	{
		if((string[i]=='.' || string[i] == ',') && (!carka)) //detekce desetinne carky resp tecky
		{
			desetinne_buffer[desetinne_chars] = '.'; //pridani desetinne carky
			carka = true;
		}
		else if (!isdigit(string[i])) //pokud znak neni cislo vrat false
		{
			return false;
		}
		else
		{
			//pokud jde o cislo, pridame jej do bufferu
			desetinne_buffer[desetinne_chars] = string[i];
		}
		//posun k dalsimu znaku
		desetinne_chars++;
		i++;
	}
	//korektni ukonceni textoveho retezce
	desetinne_buffer[desetinne_chars] = '\0';
	*desetinne = atof(desetinne_buffer); //vlastni konverze z retezce na cislo
	return true;
}

int main()
{
	int cislo;
	float cislo2;
	char buffer[BUFFER_SIZE]; //textove pole pro ulozeni vstupu
	bool uspech = true;
	do
	{
		printf("Zadej cele cislo: ");
		scanf(" %4096[^\n]s", buffer);; //nacteni z konzole do bufferu
		uspech = parse_int(buffer, &cislo); //promenou cislo predavame jako ukazatel v pameti
		if (!uspech)
		{
			printf("Musi byt zadano cele cislo\n");
		}
	} while (!uspech); //dokud neni spravne nacteno
	printf("Zadane cele cislo je %d\n", cislo);
	uspech = true;
	do
	{
		printf("Zadej desetinne cislo: ");
		scanf(" %4096[^\n]s", buffer);; //nacteni z konzole do bufferu
		uspech = parse_float(buffer, &cislo2); //promenou cislo predavame jako ukazatel v pameti
		if (!uspech)
		{
			printf("Musi byt zadano cele cislo\n");
		}
	} while (!uspech); //dokud neni spravne nacteno
	printf("Zadane destinne cislo je %f\n", cislo2);
	return 0;
}

Vlastní konverzní funkce využívající dekadický zápis čísel

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define DELKA 4096

//vyuzit dekatickeho zapisu pro konverzi string na int
void main()
{
	char text[DELKA]; //pro přímé zadání vstupu
	char cislice[DELKA]; //ocistene cislo
	int cislo = 0; //finalni cislice
	float desetine = 0.0;
	int i = 0, j = 0; //ridici promene
	int zaporne = 0; //detekce zaporne hodnoty
	printf("Zadej cele cislo: ");
	scanf_s("%4096[^\n]s", &text, 4096); //nacteni cisla v podobe textu
	getchar();
	//odmazani mezer a dalsich bilich znaku pred cislem
	for (i = 0; i < DELKA; i++)
	{
		if (!isspace(text[i]))
		{
			break;
		}
	}
	if (i < DELKA)
	{
		if (text[i] == '-') //detekce zaporne hodnoty
		{
			i++;
			zaporne = -1;
		}
		do
		{
			if (isdigit(text[i])) //prevedeni ciselnych hodnot do druheho pole (ciste cislo)
			{
				cislice[j] = text[i]; 
			}
			else if (isspace(text[i])) //mezera za cislem => ukonceni prevodu
			{
				break;
			}
			else if (text[i] == '\0') //znak konce retezce ukonci prevod
			{
				cislice[j] = text[i]; //ukonceni retezce cisteho sicla
				break;
			}else
			{
				printf("Nejde o ciso"); //vypis chyby
				break;
			}
			//povyseni ridicich promenych
			j++;
			i++;
		} while (i < DELKA);
		int mocnina = 0; //hodnota mocniny deseti
		//prevod pomoci dekadickeho zapisu disla (mantisa * deset na pozici)
		for (int d = strlen(cislice) -1; d >= 0; d--)
		{
			switch (cislice[d])
			{
			case '0':
				cislo = cislo + 0 * pow(10, mocnina);
				break;
			case '1':
				cislo = cislo + 1 * pow(10, mocnina);
				break;
			case '2':
				cislo = cislo + 2 * pow(10, mocnina);
				break;
			case '3':
				cislo = cislo + 3 * pow(10, mocnina);
				break;
			case '4':
				cislo = cislo + 4 * pow(10, mocnina);
				break;
			case '5':
				cislo = cislo + 5 * pow(10, mocnina);
				break;
			case '6':
				cislo = cislo + 6 * pow(10, mocnina);
				break;
			case '7':
				cislo = cislo + 7 * pow(10, mocnina);
				break;
			case '8':
				cislo = cislo + 8 * pow(10, mocnina);
				break;
			case '9':
				cislo = cislo + 9 * pow(10, mocnina);
				break;
			default:
				break;
			}
			mocnina++; //povyseni mocniny pro dalsi pozici
		}
		if (zaporne == -1) //realizace zaporne hodnoty
		{
			cislo = cislo * (-1);
		}
	}
	//kontolni vypis cisla
	printf("\n\nZadane cislo je %d", cislo);
	//desetinne cislo
	//nulovani ridicich promennych
	i = 0;
	j = 0; 
	zaporne = 0;
	//nulvani retezcu
	for (int i = 0; i < DELKA; i++)
	{
		text[i] = '\0';
		cislice[i] = '\0';
	}
	i = 0; //opetovne vynulovani
	printf("\n\nZadej desetinne cislo: ");
	scanf_s("%4096[^\n]s", &text, 4096); //nacteni cisla v podobe textu
	//odmazani mezer a dalsich bilich znaku pred cislem
	for (i = 0; i < DELKA; i++)
	{
		if (!isspace(text[i]))
		{
			break;
		}
	}
	if (i < DELKA) //pokud retezec obsahuje jiny nez bily znak
	{
		if (text[i] == '-') //detekce zaporne hodnoty
		{
			i++;
			zaporne = -1;
		}
		do
		{
			if (isdigit(text[i])) //prevedeni ciselnych hodnot do druheho pole (ciste cislo)
			{
				cislice[j] = text[i];
			}
			else if (isspace(text[i])) //mezera za cislem => ukonceni prevodu
			{
				break;
			}
			else if (text[i] == '\0') //znak konce retezce ukonci prevod
			{
				cislice[j] = text[i]; //ukonceni retezce cisteho sicla
				break;
			}
			else if (text[i] == '.' || text[i] == ',') //detekce a prevedeni desetinneho oddelovace
			{
				cislice[j] = text[i];
			}
			else
			{
				printf("Nejde o ciso"); //vypis chyby
				break;
			}
			//povyseni ridicich promenych
			j++;
			i++;
		} while (i < DELKA);
		int mocnina = 0; //hodnota mocniny deseti
		int tecka = -1; //pozice desetineho oddelovace
		for (int k = 0; k < strlen(cislice); k++) //nalezeni pozice desetinneho oddelovace
		{
			if (cislice[k] == '.' || cislice[k] == ',')
			{
				tecka = k;
				break;
			}
		}
		if (tecka > -1) //jestli je desetinna nalezena
		{
			//prevod desetinne casti
			mocnina = 1; //nastaveni na rad desetin
			for (int d = tecka+1; d <strlen(cislice); d++)
			{
				switch (cislice[d])
				{
				case '0':
					desetine = desetine + 0 * pow(10, (mocnina * (-1))); //hodnota cifry * 10 na -cifru
					break;
				case '1':
					desetine = desetine + 1 * pow(10, (mocnina * (-1)));
					break;
				case '2':
					desetine = desetine + 2 * pow(10, (mocnina * (-1)));
					break;
				case '3':
					desetine = desetine + 3 * pow(10, (mocnina * (-1)));
					break;
				case '4':
					desetine = desetine + 4 * pow(10, (mocnina * (-1)));
					break;
				case '5':
					desetine = desetine + 5 * pow(10, (mocnina * (-1)));
					break;
				case '6':
					desetine = desetine + 6 * pow(10, (mocnina * (-1)));
					break;
				case '7':
					desetine = desetine + 7 * pow(10, (mocnina * (-1)));
					break;
				case '8':
					desetine = desetine + 8 * pow(10, (mocnina * (-1)));
					break;
				case '9':
					desetine = desetine + 9 * pow(10, (mocnina * (-1)));
					break;
				default:
					break;
				}
				mocnina++; //povyseni mocniny pro dalsi pozici
			}
			mocnina = 0; //nastaveni mocniny pro rad jednotek
			//prevod cele casti
			for (int d = tecka - 1; d >=0 ; d--)
			{
				switch (cislice[d])
				{
				case '0':
					desetine = desetine + 0 * pow(10, mocnina); //hodnota cifry *10 na cifru
					break;
				case '1':
					desetine = desetine + 1 * pow(10, mocnina);
					break;
				case '2':
					desetine = desetine + 2 * pow(10, mocnina);
					break;
				case '3':
					desetine = desetine + 3 * pow(10, mocnina);
					break;
				case '4':
					desetine = desetine + 4 * pow(10, mocnina);
					break;
				case '5':
					desetine = desetine + 5 * pow(10, mocnina);
					break;
				case '6':
					desetine = desetine + 6 * pow(10, mocnina);
					break;
				case '7':
					desetine = desetine + 7 * pow(10, mocnina);
					break;
				case '8':
					desetine = desetine + 8 * pow(10, mocnina);
					break;
				case '9':
					desetine = desetine + 9 * pow(10, mocnina);
					break;
				default:
					break;
				}
				mocnina++; //povyseni mocniny pro dalsi pozici
			}
		}
		else
		{
			//prevod pomoci dekadickeho zapisu disla (mantisa * deset na pozici)
			for (int d = strlen(cislice) - 1; d >= 0; d--)
			{
				switch (cislice[d])
				{
				case '0':
					desetine = desetine + 0 * pow(10, mocnina);
					break;
				case '1':
					desetine = desetine + 1 * pow(10, mocnina);
					break;
				case '2':
					desetine = desetine + 2 * pow(10, mocnina);
					break;
				case '3':
					desetine = desetine + 3 * pow(10, mocnina);
					break;
				case '4':
					desetine = desetine + 4 * pow(10, mocnina);
					break;
				case '5':
					desetine = desetine + 5 * pow(10, mocnina);
					break;
				case '6':
					desetine = desetine + 6 * pow(10, mocnina);
					break;
				case '7':
					desetine = desetine + 7 * pow(10, mocnina);
					break;
				case '8':
					desetine = desetine + 8 * pow(10, mocnina);
					break;
				case '9':
					desetine = desetine + 9 * pow(10, mocnina);
					break;
				default:
					break;
				}
				mocnina++; //povyseni mocniny pro dalsi pozici
			}
		}
		if (zaporne == -1) //realizace zaporne hodnoty
		{
			desetine = desetine * (-1);
		}
	}
	//kontolni vypis cisla
	printf("\n\nZadane cislo je %f", desetine);
}
Back to Top