Inne działy

 

 

Język C funkcja scanf

 

Teraz pomyślmy o sytuacji odwrotnej. Tym razem to użytkownik musi powiedzieć coś programowi. W poniższym przykładzie program podaje kwadrat liczby, podanej przez użytkownika:

#include <stdio.h>
int main ()
{
int liczba = 0;
printf ("Podaj liczbę: ");
scanf ("%d", &liczba);
printf ("%d*%d=%d\n", liczba, liczba, liczba*liczba);
return 0;
}

 Zauważyłeś, że w tej funkcji przy zmiennej pojawił się nowy operator —&(etka). Jest on ważny, gdyż bez niego funkcja scanf() nie skopiuje odczytanej wartości liczby do odpowiedniej zmiennej! Właściwie oznacza przekazanie do funkcji adresu zmiennej, by funkcja mogła zmienić jej wartość. Nie musisz teraz rozumieć, jak to się odbywa, wszystko zostanie wyjaśnione w rozdziale Wskaźniki.

Oznaczenia są podobne takie jak przy printf(), czyli scanf(%i, &liczba); wczytuje liczbę typu int, scanf(%f, &liczba); liczbę typu float, a scanf(%s, tablica znaków); ciąg znaków. Ale czemu w tym ostatnim przypadku nie ma etki? Otóż, gdy podajemy jako argument do funkcji wyrażenie typu tablicowego zamieniane jest ono automatycznie na adres pierwszego elementu tablicy. Będzie to dokładniej opisane w rozdziale poświęconym wskaźnikom.

Brak etki jest częstym błędem szczególnie wśród początkujących programistów. Ponieważ funkcja scanf() akceptuje zmienną liczbę argumentów to nawet kompilator może mieć kłopoty z wychwyceniem takich błędów (konkretnie chodzi o to, że standard nie wymaga od kompilatora wykrywania takich pomyłek), choć kompilator GCC radzi sobie z tym jeżeli podamy mu argument -Wformat.

Należy jednak uważać na to ostatnie użycie. Rozważmy na przykład poniższy kod:

 

#include <stdio.h>
int main(void)
{
char tablica[100]; /* 1 */
scanf("%s", tablica); /* 2 */
return 0;
}

 Robi on niewiele. W linijce ? deklarujemy tablicę 100 znaków czyli mogącą przechować napis długości 99 znaków. Nie przejmuj się jeżeli nie do końca to wszystko rozumiesz — pojęcia takie jak tablica czy ciąg znaków staną się dla Ciebie jasne w miarę czytania kolejnych rozdziałów. W linijce 2 wywołujemy funkcję scanf(), która odczytuje tekst ze standardowego wejścia. Nie zna ona jednak rozmiaru tablicy i nie wie ile znaków może ona przechować przez co będzie czytać tyle znaków, aż napotka biały znak (format %s nakazuje czytanie pojedynczego słowa), co może doprowadzić do przepełnienia bufora. Niebezpieczne skutki czegoś takiego opisane są w rozdziale poświęconym napisom. Na chwilę obecną musisz zapamiętać, żeby zaraz po znaku procentu podawać maksymalną liczbę znaków, które może przechować bufor, czyli liczbę o jeden mniejszą, niż rozmiar tablicy. Bezpieczna wersją powyższego kodu
jest:

#include <stdio.h>
int main(void)
{
char tablica[100];
scanf("%99s", tablica);
return 0;
}

 

 Funkcja scanf() zwraca liczbę poprawnie wczytanych zmiennych lub EOF jeżeli nie ma już danych w strumieniu lub nastąpił błąd. Załóżmy dla przykładu, że chcemy stworzyć program, który odczytuje po kolei liczby i wypisuje ich 3 potęgi. W pewnym momencie dane się kończą lub jest wprowadzana niepoprawna dana i wówczas nasz program powinien zakończyć działanie. Aby to zrobić, należy sprawdzać wartość zwracaną przez funkcję scanf() w warunku pętli:

 

#include <stdio.h>
int main(void)
{
int n;
while (scanf("%d", &n)==1)
{
printf("%d\n", n*n*n);
}
return 0;
}

 

Podobnie możemy napisać program, który wczytuje po dwie liczby i je sumuje:

 

#include <stdio.h>
int main(void)
{
int a, b;
while (scanf("%d %d", &a, &b)==2)
{
printf("%d\n", a+b);
}
return 0;
}

 

 Rozpatrzmy teraz trochę bardziej skomplikowany przykład. Otóż, ponownie jak poprzednio nasz program będzie wypisywał 3 potęgę podanej liczby, ale tym razem musi ignorować błędne dane (tzn. pomijać ciągi znaków, które nie są liczbami) i kończyć działanie tylko w momencie, gdy nastąpi błąd odczytu lub koniec pliku.

 

#include <stdio.h>
int main(void)
{
int result, n;
do
{
result = scanf("%d", &n);
if (result==1)
{
printf("%d\n", n*n*n);
}
else if (!result) { /* !result to to samo co result==0 */
result = scanf("%*s");
}
}
while (result!=EOF);
return 0;
}

 

Zastanówmy się przez chwilę co się dzieje w programie. Najpierw wywoływana jest funkcja scanf() i następuje próba odczytu liczby typu int. Jeżeli funkcja zwróciła 1 to liczba została poprawnie odczytana i następuje wypisanie jej trzeciej potęgi. Jeżeli funkcja zwróciła 0 to na wejściu były jakieś dane, które nie wyglądały jak liczba. W tej sytuacji wywołujemy funkcję scanf() z formatem odczytującym dowolny ciąg znaków nie będący białymi znakami z jednoczesnym określeniem, żeby nie zapisywała nigdzie wyniku. W ten sposób niepoprawnie wpisana dana jest omijana. Pętla główna wykonuje się tak długo jak długo funkcja scanf() nie zwróci wartości EOF.

 

 

Zobacz nasze wszystkie kursy

WWW


HTML
HTML - Znaczniki
CSS - Tutorial
CSS - Selektory
PHP
JavaScript

XML

XSLT

Bazy danych


SQL
SQLite
MySQL
PostgreSQL

 

 

Programowanie


C
C++
C#
Java
VisualBasic
Python

Linux


Podstawy Linuxa
Bash
Linuks artykuły

Windows


Excel funkcje
Windows wskazówki
Outlook

Pozotałe działy


Programy
Rozrywka

 

 

 

This email address is being protected from spambots. You need JavaScript enabled to view it.