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ś.
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.ReadLinepodkreśla się na żółto
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.
Console.Write("Jak masz na imie? ");
string imie = Console.ReadLine();
Console.WriteLine($"Milo cie poznac, {imie}!");
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.
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ązanie | Kiedy |
|---|---|
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.
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.
// ✗ 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.
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.
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:
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ą
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.
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.
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.");
}
| Wpisane | Który blok się wykona | Dlaczego |
|---|---|---|
abc | pierwszy | konwersja się nie udała |
-5 | drugi | konwersja OK, ale wartość poza zakresem |
200 | drugi | jak wyżej |
17 | trzeci | wszystko 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.
Pozostałe metody klasy Console
| Metoda | Zwraca | Dział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.Title | string |
Właściwość — ustawia napis na pasku tytułu okna: Console.Title = "Kalkulator";. |
Console.ForegroundColor | kolor | Zmienia kolor tekstu: Console.ForegroundColor = ConsoleColor.Red;. Przywrócenie: Console.ResetColor(). |
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.
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.
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");
}Rozmiar pliku w MB (np. 120): 120
Predkosc w MB/s (np. 8): 8
Szacowany czas: 15,0 sOmó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.
Na co uważać
| Kod | Problem |
|---|---|
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
Program pyta o imię i rok urodzenia, po czym wypisuje powitanie z obliczonym wiekiem. Zadbaj o poprawne zachęty.
Wczytaj długość w centymetrach i wypisz ją w metrach, calach i stopach. Przelicznik: 1 cal = 2,54 cm, 1 stopa = 30,48 cm.
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.
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.
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.
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.