Przejdź do treści

Obsługa wejścia-wyjścia

W języku C do obsługi wejścia/wyjścia korzystamy standardowo z funkcji printf oraz scanf.

Biblioteka

Funkcje printf oraz scanf znajdują się w standardowej bibliotece wejścia/wyjścia (standard input/output):

#include <stdio.h>

Printf

Funkcja printf przyjmuje dwa argumenty:

  • format wypisywanego komunikatu,
  • listę oddzielonych przecinkami wartości do podstawienia.

Format jest standardowym tekstem, który może zawierać specjalne symbole określające, że w tym miejscu komunikatu ma zostać podstawiona kolejna wartość, przekazana jako drugi argument.

Funkcji printf możemy także użyć do wypisania komunikatu bez podawania wartości do podstawienia.

printf("Hello World!");

Każdy symbol specjalny składający się ze znaku % i litery oznacza, że w to miejsce należy wstawić odpowiednią wartość. Np. %d w formacie zostanie zastąpiony wartością typu int podaną jako kolejny argument funkcji printf.

printf("%d", 68); /* 68 */
printf("Wynik to %d", 24); /* Wynik to 24 */

Formatowanie szerokości

Możemy wypisać wartość w polu o zadanej minimalnej szerokości. Aby to zrobić, bezpośrednio po znaku % podajemy liczbę określającą szerokość pola. Domyślnie wartości będą wyrównywane do prawej.

printf("%3d", 0); 
printf("%3d", 123456789); 
printf("%8d", -10);

Aby wyrównać wartości do lewej, należy podać szerokość pola jako liczbę ujemną.

printf("%-3d", 0);
printf("%-3d", 123456789);
printf("%-8d", -10);

Uzupełnienie do szerokości pola

Wypisywaną wartość liczbową możemy uzupełnić zerami z lewej strony do wymaganej szerokości pola. W tym celu piszemy %0, zadaną szerokość pola i znak formatu.

printf("%03d", 0); /* 000 */
printf("%08d", 12); /* 00000012 */
printf("%02d:%02d", 14, 5); /* 14:05 */

Liczby rzeczywiste

Domyślnie przy wypisywaniu liczb rzeczywistych zostaną one wypisane z dokładnością do 6 miejsc po przecinku. Możemy to jednak zmienić, pisząc %. i zadaną dokładność. Wartość zostanie zaokrąglona do zadanej liczby miejsc po przecinku.

printf("%f", 12.85); /* 12.850000 */
printf("%.2f", 12.85); /* 12.85 */
printf("%.1f", 12.85); /* 12.9 */

Możemy także połączyć określenie szerokości pola z dokładnością do zadanej liczby miejsc po przecinku. Należy pamiętać, że szerokość uwzględnia całą liczbę, łącznie ze znakiem kropki.

printf("%6.2f", 12.85); /* 12.85 */
printf("%06.2f", 12.85); /* 012.85 */
printf("%-6.2f", 12.85);

Notacja naukowa

W celu wypisania liczby rzeczywistej w formacie naukowym używamy formatu %e.

printf("%e", 5.65); /* 5.650000e+00 */
printf("%e", 5.653745343438343); /* 5.653745e+00 */
printf("%e", 4342342343245.0); /* 4.342342e+12 */

Znak liczby

Aby zawsze wypisywać znak liczby, a nie tylko przy wartościach ujemnych, możemy podać znak \(+\) przed literą formatu.

printf("%+d", 5); /* +5 */
printf("%+d", -5); /* -5 */

Inne systemy liczbowe

Za pomocą printf możemy w łatwy sposób wypisać liczbę naturalną w systemie oktalnym lub heksadecymalnym. Służą do tego odpowiednio formaty %o i %x.

printf("%o", 127); /* 177 */
printf("%x", 127); /* 7f */
printf("%X", 127); /* 7F */

Printf - przykłady

Scanf

Funkcja scanf pozwala nam wczytać dane od użytkownika. Jej użycie wygląda podobnie do printf. Najpierw podajemy format, a następnie zmienne, do których chcemy wczytać poszczególne wartości. W formacie zazwyczaj ograniczamy się do podania formatów wczytywanych wartości. Zmienne natomiast muszą być podane jako adres w pamięci, pod którym należy zapisać wczytaną wartość. Dlatego zazwyczaj zmienne poprzedzamy symbolem &.

int a;
scanf("%d", &a);

Ignorowanie znaku %

Możemy zignorować znak % podany na wejściu.

int a;
scanf("%d%%", &a);

Inne systemy liczbowe

Podobnie jak w przypadku printf, scanf możemy użyć do wczytania liczb w formatach oktalnym i heksadecymalnym.

int a, b;
scanf("%o", &a); /* 012 */
scanf("%x", &b); /* Af */
printf("a = %d, b = %d", a, b); /* a = 10, b = 175 */

Wczytywanie tekstów

Teksty wczytujemy do tablicy typu char. W przypadku tablic nie podajemy znaku &, ponieważ nazwa zmiennej tablicowej zwraca adres w pamięci, gdzie znajduje się początek tablicy.

char txt[100];
scanf("%s", txt);

Alternatywnie:

char txt[100];
scanf("%s", &txt[0]);

Ignorowanie wejścia

Aby wczytać i zignorować wejście (lub jego fragment), czyli nie przypisywać wartości do zmiennej, możemy po znaku % dać *.

int a;
scanf("%*s %d", &a);  /* Age: 29 */
printf("a = %d", a);  /* a = 29 */

Maksymalna długość wejścia

Możemy określić, ile maksymalnie znaków ma zostać wczytanych. Reszta danych zostanie zignorowana.

int a;
scanf("%2d", &a);     /* 1234 */
printf("a = %d", a);  /* a = 12 */

Możemy też nie ignorować reszty wejścia i przypisać je do kolejnej zmiennej.

int a, b;
scanf("%2d%d", &a, &b);          /* 1234 */
printf("a = %d, b = %d", a, b);  /* a = 12, b = 34 */

Koniec wejścia

W momencie napotkania końca wejścia, funkcja scanf zwróci stałą EOF. W celu wczytywania wejścia aż do jego końca możemy więc np. zastosować taką pętlę:

int a;
while(scanf("%d", &a) != EOF) {
}

Znaki specjalne

  • - znak nowej linii
  • - tabulacja pozioma
  • \v - tabulacja pionowa
  • \b - backspace
  • \a - alarm
  • \\ - backslash
  • \? - znak
  • \` - apostrof
  • \" - cudzysłów

Formaty typów

Typ Format
char %c
unsigned char %c
short %h
unsigned short %uh
int %d, %i
unsigned int %u
long int %ld
unsigned long int %lu
long long int %lld
unsigned long long int %llu
float %f, %F
double %lf
long double %Lf
char* %s

Formaty specjalne

Opis Format
notacja naukowa %e, %E
notacja standardowa lub naukowa, w zależności od wielkości liczby %g, %G
unsigned intw formacie oktalnym (ósemkowym) %o
unsigned int w formacie heksadecymalnym (szesnastkowym) %x, %X
doublew formacie heksadecymalnym (szesnastkowym) %a, %A