Przejdź do treści
School IT / Przestrzeń do nauki
← C# od podstawLekcja 12 z 58

Wczytywanie danych od użytkownika

Do tej pory wszystkie dane były wpisane na sztywno w kodzie. Teraz program zacznie pytać i słuchać. Poznasz metody konsoli do czytania z klawiatury i — co ważniejsze — nauczysz się pisać kod, który nie wywraca się, gdy ktoś wpisze coś innego, niż się spodziewałeś.

C# ReadLine walidacja 40 min
CEL LEKCJI

Czego się dziś nauczysz

  • Wczytasz tekst z klawiatury metodą Console.ReadLine
  • Napiszesz czytelną zachętę, która mówi użytkownikowi, czego oczekujesz
  • Zamienisz wczytany tekst na liczbę bezpiecznym sposobem
  • Sprawdzisz, czy wprowadzona wartość mieści się w dozwolonym zakresie
  • Wyjaśnisz, dlaczego Console.ReadLine podkreśla się na żółto
TEORIA

Metoda Console.ReadLine

Ta jedna metoda robi wszystko, czego potrzeba do wczytania danych: zatrzymuje program, czeka na wpisanie tekstu i naciśnięcie klawisza Enter, po czym zwraca wpisany tekst.

Program.cs
Console.Write("Jak masz na imie? ");
string imie = Console.ReadLine();

Console.WriteLine($"Milo cie poznac, {imie}!");
wynik w konsoli (podkreślone = wpisane przez użytkownika)
Jak masz na imie? Anna
Milo cie poznac, Anna!

ReadLine zawsze zwraca tekst

Nawet jeśli użytkownik wpisze 42, dostaniesz napis "42", a nie liczbę. Żeby móc liczyć, trzeba wykonać konwersję z poprzedniej lekcji. To najczęstsze potknięcie przy pierwszych programach interaktywnych.

Żółte podkreślenie pod ReadLine

Visual Studio prawdopodobnie podkreśli ci tę linię i pokaże ostrzeżenie CS8600. Program działa, ale warto wiedzieć, o co chodzi.

Program.cs
string imie = Console.ReadLine();
//            └── ostrzeżenie CS8600: konwersja literału o wartości null

Console.ReadLine może w rzadkich sytuacjach zwrócić brak wartości zamiast tekstu — na przykład gdy dane wejściowe pochodzą z pliku, który właśnie się skończył. Kompilator o tym wie i uprzedza, że zmienna string mogłaby zostać pusta w sensie „nie ma nic”.

RozwiązanieKiedy
string imie = Console.ReadLine() ?? ""; Zalecane. Operator ?? mówi: „jeśli po lewej nic nie ma, użyj tego z prawej”. Zmienna zawsze dostanie jakiś napis, choćby pusty.
string? imie = Console.ReadLine(); Znak zapytania po typie oznacza „ta zmienna może nie mieć wartości”. Poprawne, ale wtedy trzeba to sprawdzać przy każdym użyciu.
zignorować ostrzeżenie W programie uruchamianym z klawiatury ReadLine praktycznie nigdy nie zwróci braku wartości. Na potrzeby nauki to dopuszczalne — ale lepiej wyrobić sobie nawyk pisania ?? "".

W tym kursie będziemy pisać ?? "". To jeden znak więcej, a kod jest wtedy bez zarzutu.

TEORIA

Zachęta, czyli jak zapytać użytkownika

Program, który po prostu zatrzymuje się i miga kursorem, jest bezużyteczny. Użytkownik musi wiedzieć, czego od niego chcesz.

Program.cs
// ✗ Kursor w nowej linii — wygląda, jakby program się zawiesił
Console.WriteLine("Podaj wiek:");
string a = Console.ReadLine() ?? "";

// ✓ Kursor tuż za pytaniem — naturalnie zaprasza do pisania
Console.Write("Podaj wiek: ");
string b = Console.ReadLine() ?? "";

Trzy zasady dobrej zachęty

1. Używaj Console.Write, nie WriteLine — kursor zostaje w tej samej linii.

2. Zostaw spację na końcu — "Podaj wiek: ", żeby wpisany tekst nie kleił się do dwukropka.

3. Podaj oczekiwany format — "Podaj wiek (0-120): " albo "Podaj cene (np. 19,99): ". Użytkownik nie zgadnie, czy ma wpisać kropkę czy przecinek.

TEORIA

Wczytywanie liczb

Skoro ReadLine zwraca tekst, potrzebny jest drugi krok — konwersja. Z poprzedniej lekcji wiesz już, że dla danych od użytkownika używamy TryParse.

Program.cs
Console.Write("Podaj wiek: ");
string tekst = Console.ReadLine() ?? "";

bool sieUdalo = int.TryParse(tekst, out int wiek);

Console.WriteLine($"Wczytano poprawnie: {sieUdalo}");
Console.WriteLine($"Wartosc: {wiek}");

Można to skrócić i wczytać od razu w jednej linii:

Program.cs
Console.Write("Podaj wiek: ");
bool sieUdalo = int.TryParse(Console.ReadLine(), out int wiek);

Tutaj ?? "" nie jest potrzebne

TryParse przyjmuje brak wartości bez protestu — po prostu zwraca wtedy false. Ostrzeżenie CS8600 pojawia się tylko wtedy, gdy przypisujesz wynik ReadLine do zmiennej typu string.

Liczby z częścią ułamkową

Program.cs
Console.Write("Podaj wzrost w metrach (np. 1,75): ");
bool ok = double.TryParse(Console.ReadLine(), out double wzrost);

Console.WriteLine($"Wczytano: {wzrost}");

Przecinek, nie kropka

Na polskim systemie double.TryParse oczekuje przecinka. Użytkownik, który wpisze 1.75, dostanie false — i pomyśli, że program jest zepsuty.

Dlatego zawsze podawaj przykład w zachęcie: "(np. 1,75)". W następnej lekcji pokażemy, jak przyjmować oba zapisy naraz.

TEORIA

Sprawdzanie, czy dane mają sens

Udana konwersja to dopiero połowa sukcesu. Liczba -500 jest poprawną liczbą całkowitą, ale nie jest poprawnym wiekiem.

Przedsmak instrukcji warunkowej

Do sprawdzania danych potrzebujemy instrukcji if. Poznasz ją dokładnie w lekcji 14, ale zasada jest tak prosta, że możemy z niej skorzystać już teraz:

if (warunek) { ... } else { ... } — jeśli warunek jest prawdziwy, wykona się pierwszy blok; w przeciwnym razie drugi. Warunki budujesz z operatorów poznanych w lekcji 10.

Program.cs
Console.Write("Podaj wiek (0-120): ");
bool sieUdalo = int.TryParse(Console.ReadLine(), out int wiek);

if (!sieUdalo)
{
    Console.WriteLine("To nie jest liczba calkowita.");
}
else if (wiek < 0 || wiek > 120)
{
    Console.WriteLine("Wiek musi miescic sie w zakresie 0-120.");
}
else
{
    Console.WriteLine($"Dziekuje. Za 10 lat bedziesz mial {wiek + 10} lat.");
}
WpisaneKtóry blok się wykonaDlaczego
abcpierwszykonwersja się nie udała
-5drugikonwersja OK, ale wartość poza zakresem
200drugijak wyżej
17trzeciwszystko w porządku

Dwa różne pytania, dwa różne komunikaty

Rozdzielenie „to nie jest liczba” od „liczba jest poza zakresem” to nie pedanteria. Użytkownik, który dostanie właściwy komunikat, poprawi się za pierwszym razem. Komunikat „błędne dane” nie mówi mu nic.

Czego tu jeszcze brakuje

Ten program mówi, co jest nie tak — ale kończy się i nie daje drugiej szansy. Żeby prosić o dane do skutku, potrzebna jest pętla. Wrócimy do tego w lekcji 16 i wtedy dopiszemy brakujący fragment.

METODY WBUDOWANE

Pozostałe metody klasy Console

MetodaZwracaDziałanie
Console.ReadLine()string? Czeka na wpisanie tekstu i klawisz Enter. Zwraca wpisany tekst bez znaku końca linii.
Console.Write(x)nic Wypisuje tekst, kursor zostaje w tej samej linii. Do zachęt.
Console.WriteLine(x)nic Wypisuje tekst i przechodzi do nowej linii. Bez argumentu robi pustą linię.
Console.ReadKey()ConsoleKeyInfo Czeka na jeden klawisz, bez Entera. Przydatne do „naciśnij dowolny klawisz”. Wywołanie Console.ReadKey(true) nie wyświetla naciśniętego znaku.
Console.Clear()nic Czyści okno konsoli. Uwaga: w niektórych terminalach nie działa albo tylko przewija ekran.
Console.Titlestring Właściwość — ustawia napis na pasku tytułu okna: Console.Title = "Kalkulator";.
Console.ForegroundColorkolor Zmienia kolor tekstu: Console.ForegroundColor = ConsoleColor.Red;. Przywrócenie: Console.ResetColor().
Program.cs
Console.Title = "Moj program";

Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Operacja zakonczona powodzeniem.");
Console.ResetColor();

Console.WriteLine();
Console.Write("Nacisnij dowolny klawisz...");
Console.ReadKey(true);

Kolorów używaj oszczędnie

Zielony przy powodzeniu i czerwony przy błędzie — tak. Tęcza w każdej linii sprawia, że program wygląda amatorsko i gorzej się czyta. Pamiętaj też o ResetColor(), inaczej kolor zostanie ustawiony aż do zamknięcia okna.

PRZYKŁAD Z OMÓWIENIEM

Ile potrwa pobieranie pliku?

Program szacuje czas przy stałej prędkości. Obie jednostki są podane w megabajtach: MB i MB/s, nie w megabitach. Limity to zasady tego ćwiczenia, a nie ograniczenia typu double.

Program.cs — cały przykład
Console.Write("Rozmiar pliku w MB (np. 120): ");
bool okRozmiar = double.TryParse(Console.ReadLine(), out double rozmiar);
Console.Write("Predkosc w MB/s (np. 8): ");
bool okPredkosc = double.TryParse(Console.ReadLine(), out double predkosc);

if (!okRozmiar || !okPredkosc)
{
    Console.WriteLine("Wpisz liczby.");
}
else if (!double.IsFinite(rozmiar) || !double.IsFinite(predkosc) ||
         rozmiar <= 0 || rozmiar > 100000 || predkosc < 0.001 || predkosc > 100000)
{
    Console.WriteLine("Rozmiar: (0, 100000] MB, predkosc: [0,001, 100000] MB/s.");
}
else
{
    double sekundy = rozmiar / predkosc;
    Console.WriteLine($"Szacowany czas: {sekundy:F1} s");
}
Przebieg dla polskich ustawień regionalnych
Rozmiar pliku w MB (np. 120): 120
Predkosc w MB/s (np. 8): 8
Szacowany czas: 15,0 s

Omówienie użytych elementów

Console.Write wyświetla pytanie bez nowego wiersza i zwraca void. Console.ReadLine zwraca string? — tekst lub null. double.TryParse zwraca bool i przez out wpisuje wartość liczby. Korzysta z bieżącej kultury; w pracowni z polską kulturą separator dziesiętny to przecinek. double.IsFinite zwraca bool i odrzuca NaN oraz nieskończoności, które także mogą zostać poprawnie sparsowane. Console.WriteLine wyświetla wynik w nowym wierszu, a F1 oznacza jedno miejsce po przecinku.

if uruchamia blok dla prawdziwego warunku; else if sprawdza następny warunek, a else wykonuje pozostały przypadek. To zapowiedź lekcji 14. Najpierw sprawdzamy parsowanie, potem zakres, a dopiero na końcu dzielimy. Dzięki minimalnej prędkości i maksymalnemu rozmiarowi wynik pozostaje skończony.

Sprawdź: 120 i 8 → 15 sekund; 0 i 8 → odrzucenie; 120 i 0 → odrzucenie; kot i 8 → informacja o złym formacie; NaN i 8 → odrzucenie.

CZĘSTE BŁĘDY

Na co uważać

KodProblem
int wiek = Console.ReadLine(); CS0029 — ReadLine zwraca tekst, nie liczbę. Potrzebna konwersja.
int wiek = int.Parse(Console.ReadLine()); Kompiluje się, ale przerwie program, gdy użytkownik wpisze cokolwiek innego niż liczbę. Użyj TryParse.
Console.WriteLine("Podaj wiek: "); Nie błąd, ale kursor przeskoczy do nowej linii i program będzie wyglądał na zawieszony. Do zachęt używaj Write.
Console.Write("Podaj wiek:"); Brak spacji na końcu — wpisany tekst sklei się z dwukropkiem.
zachęta bez formatu "Podaj wzrost: " nie mówi, czy chodzi o metry czy centymetry ani czy pisać kropkę czy przecinek. Dodaj przykład.
sprawdzenie zakresu bez sprawdzenia konwersji Gdy TryParse zawiedzie, zmienna dostaje zero — a zero często mieści się w dozwolonym zakresie. Najpierw pytaj, czy konwersja się udała.
Console.ReadKey() bez argumentu Naciśnięty klawisz wypisze się na ekranie. Użyj ReadKey(true).
brak ResetColor() Ustawiony kolor zostaje do końca działania programu — także dla komunikatów systemowych.
ZADANIA

Zadania

ZAD 1Powitanie★☆☆

Program pyta o imię i rok urodzenia, po czym wypisuje powitanie z obliczonym wiekiem. Zadbaj o poprawne zachęty.

ZAD 2Zamiana jednostek★☆☆

Wczytaj długość w centymetrach i wypisz ją w metrach, calach i stopach. Przelicznik: 1 cal = 2,54 cm, 1 stopa = 30,48 cm.

ZAD 3Kalkulator dwóch liczb★★☆

Wczytaj dwie liczby całkowite i wypisz ich sumę, różnicę, iloczyn oraz iloraz z dokładnością do dwóch miejsc. Zabezpiecz się przed dzieleniem przez zero.

ZAD 4Rachunek za prąd★★☆

Wczytaj stan licznika z poprzedniego i bieżącego miesiąca oraz cenę za kilowatogodzinę. Oblicz zużycie i kwotę do zapłaty. Sprawdź, czy nowy stan nie jest mniejszy od poprzedniego.

ZAD 5Ankieta★★★

Napisz krótką ankietę: imię, wiek, ulubiony przedmiot oraz odpowiedź tak/nie na pytanie, czy uczeń lubi programować. Na końcu wypisz podsumowanie w ramce z gwiazdek. Odpowiedź „tak” ma być rozpoznawana niezależnie od wielkości liter.

PODSUMOWANIE

Co trzeba zapamiętać

  • Console.ReadLine zwraca wpisany wiersz jako string albo null na końcu strumienia wejściowego.
  • Console.Write wyświetla zachętę bez końca wiersza.
  • ?? wybiera wartość zastępczą tylko dla null, nie dla pustego tekstu.
  • TryParse sprawdza zapis liczby, a osobne warunki sprawdzają jej sens i zakres.
  • Dla double wymagającego skończonej wartości sprawdź double.IsFinite.
  • Parsowanie i formatowanie bez jawnej kultury korzystają z kultury bieżącej.
  • ReadKey(true) odczytuje klawisz bez jego wypisania; przekierowane wejście może nie obsługiwać tej operacji.
  • Po zmianie kolorów konsoli ResetColor przywraca domyślne ustawienia.
Postęp zapisuje się w tej przeglądarce.