Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00243 005131 13083135 na godz. na dobę w sumie
Język C. Nowoczesne programowanie. Wydanie II - książka
Język C. Nowoczesne programowanie. Wydanie II - książka
Autor: Liczba stron: 936
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-2805-6 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> c - programowanie
Porównaj ceny (książka, ebook, audiobook).

Język C żyje i ma się dobrze. Sprawdź, co nowego w wersji C99!

Język C należy do nielicznej grupy języków, które sprawdzają się w środowiskach produkcyjnych, a jednocześnie nadają się do nauki programowania na uczelniach wyższych. Dzięki logicznej i przejrzystej składni, jasno określonym zasadom wykorzystania oraz ogromnym możliwościom język ten pomimo swojego wieku cieszy się popularnością i uznaniem. Nawet dziś, kiedy na rynku panują niepodzielnie Java oraz .NET, język C znalazł swoją niszę i świetnie ją wypełnia. Na tym polu żaden współczesny język nie ma z nim żadnych szans!

Kolejne wydanie książki rozszerzono między innymi o elementy zawarte w specyfikacji oznaczonej numerem C99 (ISO 9899:1999). Co jeszcze wyróżnia tę książkę? Jej pierwsze wydanie było wykorzystywane na kursach programowania prowadzonych przez 225 uczelni. Dzięki temu zaliczana jest ona do najbardziej znaczących wydawnictw dotyczących języka C. Wydanie drugie powiela zalety pierwszego, a dodatkowo zostało rozbudowane o jeszcze większą liczbę przykładów, pytań, ćwiczeń i zadań programistycznych.

W trakcie pasjonującej lektury - zgadza się, K.N. King potrafi w ten sposób pisać o swoim ulubionym języku - poznasz wszystkie aspekty programowania w języku C, począwszy od jego historii, poprzez fundamentalne pojęcia funkcji, zmiennych, a skończywszy na zarządzaniu pamięcią oraz wykorzystaniu wskaźników. 'Język C. Nowoczesne programowanie. Wydanie II' to obowiązkowa pozycja dla każdego studenta poznającego tajniki tego języka. Programiści znający język C niewątpliwie docenią kunszt autora, a książka znajdzie zastosowanie jako przekrojowy przewodnik - taka pozycja powinna być na półce każdego programisty!

Poznaj język C, korzystając z uznanego podręcznika!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Język C. Nowoczesne programowanie. Wydanie II Autor: K. N. King Tłumaczenie: Przemysław Szeremiota ISBN: 978-83-246-2805-6 Tytuł oryginału: C Programming: A Modern Approach, 2nd Edition Format: B5, stron: 928 Język C żyje i ma się dobrze. Sprawdź, co nowego w wersji C99! • Jak wygląda proces standaryzacji języka? • Jak komentować kod? • Jak przygotować projekt programu? Język C należy do nielicznej grupy języków, które sprawdzają się w środowiskach produkcyjnych, a jednocześnie nadają się do nauki programowania na uczelniach wyższych. Dzięki logicznej i przejrzystej składni, jasno określonym zasadom wykorzystania oraz ogromnym możliwościom język ten pomimo swojego wieku cieszy się popularnością i uznaniem. Nawet dziś, kiedy na rynku panują niepodzielnie Java oraz .NET, język C znalazł swoją niszę i świetnie ją wypełnia. Na tym polu żaden współczesny język nie ma z nim żadnych szans! Kolejne wydanie książki rozszerzono między innymi o elementy zawarte w specyfikacji oznaczonej numerem C99 (ISO 9899:1999). Co jeszcze wyróżnia tę książkę? Jej pierwsze wydanie było wykorzystywane na kursach programowania prowadzonych przez 225 uczelni. Dzięki temu zaliczana jest ona do najbardziej znaczących wydawnictw dotyczących języka C. Wydanie drugie powiela zalety pierwszego, a dodatkowo zostało rozbudowane o jeszcze większą liczbę przykładów, pytań, ćwiczeń i zadań programistycznych. W trakcie pasjonującej lektury – zgadza się, K.N. King potrafi w ten sposób pisać o swoim ulubionym języku – poznasz wszystkie aspekty programowania w języku C, począwszy od jego historii, poprzez fundamentalne pojęcia funkcji, zmiennych, a skończywszy na zarządzaniu pamięcią oraz wykorzystaniu wskaźników. „Język C. Nowoczesne programowanie. Wydanie II” to obowiązkowa pozycja dla każdego studenta poznającego tajniki tego języka. Programiści znający język C niewątpliwie docenią kunszt autora, a książka znajdzie zastosowanie jako przekrojowy przewodnik – taka pozycja powinna być na półce każdego programisty! Poznaj język C, korzystając z uznanego podręcznika! Idź do • Spis treści • Przykładowy rozdział Katalog książek • Katalog online • Zamów drukowany katalog Twój koszyk • Dodaj do koszyka Cennik i informacje • Zamów informacje o nowościach • Zamów cennik Czytelnia • Fragmenty książek online Kontakt Helion SA ul. Kościuszki 1c 44-100 Gliwice tel. 32 230 98 63 e-mail: helion@helion.pl © Helion 1991–2010 SPIS TREĝCI WstĊp 1. WPROWADZENIE 1.1. Historia jĊzyka C Początki Standaryzacja JĊzyki oparte na C 1.2. Mocne i sáabsze strony jĊzyka C Mocne strony SáaboĞci Efektywne stosowanie jĊzyka C 2. FUNDAMENTY JĉZYKA C 2.1. Piszemy prosty program WyĞwietlamy cytat Kompilacja i konsolidacja Zintegrowane Ğrodowiska programistyczne 2.2. Ogólna postaü prostego programu w C 2.3. 2.4. Dyrektywy preprocesora Funkcje Instrukcje Wypisywanie ciągów znakowych Komentarze Zmienne i przypisania Typy Deklaracje Przypisania Wypisywanie wartoĞci zmiennej Obliczanie gabarytu przesyáki Inicjalizacja Wypisywanie wartoĞci wyraĪeĔ 19 29 29 29 30 31 32 33 33 34 39 39 40 40 41 42 43 43 44 45 46 48 48 48 49 50 51 52 53 5 6 Spis treĞci 3. 2.5. Wczytywanie danych 2.6. 2.7. Obliczanie gabarytu przesyáki (podejĞcie drugie) Definiowanie nazw dla staáych Konwersja skali Fahrenheita na skalĊ Celsjusza Identyfikatory Sáowa kluczowe 2.8. Ogólny ukáad programu C FORMATOWANIE WEJĝCIA-WYJĝCIA 3.1. Funkcja printf Specyfikatory konwersji Wykorzystanie printf do formatowania liczb Znaki sterujące Funkcja scanf Dziaáanie funkcji scanf Zwykáe znaki w ciągu formatującym funkcji scanf Skutki mylenia printf ze scanf Dodawanie uáamków 3.2. 4. WYRAĩENIA 4.1. Operatory arytmetyczne PierwszeĔstwo i áącznoĞü operatorów Obliczanie cyfry kontrolnej kodu kreskowego 4.2. Operatory przypisania Przypisania proste L-wartoĞci Przypisania záoĪone 4.3. Operatory inkrementacji i dekrementacji 4.4. Obliczanie wartoĞci wyraĪeĔ KolejnoĞü obliczania podwyraĪeĔ Instrukcje wyraĪeniowe 4.5. 5. INSTRUKCJE WYBORU 5.1. WyraĪenia logiczne Operatory relacji Operatory porównaĔ Operatory logiczne Instrukcja if Instrukcje blokowe Klauzula else Kaskadowe instrukcje if Obliczanie prowizji brokera gieádowego Problem „bezpaĔskiego” else WyraĪenia warunkowe WartoĞci boolowskie w C89 WartoĞci boolowskie w C99 Instrukcja switch Rola instrukcji break Wypisywanie daty w zapisie urzĊdowym 5.2. 5.3. 53 54 55 55 57 58 58 69 69 70 72 73 74 76 78 79 79 85 86 87 88 91 91 92 93 94 96 97 98 107 108 108 109 109 111 112 112 114 115 116 117 118 120 120 123 124 Spis treĞci 7 133 134 135 136 137 137 138 139 141 142 143 143 144 146 146 147 148 149 151 6.4. 6.5. 7.1. 7.2. 7.3. 7.4. 7.5. 6. 6.2. 6.3. INSTRUKCJE PĉTLI Instrukcja while 6.1. PĊtle nieskoĔczone Wypisywanie tabeli kwadratów liczb Obliczanie sumy szeregu liczb Instrukcja do Obliczanie liczby cyfr w liczbie caákowitej Instrukcja for Idiomy instrukcji for Pomijanie wyraĪeĔ w instrukcji for Instrukcje for w C99 Operator przecinka Wypisywanie tabeli kwadratów liczb (podejĞcie drugie) Przerywanie pĊtli Instrukcja break Instrukcja continue Instrukcja goto Saldo konta Instrukcja pusta 7. PODSTAWOWE TYPY C 161 Typy caákowite 161 Typy caákowite w C99 164 Literaáy caákowite 164 Literaáy caákowite w C99 166 Przepeánienie zakresu 166 Wczytywanie i wypisywanie wartoĞci caákowitych 166 Sumowanie szeregu liczb caákowitych (podejĞcie drugie) 167 Typy zmiennoprzecinkowe 168 Literaáy zmiennoprzecinkowe 170 Wczytywanie i wypisywanie wartoĞci zmiennoprzecinkowych 170 Typy znakowe 171 Operacje na znakach 172 Znaki ze znakiem i bez znaku 173 Typy arytmetyczne 173 Znaki sterujące 174 Funkcje do manipulowania znakami 176 Wczytywanie i wypisywanie znaków funkcjami scanf i printf 176 Wczytywanie i wypisywanie znaków funkcjami getchar i putchar 177 179 OkreĞlanie dáugoĞci komunikatu 180 Konwersja typów 181 Zwyczajne konwersje arytmetyczne Konwersja przy przypisaniu 183 184 Niejawne konwersje w C99 185 Rzutowanie 186 Definicje typów 187 Zalety definicji typów Definicje typów a przenoĞnoĞü programów 188 189 7.6. Operator sizeof 8 Spis treĞci 8. 9. TABLICE 8.1. Tablice jednowymiarowe Indeksowanie tablic Odwracanie szeregu liczbowego Inicjalizacja tablicy Inicjalizatory desygnowane Sprawdzanie, czy liczba zawiera powtarzające siĊ cyfry Operator sizeof dla tablic Naliczanie odsetek Tablice wielowymiarowe Inicjalizowanie tablic wielowymiarowych Staáe tablicowe Rozdawanie kart Tablice o zmiennej liczbie elementów (C99) FUNKCJE 9.1. 8.2. 8.3. 9.2. 9.3. 9.4. 9.5. 9.6. Definiowanie i wywoáywanie funkcji Obliczanie Ğrednich Odliczanie WyĞwietlanie napisu (kolejne podejĞcie) Definicja funkcji Wywoáanie funkcji Sprawdzanie, czy podana liczba jest liczbą pierwszą Deklaracja funkcji Argumenty Konwersje argumentów Argumenty tablicowe Parametry tablicowe o zmiennym rozmiarze Deklaracje parametrów tablicowych ze sáowem static Literaáy tablicowe Instrukcja return ZakoĔczenie programu Funkcja exit Rekurencja Algorytm quicksort quicksort 10. ORGANIZACJA PROGRAMU 10.1. Zmienne lokalne Zmienne statyczne funkcji Parametry 10.2. Zmienne zewnĊtrzne 10.3. Bloki 10.4. ZasiĊg zmiennych 10.5. Organizacja programu w C Siáa rozdania pokerowego Przykáad. Stos implementowany na zmiennych zewnĊtrznych Zalety i wady zmiennych zewnĊtrznych Zgadywanka liczbowa 199 199 200 202 203 203 204 205 206 208 209 210 211 212 223 223 224 225 226 227 229 230 231 233 234 235 238 240 241 242 243 243 244 246 248 261 261 262 263 263 263 264 266 270 271 272 273 Spis treĞci 9 11. WSKAħNIKI 11.1. Zmienne wskaĨnikowe Deklarowanie zmiennych wskaĨnikowych 11.2. Operator adresu i wyáuskania Operator adresu Operator wyáuskania 11.3. Przypisania a wskaĨniki 11.4. WskaĨniki jako argumenty funkcji Wyszukiwanie najwiĊkszego i najmniejszego elementu tablicy Ochrona argumentów za pomocą const 11.5. WskaĨniki jako wartoĞci zwracane 12. WSKAħNIKI A TABLICE 12.1. Arytmetyka wskaĨników Dodawanie liczby do wskaĨnika Odejmowanie liczby od wskaĨnika Odejmowanie wskaĨnika od wskaĨnika Porównywanie wskaĨników WskaĨniki do literaáów tablicowych 12.2. Przetwarzanie tablic na bazie wskaĨników àączenie operatorów * i ++ 12.3. Nazwa tablicy jako wskaĨnik Odwracanie szeregu liczbowego Argumenty tablicowe (ponownie) WskaĨnik jako nazwa tablicy 12.4. WskaĨniki a tablice wielowymiarowe Przetwarzanie elementów tablicy wielowymiarowej Przetwarzanie wierszy tablicy wielowymiarowej Przetwarzanie kolumn tablicy wielowymiarowej Nazwa tablicy wielowymiarowej jako wskaĨnik 12.5. WskaĨniki a tablice o zmiennym rozmiarze (C99) 13. CIĄGI ZNAKÓW 13.1. Literaáy napisowe Znaki sterujące w literaáach napisowych Kontynuacja literaáu napisowego w nowym wierszu Literaáy napisowe a pamiĊü programu Operacje na literaáach napisowych Literaáy napisowe a literaáy znakowe 13.2. Zmienne napisowe Inicjalizowanie zmiennej napisowej Tablice znaków a wskaĨniki do znaków 13.3. Wczytywanie i wypisywanie napisów Wypisywanie napisów funkcjami printf i puts Wczytywanie ciągów znaków funkcjami scanf i gets Wczytywanie napisów znak po znaku 13.4. Odwoáania do pojedynczych znaków w ciągu 13.5. Funkcje biblioteczne jĊzyka C Funkcja strcpy (kopiowanie ciągów) Funkcja strlen (dáugoĞü ciągu) Funkcja strcat (áączenie ciągów) 283 283 284 285 285 286 287 289 291 293 293 301 302 303 303 304 304 304 305 306 307 308 309 311 311 311 312 313 314 314 323 323 324 324 325 326 326 327 328 329 330 330 331 333 334 335 336 338 338 10 Spis treĞci 13.6. Funkcja strcmp (porównywanie ciągów) Wypisywanie notatek kalendarzowych Idiomy Szukanie koĔca ciągu Kopiowanie ciągu 13.7. Tablice ciągów znaków Argumenty wywoáania programu Weryfikacja nazw planet 14. PREPROCESOR 14.1. Jak dziaáa preprocesor 14.2. Dyrektywy preprocesora 14.3. Makrodefinicje Makrodefinicje proste Makrodefinicje sparametryzowane Operator # Operator ## Ogólne wáaĞciwoĞci makrodefinicji Nawiasy w makrodefinicjach Tworzenie dáugich makrodefinicji Makrodefinicje predefiniowane Dodatkowe makrodefinicje predefiniowane w C99 Puste argumenty makrodefinicji Makrodefinicje o zmiennej liczbie argumentów Identyfikator __func__ 14.4. Warunkowa kompilacja kodu Dyrektywy #if i #endif Operator defined Dyrektywy #ifdef i #ifndef Dyrektywy #elif i #else Zastosowania warunkowej kompilacji kodu Inne dyrektywy Dyrektywa #error Dyrektywa #line Dyrektywa #pragma Operator _Pragma 14.5. 15. DUĩE PROGRAMY 15.1. Pliki Ĩródáowe 15.2. Pliki nagáówkowe Dyrektywa #include Wspólne makrodefinicje i synonimy typów Wspólne prototypy funkcji Wspólne deklaracje zmiennych ZagnieĪdĪone dyrektywy #include Ochrona plików nagáówkowych Dyrektywy #error w plikach nagáówkowych 15.3. Podziaá programu na pliki Formatowanie tekstu 15.4. Budowanie programu z wielu plików Pliki Makefile BáĊdy konsolidowania programu 339 340 343 343 345 347 349 351 363 363 366 367 367 370 373 374 375 376 377 379 380 381 382 383 384 384 385 386 386 387 388 389 390 391 391 401 401 403 403 405 406 407 409 410 411 411 412 419 419 422 Spis treĞci 11 Przebudowa programu Definiowanie makrodefinicji na zewnątrz programu 16. STRUKTURY, UNIE I WYLICZENIA 16.1. Zmienne strukturalne Deklarowanie zmiennych strukturalnych Inicjalizowanie zmiennych strukturowych Inicjalizatory desygnowane Operacje na strukturach 16.2. Typy strukturowe Deklarowanie znacznika struktury Definiowanie typu strukturowego Struktury jako argumenty i wartoĞci zwracane funkcji Literaáy strukturowe 16.3. Tablice i struktury zagnieĪdĪone Struktury struktur Tablice struktur Inicjalizowanie tablic struktur Zarządzanie bazą danych magazynu 16.4. Unie Unie dla oszczĊdnoĞci Unie jako mieszane struktury danych Pole „wyróĪnika” w unii 16.5. Wyliczenia Znaczniki i typy wyliczeniowe Wyliczenia jako liczby caákowite Wyliczenia jako wyróĪniki unii 17. ZAAWANSOWANE ZASTOSOWANIA WSKAħNIKÓW 17.1. Dynamiczny przydziaá pamiĊci Funkcje przydziaáu pamiĊci WskaĨniki puste 17.2. Dynamiczny przydziaá ciągów znaków Przydziaá pamiĊci dla ciągu znaków za pomocą funkcji malloc Przydziaáy dynamiczne w funkcjach operujących na ciągach znaków Tablice ciągów przydzielanych dynamicznie Wypisywanie notatek kalendarzowych (podejĞcie drugie) 17.3. Tablice przydzielane dynamicznie Przydziaá pamiĊci dla ciągu znaków za pomocą funkcji malloc Funkcja calloc Funkcja realloc 17.4. Zwalnianie pamiĊci Funkcja free Problem „wiszących” wskaĨników 17.5. Listy elementów Deklarowanie typu wĊzáa Tworzenie wĊzáa listy Operator - Wstawianie wĊzáa na początek listy Przeszukiwanie listy Usuwanie wĊzáa z listy 422 425 431 431 432 433 434 435 436 437 438 439 440 441 441 442 443 444 450 452 454 455 456 457 458 459 469 470 470 471 472 472 473 474 475 476 477 478 478 479 480 481 481 482 483 484 484 487 488 12 Spis treĞci Listy uporządkowane Zarządzanie bazą danych magazynu (drugie podejĞcie) 17.6. WskaĨniki do wskaĨników 17.7. WskaĨniki do funkcji WskaĨniki do funkcji w roli argumentów Funkcja qsort Inne zastosowania wskaĨników do funkcji Tablice funkcji trygonometrycznych 17.8. WskaĨniki zastrzeĪone (C99) 17.9. Elastyczne skáadowe tablicowe (C99) 18. DEKLARACJE 18.1. Skáadnia deklaracji 18.2. Klasy przydziaáu WáasnoĞci zmiennych Klasa przydziaáu auto Klasa przydziaáu static Klasa przydziaáu extern Klasa przydziaáu register Klasa przydziaáu funkcji Podsumowanie 18.3. Kwalifikatory typów 18.4. Deklaratory Rozszyfrowywanie zawiáych deklaracji Stosowanie synonimów typów dla uproszczenia deklaracji Inicjalizatory Zmienne niezainicjalizowane 18.5. 18.6. Funkcje inline (C99) Definicje rozwijane w miejscu wywoáania Ograniczenia funkcji rozwijanych w miejscu wywoáania Funkcje inline w GCC 19. PROJEKT PROGRAMU 19.1. Moduáy SpójnoĞü i wspóázaleĪnoĞü Rodzaje moduáów 19.2. Ukrywanie informacji Moduá obsáugi stosu 19.3. Abstrakcyjne typy danych Hermetyzacja Typy niepeáne 19.4. Stos jako abstrakcyjny typ danych (ADT) Definiowanie interfejsu stosu w wersji ADT Implementacja stosu w wersji ADT (na bazie tablicy) Zmiana typu elementu w stosie w wersji ADT Implementowanie stosu ADT (na bazie tablicy dynamicznej) Implementowanie stosu ADT (na bazie listy) 19.5. Problemy projektowe przy ADT Nomenklatura Obsáuga báĊdów Uniwersalny typ ADT ADT w nowszych jĊzykach programowania 490 491 496 497 497 498 501 502 503 505 517 517 519 519 520 521 522 523 524 525 526 528 529 531 531 533 533 534 536 536 545 546 548 548 549 550 553 554 554 555 555 557 559 560 562 564 564 565 565 566 20. PROGRAMOWANIE NISKOPOZIOMOWE Spis treĞci 20.1. Operatory bitowe Operatory przesuniĊü bitowych Negacja, iloczyn, suma i suma wyáączająca Operatory bitowe w odwoáaniach do poszczególnych bitów wartoĞci liczbowych Operatory bitowe w odwoáaniach do pól bitowych Szyfrowanie XOR 20.3. 20.2. Pola bitowe w strukturach Reprezentacja pól bitowych Inne niskopoziomowe techniki programistyczne Definiowanie typów maszynowych Unie jako perspektywy WskaĨniki jako adresy Podgląd pamiĊci Kwalifikator typu volatile 21. BIBLIOTEKA STANDARDOWA 21.1. Stosowanie biblioteki standardowej Nazewnictwo w bibliotece standardowej Funkcje ukrywane przez makrodefinicje 21.2. Przegląd biblioteki standardowej C89 Diagnostyka Obsáuga znaków BáĊdy Cechy typów zmiennoprzecinkowych Rozmiary typów caákowitoliczbowych Lokalizacja programów Matematyka Skoki nielokalne Obsáuga sygnaáów Zmienne listy argumentów Podstawowe definicje WejĞcie-wyjĞcie NarzĊdzia Obsáuga ciągów znaków Daty i godziny 21.3. Uzupeánienia i zmiany w C99 Arytmetyka liczb zespolonych ĝrodowisko implementacji zmiennoprzecinkowej Znakowe konwersje typów caákowitoliczbowych Alternatywny zapis skáadni C WartoĞci i typy logiczne Typy caákowitoliczbowe Matematyka na uniwersalnych typach Operacje na znakach wielobajtowych NarzĊdzia mapowania i klasyfikacji znaków wielobajtowych 21.4. Nagáówek stddef.h — definicje podstawowe 21.5. Nagáówek stdbool.h (C99) — typy i wartoĞci logiczne 13 571 571 572 573 574 576 577 578 580 581 581 582 584 584 586 593 593 594 595 596 596 596 596 596 596 597 597 597 597 597 597 597 598 598 598 598 599 599 599 599 599 599 599 600 600 600 601 14 Spis treĞci 22. WEJĝCIE-WYJĝCIE 22.1. Strumienie WskaĨniki plikowe Strumienie standardowe a przekierowania Pliki tekstowe i pliki binarne 22.2. Operacje na plikach Otwieranie pliku Tryby dostĊpu do plików Zamykanie pliku Doáączanie pliku do otwartego strumienia Pobieranie nazw plików z wiersza polecenia Sprawdzanie moĪliwoĞci otwarcia pliku Pliki tymczasowe Buforowanie plików Inne operacje na plikach 22.3. Formatowanie wejĞcia-wyjĞcia Funkcje …printf Specyfikatory konwersji dla funkcji …printf Zmiany specyfikatorów konwersji w C99 Przykáady specyfikacji konwersji dla funkcji …printf Funkcje …scanf Ciągi formatujące funkcji …scanf Specyfikacje konwersji funkcji …scanf Zmiany specyfikatorów konwersji w C99 Przykáady dla funkcji scanf Wykrywanie koĔca strumienia wejĞciowego i báĊdów 22.4. WejĞcie-wyjĞcie znakowe 605 606 606 607 608 609 610 611 612 613 613 614 615 616 618 619 619 620 622 624 626 627 628 631 631 632 635 635 636 637 638 638 639 640 641 643 644 645 646 668 Funkcje wyjĞcia Funkcje wejĞcia Kopiowanie pliku Funkcje wyjĞcia Funkcje wejĞcia 22.5. Wierszowe wejĞcie-wyjĞcie 22.6. Blokowe wejĞcie-wyjĞcie 22.7. Pozycjonowanie w plikach Modyfikowanie pliku rekordów bazy danych 22.8. Funkcje wejĞcia-wyjĞcia w pamiĊci Funkcje wyjĞcia Funkcje wejĞcia 23. OBSàUGA LICZB I DANYCH ZNAKOWYCH 659 23.1. Nagáówek float.h — cechy typów zmiennoprzecinkowych 659 23.2. Nagáówek limits.h — rozmiary typów caákowitych 662 664 23.3. Nagáówek math.h — matematyka 664 665 666 666 667 BáĊdy Funkcje trygonometryczne Funkcje hiperboliczne Funkcje wykáadnicze i logarytmiczne Funkcje potĊgowe NajbliĪsza liczba caákowita, wartoĞü bezwzglĊdna, reszta z dzielenia Spis treĞci 23.4. Nagáówek math.h — matematyka (C99) Standard zmiennoprzecinkowy IEEE Typy Makrodefinicje BáĊdy Funkcje Makrodefinicje klasyfikujące Funkcje trygonometryczne Funkcje hiperboliczne Funkcje wykáadnicze i logarytmiczne Funkcje potĊgowe i funkcje wartoĞci bezwzglĊdnej Funkcje báĊdów i funkcje gamma Funkcje zaokrąglania Funkcje reszty z dzielenia Funkcja manipulacji Funkcje maksimum, minimum i róĪnicy dodatniej Zmiennoprzecinkowy iloczyn-suma Makrodefinicje porównaĔ 23.5. Nagáówek ctype.h — obsáuga znaków Funkcje klasyfikacji znaków Test funkcji klasyfikacji znaków Funkcje mapowania wielkoĞci liter Test funkcji zmiany wielkoĞci liter 23.6. Nagáówek string.h — obsáuga ciągów znaków Funkcje kopiujące Funkcje áączenia ciągów Funkcje porównaĔ Funkcje wyszukujące RóĪne 24. OBSàUGA BàĉDÓW 24.1. Nagáówek assert.h — diagnostyka 24.2. Nagáówek errno.h — báĊdy Funkcje perror i strerror 24.3. Nagáówek signal.h — obsáuga sygnaáów Makrodefinicje sygnaáów Funkcja signal Predefiniowane funkcje obsáugi sygnaáów Funkcja raise Testowanie mechanizmu sygnaáów 24.4. Nagáówek setjmp.h — skoki nielokalne Testowanie setjmp/longjmp 25. „MIĉDZYNARODÓWKA” 25.1. Nagáówek locale.h — Ğrodowiska jĊzykowe Kategorie Funkcja setlocale Funkcja localeconv 25.2. Znaki wielobajtowe i znaki poszerzone Znaki wielobajtowe Znaki poszerzone Unicode i uniwersalny zestaw znaków UCS 15 669 669 671 671 672 673 674 675 675 676 677 678 679 680 680 681 682 683 684 684 685 686 687 687 688 689 690 691 695 699 700 701 702 703 704 704 705 707 707 708 709 715 716 716 717 719 722 723 724 724 16 Spis treĞci 25.3. Dwuznaki i trójznaki 725 Kodowanie Unicode Funkcje konwersji znaków poszerzonych i wielobajtowych 727 Funkcje konwersji ciągów znaków poszerzonych i wielobajtowych 729 729 730 731 731 732 Trójznaki Dwuznaki Nagáówek iso646.h — symbole alternatywne 25.4. Uniwersalne nazwy znaków (C99) 25.5. Nagáówek wchar.h (C99) — dodatkowe narzĊdzia 733 734 735 737 738 743 743 747 747 748 749 750 755 755 758 758 759 760 761 762 764 765 766 768 769 770 771 772 774 778 787 788 788 790 790 791 dla znaków poszerzonych i wielobajtowych Orientacja strumienia Funkcje formatowanego wejĞcia-wyjĞcia dla znaków poszerzonych Funkcje wejĞcia-wyjĞcia dla znaków poszerzonych Obsáuga ciągów znaków poszerzonych Funkcja konwersji dat i godzin na ciągi znaków poszerzonych Dodatkowe funkcje konwersji znaków poszerzonych i wielobajtowych 25.6. Nagáówek wctype.h (C99) — klasyfikacja znaków poszerzonych Funkcje klasyfikacji znaków poszerzonych Rozszerzalne funkcje klasyfikacji znaków poszerzonych Funkcje zmiany wielkoĞci liter dla znaków poszerzonych Rozszerzalne funkcje zmiany wielkoĞci liter znaków poszerzonych 26. RÓĩNE 26.1. Nagáówek stdarg.h — zmienna liczba argumentów Wywoáanie funkcji o zmiennej liczbie argumentów Funkcje v…printf Funkcje v…scanf 26.2. Nagáówek stdlib.h — inne narzĊdzia Funkcje konwersji liczbowych Testowanie funkcji konwersji liczbowych Funkcje sekwencji pseudolosowych Testowanie funkcji generowania liczb pseudolosowych Komunikacja ze Ğrodowiskiem wykonawczym Wyszukiwanie i sortowanie OkreĞlanie odlegáoĞci Funkcje arytmetyki liczb caákowitych 26.3. Nagáówek time.h — daty i godziny Funkcje operujące na datach i godzinach Funkcje konwersji dat i godzin Wypisywanie daty i godziny 27. ROZSZERZONE OPERACJE MATEMATYCZNE W C99 27.1. Nagáówek stdint.h — typy caákowite Typy nagáówka stdint.h Ograniczenia typów o okreĞlonym rozmiarze Ograniczenia pozostaáych typów caákowitych Makrodefinicje dla staáych caákowitych Spis treĞci 27.2. Nagáówek inttypes.h — konwersje typów caákowitych Makrodefinicje dla specyfikatorów konwersji Funkcje obsáugi najszerszych typów 27.3. Liczby zespolone (C99) Definicja liczb zespolonych Arytmetyka liczb zespolonych Typy zespolone w C99 Operacje na wartoĞciach zespolonych Reguáy konwersji dla typów zespolonych 27.4. Nagáówek complex.h (C99) — arytmetyka liczb zespolonych Makrodefinicje nagáówka complex.h CX_LIMITED_RANGE Funkcje nagáówka complex.h Funkcje trygonometryczne Funkcje hiperboliczne Funkcje wykáadnicze i logarytmiczne Funkcje potĊgowe i funkcje wartoĞci bezwzglĊdnych Inne Szukanie pierwiastków równania kwadratowego 27.5. Nagáówek tgmath.h (C99) — matematyka bez typów Makrodefinicje rozprowadzające wywoáania funkcji matematycznych Wywoáania makrodefinicji rozprowadzających 27.6. Nagáówek fenv.h (C99) — Ğrodowisko zmiennoprzecinkowe Stany i tryby jednostki zmiennoprzecinkowej Makrodefinicje nagáówka fenv.h FENV_ACCESS Funkcje wyjątków zmiennoprzecinkowych Funkcje zaokrąglania Funkcje Ğrodowiska Dodatek A Operatory jĊzyka C Dodatek B C99 kontra C89 Dodatek C C89 kontra K R Dodatek D Funkcje biblioteki standardowej Dodatek E Zestaw znaków ASCII Bibliografia Skorowidz 17 792 792 793 795 795 797 797 798 798 800 800 801 802 802 803 804 804 805 805 806 807 807 810 810 811 811 813 814 815 819 821 827 831 893 895 899 3 Formatowanie wejĞcia-wyjĞcia W poszukiwaniu nieosiągalnego na przeszkodzie staje tylko prostota. Do najczĊĞciej wykorzystywanych funkcji bibliotecznych jĊzyka C naleĪą printf i scanf, sáuĪące do obsáugi formatowanego wejĞcia i wyjĞcia programu. W tym rozdziale przekonasz siĊ o moĪliwoĞciach tych funkcji, ale teĪ o koniecznej ostroĪ- noĞci w ich stosowaniu. W podrozdziale 3.1 zajmiemy siĊ funkcją printf. Gáów- nym zagadnieniem podrozdziaáu 3.2 bĊdzie funkcja scanf. W Īadnym z pod- rozdziaáów nie zgáĊbimy jednak wszystkich detali — niektóre bĊdą musiaáy poczekaü do rozdziaáu 22. 3.1. Funkcja printf Funkcja printf sáuĪy do wypisywania na wyjĞciu programu zawartoĞci ciągu znaków, okreĞlanego mianem ciągu formatującego, który moĪe zawieraü sym- bole zastĊpcze dla wartoĞci zmiennych wstawianych do ciągu wypisywanego. W wywoáaniu funkcji printf musi siĊ znajdowaü ciąg formatujący, uzupeániony wartoĞciami, które mają byü podstawione w odpowiednie miejsca ciągu na wyjĞciu programu: printf(ciÈg-formatujÈcy, wyraĝenie1, wyraĝenie1, …); WartoĞci przekazywane do podstawienia do ciągu formatującego mogą byü sta- áymi, zmiennymi albo caáymi wyraĪeniami. Nie istnieje ograniczenie liczby war- toĞci wypisywanych w ramach pojedynczego wywoáania funkcji printf. Ciąg formatujący moĪe zawieraü zarówno zwyczajne znaki drukowalne, jak i tak zwane specyfikatory konwersji, rozpoczynające siĊ od znaku . Specyfi- kator konwersji to symbol zastĊpczy reprezentujący wartoĞü, która ma zostaü wstawiona w dane miejsce ciągu formatującego, wraz z opisem sposobu wypisa- nia wartoĞci. Informacje znajdujące siĊ za znakiem okreĞlają sposób konwersji 69 70 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia przekazanej wartoĞci z jej reprezentacji wewnĊtrznej (binarnej) na reprezentacjĊ drukowaną (znakową) — stąd pojĊcie „specyfikatora konwersji”. Na przykáad specyfikator konwersji d mówi, Īe printf ma zamieniü przekazaną wartoĞü typu int z jej reprezentacji binarnej na ciąg znaków kolejnych cyfr. Podobnie specyfikator f nakazuje zamianĊ wartoĞci zmiennoprzecinkowej (typu float) na znakową. Zwyczajne znaki zawarte w ciągu formatującym są wypisywane bez modyfi- kacji. Specyfikatory konwersji są natomiast zastĊpowane przez znakowe repre- zentacje przekazanych wartoĞci. WeĨmy nastĊpujący przykáad: int i, j; float x, y; i = 10; j = 20; x = 43.2892f; y = 5527.0f; printf( i = d, j = d, x = f, y = f , i, j, x, y); Takie wywoáanie funkcji printf spowoduje wypisanie na wyjĞciu: i = 10, j = 20, x = 43.289200, y = 5527.000000 Zwyczajne znaki w ciągu formatującym zostaáy po prostu skopiowane na wyjĞcie. Cztery specyfikatory konwersji zostaáy zaĞ zastąpione przez odpowiednio repre- zentowane wartoĞci zmiennych i, j, x i y (w tej kolejnoĞci). Specyfikatory konwersji Specyfikatory konwersji pozwalają programistom zachowaü duĪą dozĊ kontroli nad wyglądem (formatem) wypisywanych ciągów i wartoĞci. Z drugiej strony bywają skomplikowane i trudne do ogarniĊcia. Istotnie, szczegóáowe opisywanie specyfikatorów konwersji byáoby na tym wstĊpnym etapie omówienia przed- wczesne. Zapoznamy siĊ wiĊc tylko z najwaĪniejszymi cechami i moĪliwoĞciami dawanymi przez specyfikatory. W rozdziale 2. zauwaĪyliĞmy, Īe specyfikator konwersji moĪe zawieraü infor- macje sterujące formatowaniem wartoĞci. W szczególnoĞci zastosowaliĞmy spe- cyfikator .1f, aby ograniczyü liczbĊ wypisywanych cyfr po przecinku w war- toĞci typu float. Ogólniej rzecz biorąc, specyfikator konwersji moĪe przyjąü postaü m.pX albo -m.pX, gdzie m i p to staáe caákowite, a X to litera. WartoĞci m i p są opcjonalne. W przypadku nieobecnoĞci p nie stosuje siĊ równieĪ kropki oddzielającej m od p. W specyfikatorze konwersji 10.2f m wynosi 10, p wy- nosi 2, a X to f. W specyfikatorze 10f m wynosi 10, p (wraz z kropką) zostaáo pominiĊte, a X to f. Za to w .2f m zostaáo pominiĊte, a p wynosi 2. Minimalna szerokoĞü pola m okreĞla minimalną liczbĊ znaków, jaka zostanie wypisana na wyjĞciu przy wypisywaniu wartoĞci. JeĞli wypisywana wartoĞü jest w reprezentacji znakowej krótsza niĪ m znaków, zostanie wyrównana do minimal- nej szerokoĞci pola i do prawej strony pola (innymi sáowy, przed wáaĞciwą war- toĞü wstawiona bĊdzie odpowiednia liczba spacji). Na przykáad specyfikator 4d 3.1. Funkcja printf 71 Standard nie wymaga od kompilatorów jĊzyka C sprawdzania, czy liczba specy- fikatorów konwersji okreĞlona w ciągu formatującym odpowiada liczbie przeka- zanych wartoĞci. PoniĪsze wywoáanie funkcji printf posiada wiĊcej specyfika- torów konwersji niĪ wartoĞci do wypisania: printf( d d , i); /*** ħLE ***/ Funkcja printf wypisze poprawnie wartoĞü zmiennej i, a nastĊpnie wypisze drugą — oczekiwaną, ale nieokreĞloną — wartoĞü liczbową. Podobnie káopotliwy jest nadmiar wartoĞci w stosunku do specyfikatorów konwersji: printf( d , i, j); /*** ħLE ***/ W tym przypadku funkcja printf wypisze jedynie wartoĞü i, a wartoĞü j zosta- nie pominiĊta. Kompilatory nie są teĪ zobligowane do sprawdzania, czy specyfikatory kon- wersji odpowiadają typom przekazywanych wartoĞci. JeĞli programista zastosuje nieodpowiednie specyfikatory, program moĪe wypisaü na wyjĞciu kompletne bzdury. WeĨmy dla przykáadu wywoáanie funkcji printf, w którym zmienna i typu int i zmienna x typu float zostaną przekazane w záej kolejnoĞci: printf( f d , i, x); /*** ħLE ***/ PoniewaĪ funkcja printf realizuje wytyczne z ciągu formatującego, wypisze na wyjĞciu wartoĞü float, a za nią wartoĞü int. Niestety, obie wartoĞci jako Ĩle zinterpretowane bĊdą niepoprawne. spowoduje wypisanie wartoĞci 123 jako ·123 (w caáym bieĪącym rozdziale w miejsce niewidocznych spacji ilustrujących formatowanie wartoĞci bĊdą wsta- wiane znaki ·). Z kolei kiedy wypisywana wartoĞü bĊdzie dáuĪsza niĪ m znaków, pole zostanie automatycznie poszerzone do szerokoĞci potrzebnej do zmieszczenia wartoĞci: specyfikator 4d dla wartoĞci 12345 spowoduje wypisanie na wyjĞciu 12345 — bez ucinania cyfr. Znak minusa przed m wymusza wyrównanie wartoĞci w polu do lewej strony: specyfikator 4d dla wartoĞci 123 da na wyjĞciu 123·. Znaczenie specyfikatora precyzji p jest trudniejsze do opisania, poniewaĪ jego dziaáanie jest zaleĪne od X, czyli wáaĞciwego specyfikatora konwersji. X okreĞla rodzaj konwersji do przeprowadzenia przed wypisaniem wartoĞci. Do najpopu- larniejszych konwersji wartoĞci liczbowych naleĪą: Q d — konwersja wartoĞci caákowitej do postaci dziesiĊtnej. W takim ukáadzie p oznacza minimalną liczbĊ cyfr do wypisania (w razie potrzeby przed wypi- sywaną liczbą dopisywane są zera). Przy braku p uznaje siĊ, Īe ma ono wartoĞü 1 (innymi sáowy, d jest tym samym co .1d). Q e — konwersja wartoĞci zmiennoprzecinkowej do postaci wykáadnikowej (w tzw. notacji naukowej). W takim ukáadzie p okreĞla liczbĊ cyfr do wypi- sania po przecinku dziesiĊtnym (wartoĞü domyĞlna to 6). Dla p równego 0 czĊĞü po przecinku nie jest wyĞwietlana w ogóle. Q f — konwersja wartoĞci zmiennoprzecinkowej do postaci dziesiĊtnej, bez wykáadnika. W tym ukáadzie p ma takie samo znaczenie jak przy konwersji e. 72 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia Q g — konwersja wartoĞci zmiennoprzecinkowej do postaci wykáadnikowej albo dziesiĊtnej, zaleĪnie od rozmiaru liczby. W tym ukáadzie p oznacza maksy- malną liczbĊ cyfr znaczących (nie cyfr po przecinku) do wypisania. Inaczej niĪ przy konwersji f, konwersja g nie bĊdzie wypisywaáa zer po prawej stronie wartoĞci. Co wiĊcej, jeĞli konwertowana wartoĞü nie ma cyfr po przecinku, konwersja g nie wypisze takĪe symbolu przecinka. Specyfikator konwersji g jest przydatny zwáaszcza do wypisywania wartoĞci, dla których rozmiar reprezentacji nie da siĊ ustaliü na etapie pisania programu, oraz wartoĞci z bardzo szerokich dziedzin. Konwersja g dla niezbyt wielkich i niezbyt maáych wartoĞci bĊdzie owocowaáa zapisem dziesiĊtnym. Dla wartoĞci bardzo maáych i bardzo duĪych zastosowany bĊdzie zapis wykáadnikowy, wymagający mniejszej liczby znaków. d, e, f i g to bynajmniej nie wszystkie specyfikatory konwersji. Pozo- staáe bĊdą stopniowo wprowadzane przy okazji omawiania kolejnych zagadnieĔ. Peána lista specyfikatorów wraz z objaĞnieniem ich znaczenia i dziaáania znajduje siĊ w podrozdziale 22.3. specyfikatory dla wartoĞci caákowitych ¥ 7.1 specyfikatory dla wartoĞci zmiennoprzecinkowych ¥ 7.2 dla wartoĞci znakowych ¥ 7.3 specyfikatory specyfikatory dla ciągów znaków ¥ 13.3 PROGRAM tprintf.c Wykorzystanie printf do formatowania liczb PoniĪszy program ilustruje sposób wykorzystania funkcji printf do wypisy- wania wartoĞci caákowitych i zmiennoprzecinkowych w rozmaitych formatach: /* Wypisuje wartoĞci int i float w róĪnych formatach */ #include stdio.h int main(void) { int i; float x; i = 40; x = 839.21f; printf( | d| 5d| -5d| 5.3d| , i, i, i, i); printf( | 10.3f| 10.3e| -10g| , x, x, x); return 0; } Znaki | w ciągach formatujących dla funkcji printf sáuĪą jedynie do roz- dzielenia wypisywanych wartoĞci i zilustrowania szerokoĞci pól, w których są wypisywane. W przeciwieĔstwie do znaków i znak | nie ma specjalnego zna- czenia dla funkcji printf. Program wypisuje na wyjĞciu coĞ takiego: |40| 40|40 | 040| | 839.210| 8.392e+02|839.21 | Spróbujmy przeanalizowaü znaczenie i dziaáanie specyfikatorów konwersji wykorzystanych w tym programie: 3.1. Funkcja printf 73 Q d — wypisanie i w zapisie dziesiĊtnym przy jak najmniejszej liczbie znaków. Q 5d — wypisanie wartoĞci i w zapisie dziesiĊtnym w polu o szerokoĞci co najmniej 5 znaków. PoniewaĪ wáaĞciwa wartoĞü i ma zaledwie dwa znaki, pole jest wypeániane trzema spacjami od lewej strony. Q -5d — wypisanie wartoĞci i w zapisie dziesiĊtnym w polu o szerokoĞci co najmniej 5 znaków. PoniewaĪ wáaĞciwa wartoĞü i ma zaledwie dwa znaki, pole jest wypeániane trzema spacjami po prawej stronie wartoĞci (wartoĞü i jest wiĊc wyrównana w piĊcioznakowym polu do lewej strony). Q 5.3d — wypisanie wartoĞci i w zapisie dziesiĊtnym w polu o szerokoĞci co najmniej 5 znaków i przy reprezentowaniu wartoĞci co najmniej trzema cyframi. PoniewaĪ i ma tylko dwie cyfry, przed wáaĞciwą wartoĞcią wstawiana jest pojedyncza cyfra zero. Wynikowa trzyznakowa wartoĞü jest wypisywana w polu o szerokoĞci 5 znaków, a wiĊc jest poprzedzona dwoma spacjami (war- toĞü i jest wyrównana do prawej strony pola). Q 10.3f — wypisanie wartoĞci x w zapisie dziesiĊtnym z przecinkiem w polu o szerokoĞci co najmniej 10 znaków, z trzema cyframi po przecinku. PoniewaĪ wartoĞü x zajmuje jedynie 7 znaków (trzy przed przecinkiem i trzy po prze- cinku oraz sam przecinek), jest uzupeániana trzema spacjami z lewej strony. Q 10.3e — wypisanie wartoĞci x w zapisie wykáadnikowym w polu o sze- rokoĞci co najmniej 10 znaków, z trzema cyframi po przecinku. Tak zapisana wartoĞü x zajmuje 9 znaków, wiĊc jest uzupeániona spacją z lewej strony. Q -10g — wypisanie wartoĞci x w zapisie wykáadnikowym albo dziesiĊtnym z przecinkiem w polu o szerokoĞci co najmniej 10 znaków, z trzema cyframi po przecinku. W naszym przypadku wartoĞü x zostaáa zamieniona na dzie- siĊtną z przecinkiem. ObecnoĞü znaku - w specyfikatorze konwersji wymusza wyrównanie wartoĞci do lewej strony pola czterema spacjami za wáaĞciwą wartoĞcią. Znaki sterujące Symbol , wykorzystywany juĪ w poprzednich ciągach formatujących, to przy- káad tak zwanego znaku sterującego (ang. escape sequence). Znaki sterujące pozwalają na osadzanie w ciągach znaków, które zapisane inaczej byáyby káopo- tliwe dla kompilatora. Dotyczy to przede wszystkim znaków niedrukowalnych terminali znakowych oraz znaków posiadających specjalne znaczenie dla samego kompilatora (jak ). Kompletną listĊ znaków sterujących zamieĞcimy póĨniej, na razie wystarczy wykaz najwaĪniejszych: a  sygnaá dzwonka, kasowanie poprzedniego znaku (ang. backspace), nowy wiersz, tabulator poziomy. Takie symbole w ciągu formatującym reprezentują czynnoĞci do wykonania w cza- sie wypisywania ciągu na wyjĞciu programu. OtóĪ wypisanie a spowoduje na wiĊkszoĞci maszyn wygenerowanie dĨwiĊku brzĊczyka terminala; wypisanie  znaki sterujące ¥ 7.3 74 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia cofnie kursor o jedną pozycjĊ; wypisanie przesunie kursor do nowego wiersza; wypisanie przesunie kursor do nastĊpnej pozycji tabulatora. Ciąg formatujący moĪe zawieraü dowolną liczbĊ znaków sterujących. Spójrzmy na kolejny przykáad wywoáania printf z ciągiem formatującym zawierającym áącznie szeĞü znaków sterujących: printf( Towar Cena Data jed. zakupu ); Wykonanie tej instrukcji spowoduje wypisanie na wyjĞciu dwóch wierszy: Towar Cena Data jed. zakupu Innym popularnym znakiem sterującym jest , który reprezentuje w ciągu znak podwójnego cudzysáowu . PoniewaĪ sam znak oznacza początek albo koniec literaáu napisowego, nie moĪe w takiej postaci pojawiü siĊ wewnątrz lite- raáu — musi zostaü oznaczony jako znak sterujący znakiem ukoĞnika. Oto przykáad: printf( Ahoj! ); Taka instrukcja spowoduje wypisanie na wyjĞciu komunikatu: Ahoj! Podobna sytuacja dotyczy znaku lewego ukoĞnika. JeĞli zechcemy umieĞciü taki znak w wypisywanym ciągu, nie moĪemy go wstawiü wprost do literaáu napi- sowego, bo kompilator zakáada, Īe znak ukoĞnika jest zapowiedzią znaku steru- jącego. Aby wypisaü znak , trzeba go równieĪ poprzedziü znakiem , a wiĊc wstawiü do ciągu parĊ \: printf( \ ); /* wypisuje na wyjĞciu pojedynczy znak */ 3.2. Funkcja scanf Tak jak funkcja printf sáuĪy do formatowania wyjĞcia programu, tak funkcja scanf obsáuguje formatowane wejĞcie. Ciąg formatujący dla funkcji scanf rów- nieĪ moĪe zawieraü zwyczajne znaki i specyfikatory konwersji. Konwersje obsáu- giwane przez funkcjĊ scanf pokrywają siĊ z grubsza z konwersjami funkcji printf. W wielu przypadkach ciąg formatujący funkcji scanf zawiera wyáącznie specyfikatory konwersji, jak w poniĪszym przykáadzie: int i, j; float x, y; scanf( d d f f , i, j, x, y); ZaáóĪmy, Īe uĪytkownik wprowadza na wejĞcie programu nastĊpujący wiersz: 1 -20 .3 -4.0e3 3.2. Funkcja scanf 75 Funkcja scanf wczyta taki wiersz i rozpocznie stosowanie specyfikatorów kon- wersji i podstawianie uzyskanych wartoĞci pod zmienne przekazane w wywoáaniu: 1 pod i, -20 pod j, 0.3 pod x i -4000.0 pod y. Takie „upakowane” ciągi sterujące są dla funkcji scanf typowe. W przypadku funkcji printf czĊĞciej stosuje siĊ rozmaite „dekoracje” i napisy objaĞniające, otaczające wyprowadzane wartoĞci. Funkcja scanf (tak jak printf zresztą) zastawia na nieĞwiadomych i nie- ostroĪnych uĪytkowników kilka wnyków. Programista stosujący funkcjĊ scanf musi starannie sprawdzaü, czy liczba specyfikatorów konwersji odpowiada liczbie zmiennych przekazanych w wywoáaniu i czy poszczególne konwersje odpowiadają typom przekazanych zmiennych — podobnie jak w przypadku printf, kom- pilator nie ma obowiązku przeprowadzania takiej kontroli i wykrywania ewentu- alnych niezgodnoĞci. Kolejna puáapka czai siĊ w znaku , który zazwyczaj poprze- dza kaĪdą zmienną przekazywaną do scanf. Znak jest zazwyczaj (choü nie zawsze) konieczny i to programista ma obowiązek pamiĊtaü o jego stosowaniu. PominiĊcie symbolu przy zmiennej przekazywanej do funkcji scanf prowadzi do nieprzewidywalnych wyników dziaáania programu. Potencjalnie są to efekty katastrofalne. NajczĊĞciej taki báąd prowadzi do wyáoĪenia siĊ programu. W naj- lepszym przypadku podstawienie wartoĞci pod zmienną bĊdzie nieskuteczne — zmienna zachowa swoją poprzednią wartoĞü (co nie oznacza, Īe bĊdzie miaáa jaką- kolwiek okreĞloną wartoĞü, jeĞli np. nie zostaáa zainicjalizowana!). PominiĊcie znaku jest niestety czĊstym báĊdem. Niektóre kompilatory wykrywają taki báąd i generują komunikat z ostrzeĪeniem w rodzaju „argument nie jest wskaĨnikiem” (o wskaĨnikach powiemy sobie w rozdziale 11.; to wáaĞnie znak tworzy wskaĨ- nik do zmiennej). OstrzeĪenia związane z wywoáaniami funkcji scanf trzeba trak- towaü bardzo powaĪnie. Wywoáania funkcji scanf są efektywnym, ale potencjalnie niebezpiecznym sposobem wczytywania danych do programów. Wielu zawodowych programi- stów C unika funkcji scanf. Wolą oni wczytaü do programu caáoĞü danych wejĞciowych w postaci znakowej i dopiero póĨniej zamieniü ją na oczekiwane wartoĞci liczbowe. My natomiast bĊdziemy korzystaü ze scanf caákiem sporo, zwáaszcza w początkowych rozdziaáach ksiąĪki — jest to zwyczajnie najprostszy sposób wczytywania wartoĞci liczbowych do programu. Trzeba tylko mieü Ğwia- domoĞü, Īe wiele programów zachowa siĊ niepoprawnie, kiedy uĪytkownik wpro- wadzi do nich nieodpowiednie dane wejĞciowe. Wkrótce siĊ przekonamy, Īe moĪna zresztą skutecznie sprawdzaü, czy funkcji scanf udaáo siĊ wczytaü z wejĞcia oczekiwane dane (a jeĞli nie, odpowiednio zareagowaü, zamiast brnąü dalej w pro- gram z niepoprawnymi danymi). Takie sprawdziany są jednak maáo zasadne w zakresie początkowych przykáadów prezentowanych w ksiąĪce — nadmiernie rozbudowaáyby program, który ma przecieĪ przede wszystkim ilustrowaü bieĪące zagadnienie. wykrywanie báĊdów w scanf ¥ 22.3 76 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia Dziaáanie funkcji scanf Funkcja scanf robi w istocie znacznie wiĊcej, niĪ dotychczas powiedziano. Jest to w zasadzie mechanizm dopasowywania wzorców w ciągach znaków, który pró- buje pogrupowaü znaki wejĞciowe i dopasowaü je do specyfikatorów konwersji. Dziaáaniem funkcji scanf sterujemy za pomocą ciągu formatującego. Funkcja scanf analizuje zawartoĞü tego ciągu, od lewej do prawej strony. Dla kaĪdego napotkanego w ciągu specyfikatora konwersji próbuje w ciągu wejĞciowym pro- gramu zlokalizowaü wartoĞü odpowiedniego typu. W czasie tego wyszukiwania automatycznie pomija znaki odstĊpów. Znaleziony podciąg pasujący do specyfi- katora konwersji jest wczytywany aĪ do miejsca, w którym wystąpi znak niepasu- jący do wymagaĔ konwersji. JeĞli udaáo siĊ wczytaü taki podciąg, funkcja scanf dokonuje konwersji i przechodzi do analizy reszty ciągu formatującego. Pierwsze nieudane dopasowanie specyfikatora konwersji do danych wczytywanych z wej- Ğcia koĔczy dziaáanie caáej funkcji, bez rozpatrywania reszty ciągu formatującego (i bez uwzglĊdniania reszty danych wejĞciowych). W toku poszukiwania pierwszego znaku liczby funkcja scanf ignoruje wszystkie znaki odstĊpów (spacje, znaki tabulacji poziomej i pionowej, znaki wysuwu formularza i znaki nowego wiersza). DziĊki temu na wejĞciu dane moĪna podawaü w jednym wierszu albo rozproszyü je pomiĊdzy róĪnymi wierszami. Przy danym wywoáaniu funkcji scanf: scanf( d d f f , i, j, x, y); uĪytkownik moĪe wprowadziü na wejĞcie np. trzy wiersze danych: 1 -20 .3 -4.0e3 dla funkcji scanf wejĞcie jest widoczne jako ciągáy strumieĔ znaków: ··1¤-20···.3¤···-4.0e3¤ (w celu uwidocznienia znaków odstĊpów zastosowaliĞmy znak · dla spacji i znak ¤ dla nowego wiersza). PoniewaĪ funkcja scanf pomija znaki odstĊpów i szuka przede wszystkim początku liczby i podciągu znaków nadających siĊ do konwersji, takie dane wejĞciowe mogą byü za jednym zamachem wczytane przez funkcjĊ scanf. PoniĪszy schemat ilustruje dziaáanie funkcji scanf. Znak p oznacza tu pomijanie bieĪącego znaku wejĞcia, znak w oznacza wczytywanie znaków do bie- Īącej konwersji: ··1¤-20···.3¤···-4.0e3¤ ppwpwwwpppwwppppwwwwww Ostatni znak strumienia wejĞciowego, czyli pierwszy znak za ostatnią skonwerto- waną grupą znaków, jest przez funkcjĊ scanf „podglądany”, ale nie jest wczy- tywany. Zostanie on wczytany i pominiĊty bądĨ skonwertowany przy nastĊpnym wywoáaniu scanf. Wedáug jakich reguá scanf rozpoznaje liczbĊ caákowitą albo zmiennoprze- cinkową w ciągu danych wejĞciowych? OtóĪ kiedy scanf ma wczytaü liczbĊ caákowitą, szuka w ciągu wejĞciowym znaku cyfry, ewentualnie znaku + albo -. 3.2. Funkcja scanf 77 Po znalezieniu takiego znaku wczytuje wszystkie kolejne znaki aĪ do napotkania znaku niebĊdącego cyfrą. Natomiast w przypadku liczby zmiennoprzecinkowej scanf szuka: znaku + albo - (opcjonalnie), a za nim ciągu cyfr (zawierającego ewentualnie znak przecinka dziesiĊtnego), a za nim ciągu wykáadnika (opcjonalnie); ciąg wykáadnika skáada siĊ z litery e (albo E), opcjonalnego znaku (+ albo -) i co najmniej jednej cyfry. W przypadku funkcji scanf konwersje e, f i g moĪna stosowaü zamiennie — wszystkie trzy reprezentują te same reguáy dopasowania wartoĞci zmiennoprze- cinkowej. Kiedy scanf napotyka znak niezgodny z reguáą dopasowania dla bieĪącej kon- wersji, znak ten jest „odkáadany” z powrotem do strumienia wejĞciowego, aby byá dostĊpny przy obsáudze nastĊpnych specyfikatorów konwersji albo dla kolejnych wywoáaĔ scanf wczytujących kolejne wartoĞci. WeĨmy na przykáad nastĊpujące (niewątpliwie patologiczne) rozmieszczenie naszych czterech liczb wejĞciowych: 1-20.3-4.0e3¤ Zastosujemy takie same wywoáanie scanf jak poprzednio: scanf( d d f f , i, j, x, y); Funkcja scanf bĊdzie przetwarzaü taki ciąg wejĞciowy nastĊpująco: Q BieĪąca konwersja: d. Pierwszy niepusty znak wejĞcia to 1. PoniewaĪ liczba caákowita moĪe zaczynaü siĊ od cyfry, znak jest akceptowany jako pierwszy znak podciągu do dopasowania. Funkcja wczytuje nastĊpny znak: -. Taki znak nie moĪe siĊ pojawiü wewnątrz zapisu wartoĞci caákowitej, wiĊc scanf odkáada znak z powrotem do strumienia i podstawia pod pierwszą zmienną (i) wartoĞü 1. Q BieĪąca konwersja: d. Pierwszy niepusty znak wejĞcia to - (dozwolony); kolejne znaki to 2, 0 i . (kropka). Liczba caákowita nie moĪe zawieraü kropki, wiĊc znak jest odkáadany z powrotem do strumienia wejĞciowego, a funkcja podstawia pod kolejną zmienną (j) wartoĞü –20. Q BieĪąca konwersja: f. Pierwszy niepusty znak wejĞcia to . (dozwolony); kolejne znaki to 3 i - (minus). Liczba zmiennoprzecinkowa nie zawiera znaku - po znaku cyfry, wiĊc znak - jest odkáadany z powrotem do strumienia wej- Ğciowego, a funkcja podstawia pod kolejną zmienną (x) wartoĞü 0.3. Q BieĪąca konwersja: f. Pierwszy niepusty znak wejĞcia to - (dozwolony); kolejne znaki to 4, ., 0, e, 3 i ¤ (nowy wiersz). Liczba zmiennoprzecinkowa nie moĪe zawieraü znaku nowego wiersza, wiĊc znak jest odkáadany z powro- tem do strumienia wejĞciowego, a funkcja podstawia pod kolejną zmienną (y) wartoĞü –4.0×103. W tym przykáadzie funkcja scanf mogáa skutecznie dopasowaü wszystkie kolejne specyfikatory konwersji do ciągu wejĞciowego. PoniewaĪ znak nowego wiersza nie zostaá „zuĪyty”, bĊdzie pierwszym znakiem wczytywanym przy nastĊpnym wywoáaniu scanf. 78 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia Zwykáe znaki w ciągu formatującym funkcji scanf ZasadĊ dopasowywania wzorców do podciągów strumienia wejĞciowego moĪna rozszerzyü, zapisując ciąg formatujący zawierający poza specyfikatorami konwer- sji równieĪ zwykáe napisy. W takim przypadku pomiĊdzy specyfikatorami kon- wersji funkcja scanf bĊdzie porównywaáa kolejne znaki wejĞcia ze znakami ciągu formatującego. Porównanie takie odbywa siĊ róĪnie, zaleĪnie od tego, czy ciąg formatujący zawiera znaki odstĊpów: Q Znaki odstĊpów w ciągu formatującym. Kiedy w ciągu formatującym znaj- dują siĊ znaki odstĊpu, funkcja scanf bĊdzie w strumieniu wejĞciowym wczy- tywaáa kolejne znaki tak dáugo, aĪ napotka pierwszy znak niebĊdący znakiem odstĊpu (ten znak zostanie „odáoĪony” z powrotem do strumienia wejĞciowego). Liczba znaków odstĊpu w ciągu formatującym nie musi dokáadnie odpowiadaü liczbie takich znaków w ciągu wejĞciowym. Pojedynczy znak odstĊpu w ciągu formatującym zostanie dopasowany do dowolnie dáugiego podciągu takich znaków w ciągu wejĞciowym (co wiĊcej, obecnoĞü znaku odstĊpu w ciągu formatującym nie wymusza obecnoĞci takiego znaku w ciągu wejĞciowym — znak odstĊpu w ciągu formatującym odpowiada dowolnie dáugiemu podciągowi takich znaków w ciągu wejĞciowym, a wiĊc równieĪ podciągowi zerowemu). Q Pozostaáe znaki. Kiedy w ciągu formatującym znajduje siĊ znak nienaleĪący do specyfikatorów konwersji i niebĊdący znakiem odstĊpu, funkcja scanf porównuje go wprost z nastĊpnym znakiem wejĞcia. JeĞli znaki są zgodne, funkcja przechodzi do przetwarzania nastĊpnego znaku ciągu wejĞciowego. Przy braku zgodnoĞci funkcja odkáada niepasujący znak z powrotem do ciągu wejĞciowego i przerywa dalsze przetwarzanie ciągu formatującego. Dla przykáadu niech funkcja scanf otrzyma ciąg formatujący w postaci d/ d . JeĞli na wejĞciu programu pojawi siĊ ciąg: ·5/·96 funkcja scanf pominie pierwszy znak odstĊpu, szukając liczby caákowitej, nastĊp- nie dopasuje do d podciąg 5, dopasuje bezpoĞrednio znak /, pominie spacjĊ w poszukiwaniu kolejnej liczby caákowitej, a póĨniej dopasuje do d podciąg 96. Ale jeĞli na wejĞciu pojawi siĊ: ·5·/·96 to funkcja scanf pominie pierwszy znak odstĊpu, szukając liczby caákowitej, nastĊpnie dopasuje do d podciąg 5, a póĨniej spróbuje dopasowaü do wejĞcia znak /. PoniewaĪ w bieĪącym miejscu wejĞcia zamiast tego znaku znajduje siĊ inny (tu: znak odstĊpu), funkcja przerwie przetwarzanie wejĞcia, odkáadając spacjĊ z powrotem do ciągu wejĞciowego. Na wejĞciu pozostanie ciąg ·/·96 czekający na ewentualne kolejne wywoáanie scanf. Aby umoĪliwiü dopasowanie wejĞcia ze spacją (spacjami) po pierwszej liczbie caákowitej, ciąg formatujący powinien mieü postaü d / d . 3.2. Funkcja scanf 79 Skutki mylenia printf ze scanf Wywoáania funkcji printf i scanf bywają bardzo podobne, ale w ich dziaáa- niu zachodzą daleko idące róĪnice. Zignorowanie tych róĪnic moĪe byü bardzo nie- bezpieczne dla dziaáania programu. Jedną z czĊstych pomyáek jest umieszczenie przed zmienną w wywoáaniu funkcji printf: printf( d d , i, j); /*** ħLE ***/ Na szczĊĞcie taka omyáka jest stosunkowo prosta do wytropienia — w toku dziaáania programu funkcja printf wyĞwietli „Ğmieci” zamiast oczekiwanych wartoĞci i i j. PoniewaĪ funkcja scanf normalnie pomija znaki odstĊpów przy poszuki- waniu podciągu do dopasowania do wartoĞci liczbowej, rzadko kiedy pojawia siĊ potrzeba umieszczania w ciągu formatującym scanf czegokolwiek poza specy- fikatorami konwersji. Nieuprawnione zaáoĪenie, Īe ciąg formatujący scanf powinien ĞciĞle odpowiadaü analogicznemu ciągowi formatującemu printf — to kolejny czĊsty báąd — moĪe doprowadziü do niepoprawnego dziaáania funkcji scanf. Zobaczmy, co siĊ stanie, jeĞli w programie znajdzie siĊ nastĊpująca in- strukcja: scanf( d, d , i, j); Funkcja scanf bĊdzie najpierw szukaü podciągu wartoĞci typu int i wpisze tĊ wartoĞü pod zmienną i. Potem bĊdzie próbowaáa dopasowaü w ciągu wejĞciowym znak przecinka. JeĞli w ciągu wejĞciowym zamiast przecinka pojawi siĊ spacja, dziaáanie funkcji zostanie przerwane i zmienna j nie otrzyma oczekiwanej wartoĞci. Ciągi formatujące dla funkcji printf czĊsto koĔczą siĊ znakiem sterującym , wymuszającym wstawienie do wyjĞcia nowego wiersza. Taki sam znak na koĔcu ciągu formatującego scanf to zazwyczaj záy pomysá. Dla scanf znak nowego wiersza w ciągu formatującym jest równowaĪny ze znakiem spacji; pomija go, szukając nastĊpnego znaku niebĊdącego znakiem odstĊpu. JeĞli na przykáad ciąg formatujący ma postaü d , scanf pominie ewentualne początkowe znaki odstĊpu, wczyta wartoĞü caákowitą, a nastĊpnie bĊdzie w ciągu wejĞciowym szukaü nastĊpnego znaku innego niĪ odstĊp. W przypadku programu interaktywnego moĪe to doprowadziü do „zawieszenia” programu do czasu, kiedy uĪytkownik wprowa- dzi na wejĞcie znak inny niĪ odstĊp. Dodawanie uáamków Aby zilustrowaü zdolnoĞü funkcji scanf do dopasowywania wzorców w ciągach znaków, weĨmiemy na warsztat problem wczytania uáamka wprowadzanego przez uĪytkownika. Uáamki są zwyczajowo reprezentowane przez zapis licznik/mianownik. Zamiast zmuszaü uĪytkownika do nieintuicyjnego wprowadzania uáamka jako dwóch osobnych liczb caákowitych, dziĊki funkcji scanf pozwolimy mu wpro- wadziü uáamek w klasycznej postaci. Oto program ilustrujący tĊ technikĊ przy dodawaniu dwóch uáamków: PROGRAM 80 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia addfrac.c /* Dodawanie dwóch uáamków zwykáych */ #include stdio.h int main(void) { int num1, denom1, num2, denom2, result_num, result_denom; printf( Podaj pierwszy uïamek: ); scanf( d/ d , num1, denom1); printf( Podaj drugi uïamek: ); scanf( d/ d , num2, denom2); result_num = num1 * denom2 + num2 * denom1; result_denom = denom1 * denom2; printf( Suma uïamków wynosi d/ d , result_num, result_denom); return 0; } Przykáadowa sesja z takim programem wyglądaáa tak: Podaj pierwszy uïamek: 5/6 Podaj drugi uïamek: 3/4 Suma uïamków wynosi 38/24 ZauwaĪmy, Īe program nie przewiduje znormalizowania wynikowego uáamka. Pytania i odpowiedzi *P: Widywaáem specyfikatory w postaci i, przeznaczone do wczytywania i wy- pisywania liczb caákowitych. Czym róĪnią siĊ od d (s. 71)? liczby ósemkowe ¥ 7.1 liczby szesnastkowe ¥ 7.1 P: O: W ciągu formatującym funkcji printf nie ma pomiĊdzy nimi Īadnej róĪnicy. Za to w funkcji scanf d dopasuje wyáącznie liczbĊ caákowitą zapisaną w postaci dziesiĊtnej, natomiast i moĪe dopasowaü takĪe liczby caákowite zapisane w innych systemach liczbowych (przy innych podstawach), na przykáad liczby ósemkowe czy szesnastkowe. OtóĪ jeĞli ciąg wejĞciowy zawiera przedrostek 0 (jak w 056), przy konwersji i taki ciąg zostanie potraktowany jako ósemkowy. Przedrostek 0x albo 0X (jak w 0x56) przy konwersji i spowoduje konwersjĊ liczby jako wartoĞci szesnastkowej. Zastosowanie i zamiast d do wczytywania liczb moĪe daü zaskakujące wyniki, jeĞli uĪytkownik omyákowo wprowadzi 0 przed wáaĞciwą liczbą; z tego powodu zaleca siĊ trzymanie siĊ konwersji d. Skoro printf traktuje znak jako początek specyfikatora konwersji, jak moĪna wypisaü na wyjĞciu programu znak procenta? Funkcja printf wypisze na wyjĞciu znak tam, gdzie w ciągu formatującym pojawi siĊ para przylegających znaków procenta ( ). Na przykáad instrukcja: O: Pytania i odpowiedzi 81 printf( Zysk netto: d , profit); moĪe spowodowaü wypisanie: Zysk netto: 10 P: Znak sterujący ma wymusiü na printf przesuniĊcie kursora do nastĊp- nej pozycji tabulacji. Skąd wiadomo, jaka jest szerokoĞü tabulatora (s. 74)? O: Nie wiadomo. Efekt wypisania na wyjĞciu znaku nie jest ĞciĞle zdefiniowany w standardzie jĊzyka C. Jest on zaleĪny od reakcji systemu operacyjnego na Īąda- nie wypisania znaku tabulacji. Zazwyczaj szerokoĞü tabulatora to osiem znaków, ale C sam w sobie nie daje takiej gwarancji. P: Co zrobi funkcja scanf, jeĞli bĊdzie miaáa wczytaü liczbĊ, a uĪytkownik wprowadzi ciąg nieliczbowy? O: WyjaĞnimy to na przykáadzie: printf( Podaj liczbÚ: ); scanf( d , i); ZaáóĪmy, Īe uĪytkownik wprowadzi poprawną wartoĞü liczbową, za którą umieĞci znaki inne niĪ cyfry: Podaj liczbÚ: 23bla W takim przypadku funkcja scanf wczyta znaki 2 oraz 3 i w zmiennej i umieĞci wartoĞü 23. Reszta znaków (bla) bĊdzie w strumieniu wejĞciowym czekaáa na kolejne wywoáanie scanf (albo innej funkcji obsáugującej wejĞcie). JeĞli natomiast uĪytkownik wprowadzi ciąg niepoprawny od pierwszego znaku: Podaj liczbÚ: bla zmienna i nie otrzyma wartoĞci wczytywanej z wejĞcia programu, a w strumieniu wejĞciowym ciąg bla poczeka na kolejne wywoáania funkcji wejĞcia. Co moĪna zrobiü w takich smutnych przypadkach? PóĨniej dowiesz siĊ, jak sprawdziü skutecznoĞü wywoáania funkcji scanf. JeĞli wywoáanie bĊdzie nie- skuteczne, moĪemy zakoĔczyü program albo spróbowaü naprawiü sytuacjĊ, na przy- káad odrzucając niepoprawne wejĞcie i ponownie prosząc uĪytkownika o wpro- wadzenie danych (sposoby odrzucania danych wejĞciowych bĊdą omawiane w sekcji pytaĔ i odpowiedzi rozdziaáu 22.). wykrywanie báĊdów w scanf ¥ 22.3 P: Nie rozumiem, w jaki sposób funkcja scanf „odkáada” znak z powrotem do ciągu wejĞciowego i potem ponownie wczytuje go z wejĞcia (s. 77)? O: Okazuje siĊ, Īe program nie wczytuje danych wejĞciowych bezpoĞrednio przy ich wprowadzaniu. Ciąg wejĞciowy programu jest przechowywany w ukrytym buforze, do którego odwoáuje siĊ funkcja scanf. W takim ukáadzie funkcja scanf moĪe „odáoĪyü” znak z powrotem do bufora. Buforowanie wejĞcia bĊdzie omawiane w rozdziale 22. Jak zadziaáa funkcja scanf, kiedy uĪytkownik umieĞci pomiĊdzy liczbami znaki przestankowe (np. przecinki)? P: O: Zobaczmy to na prostym przykáadzie. ZaáóĪmy, Īe zamierzamy wczytaü funkcją scanf parĊ liczb: 82 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia printf( Podaj dwie liczby: ); scanf( d d , i, j); JeĞli uĪytkownik wprowadzi: 4,28 funkcja scanf wczyta znak 4 i podstawi wartoĞü 4 do zmiennej i. W poszuki- waniu nastĊpnego podciągu reprezentującego liczbĊ caákowitą znajdzie przecinek. PoniewaĪ przecinek nie moĪe rozpoczynaü zapisu liczby, funkcja przerwie dzia- áanie. Sam przecinek i druga wprowadzona liczba zostaną do dyspozycji nastĊp- nych wywoáaĔ scanf. OczywiĞcie moĪna temu áatwo zaradziü, instruując uĪytkownika co do ocze- kiwanego formatu danych wejĞciowych, np. nakazując mu zawsze oddzielanie liczb przecinkiem: printf( Podaj dwie liczby, oddzielone przecinkiem: ); scanf( d, d , i, j); ûwiczenia Podrozdziaá 3.1 1. Co pojawi siĊ na wyjĞciu po wykonaniu poniĪszych wywoáaĔ printf? (a) printf( 6d, d4 , 86, 1040); (b) printf( 12.5e , 86, 30.253); (c) printf( .4f , 83.162); (d) printf( -6.2g , .0000009979); 2. Napisz wywoáanie funkcji printf wyĞwietlającej wartoĞü zmiennej typu float w nastĊ- pujących formatach: (a) w zapisie wykáadnikowym, wyrównaną do lewej w polu o szerokoĞci 8, z jedną cyfrą (b) w zapisie wykáadnikowym, wyrównaną do prawej w polu o szerokoĞci 10, z szeĞcioma (c) w zapisie dziesiĊtnym z przecinkiem, wyrównaną do lewej w polu o szerokoĞci 8, z trzema po przecinku; cyframi po przecinku; cyframi po przecinku; (d) w zapisie dziesiĊtnym z przecinkiem, wyrównaną do prawej w polu o szerokoĞci 6, bez cyfr po przecinku. Podrozdziaá 3.2 3. Dla kaĪdej z poniĪszych par ciągów formatujących scanf wskaĪ, czy oba ciągi pary są sobie równowaĪne, czy nie. JeĞli nie są, wskaĪ róĪnicĊ w ich dziaáaniu. (a) d (b) d- d- d d - d - d (c) f (d) f, f f f, f d * 4. WeĨmy nastĊpujące wywoáanie funkcji scanf: ûwiczenia z gwiazdką są podchwytliwe — poprawna odpowiedĨ zazwyczaj jest róĪna od odpowiedzi narzucającej siĊ na pierwszy rzut oka. Przeczytaj pytanie uwaĪnie, dokáadnie przeĞledĨ kod, w razie potrzeby powtórz lekturĊ odpowiedniego podrozdziaáu. Powodze- nia! — przyp. autora. Zadania programistyczne 83 scanf( d f d , i, x, j); Jakie bĊdą wartoĞci zmiennych i, x i j po wykonaniu wywoáania (zakáadamy, Īe zmienne i i j są zmiennymi typu int, a x jest zmienną typu float), jeĞli uĪytkownik wprowadzi: 10.3 5 6 * 5. WeĨmy nastĊpujące wywoáanie funkcji scanf: scanf( f d f , x, i, y); Jakie bĊdą wartoĞci zmiennych x, i i y po wykonaniu wywoáania (zakáadamy, Īe zmienne x i y są zmiennymi typu float, a i jest zmienną typu int), jeĞli uĪytkownik wprowadzi: 12.3 45.6 789 6. PokaĪ, jak moĪna przerobiü program addfrac.c z podrozdziaáu 3.2, aby uĪytkownik mógá wprowadzaü uáamki ze spacjami wokóá znaku dzielenia /. Zadania programistyczne 1. Napisz program, który przyjmuje na wejĞcie datĊ w postaci dd/mm/rrrr, a nastĊpnie wypisuje ją w formacie rrrrmmdd: Podaj datÚ (dd/mm/rrrr): 17/2/2011 PodaïeĂ datÚ 20110217 2. Napisz program formatujący informacje o produkcie wprowadzone przez uĪytkownika. Sesja z programem powinna wyglądaü tak: Podaj numer towaru: 583 Podaj cenÚ jednostkowÈ: 13.5 Podaj datÚ zakupu (dd/mm/rrrr): 24/10/2010 Towar Cena Data jed. zakupu 583 $ 13.50 24/10/2010 Numer towaru i data powinny byü wyrównane do lewej. Cena jednostkowa powinna byü wyrównana do prawej. Program powinien dopuszczaü kwoty do 9999,99. PodpowiedĨ: Do wyrównania kolumn zastosuj tabulatory. 3. KsiąĪki są oznaczane miĊdzynarodowym numerem ISBN (International Standard Book Number). Numery ISBN nadawane po 1 stycznia 2007 roku skáadają siĊ z 13 cyfr, podzie- lonych na piĊü grup, np. 978-0-393-97950-3 (starsze numery ISBN miaáy 10 cyfr). Pierwsza grupa (przedrostek GSI) to obecnie albo 978 albo 979. Identyfikator grupy okreĞla jĊzyk kraju wydania (np. w krajach anglojĊzycznych stosuje siĊ kody 0 i 1). Kod wydawcy identyfikuje wydawcĊ (393 to kod wydawnictwa W.W. Norton). Numer publikacji to numer nadawany przez wydawcĊ konkretnej ksiąĪce (tutaj 97950). Numer ISBN koĔczy siĊ sumą kontrolną umoĪliwiającą weryfikacjĊ poprawnoĞci numeru ISBN. Napisz program, który podzieli na grupy numer ISBN wprowadzony przez uĪytkownika: Podaj numer ISBN: 978-0-393-97950-3 Przedrostek GSI: 978 Identyfikator grupy: 0 84 Rozdziaá 3. Formatowanie wejĞcia-wyjĞcia Kod wydawcy: 393 Numer publikacji: 97950 Suma kontrolna: 3 Uwaga: Liczba cyfr w kaĪdej z grup moĪe byü róĪna. Nie moĪna zaáoĪyü, Īe grupy mają akurat takie rozmiary jak w tym przykáadzie. Przetestuj program na innych, prawdziwych numerach ISBN (znajdziesz je na okáadkach ksiąĪek i na stronach z informacjami o wydaniu). 4. Napisz program, który zapyta uĪytkownika o numer telefoniczny w formacie (xx) xxx-xxxx, a potem wyĞwietli ten numer w zapisie 0-xx xxx-xx-xx: Podaj numer telefonu [(xx) xxx-xxxx]: (61) 817-6900 Podany numer: 0-61 817-69-00 5. Napisz program, który bĊdzie monitowaá, aby uĪytkownik wprowadziá liczby od 1 do 16 (w dowolnej kolejnoĞci), potem wyĞwietli te liczby czwórkami (w postaci macierzy 4×4), a nastĊpnie wypisze sumy w wierszach, kolumnach i po przekątnych: Podaj liczby od 1 do 16 (w dowolnej kolejnoĂci): 16 3 2 13 5 10 11 8 9 6 7 12 4 15 14 1 16 3 2 13 5 10 11 8 9 6 7 12 4 15 14 1 Sumy w wierszach: 34 34 34 34 Sumy w kolumnach: 34 34 34 34 Sumy po przekÈtnych: 34 34 JeĞli sumy w wierszach, kolumnach i po przekątnych są identyczne (jak w przykáadzie), to takie liczby stanowią tak zwany magiczny kwadrat. Ten magiczny kwadrat pojawiá siĊ w 1514 roku na rycinie artysty i matematyka Albrechta Dürera (zauwaĪ, Īe Ğrodkowe liczby w ostatnim wierszu skáadają siĊ na datĊ ryciny). 6. Przerób program addfrac.c z podrozdziaáu 3.2 tak, aby uĪytkownik za jednym zamachem wprowadzaá oba uáamki oddzielone znakiem +: Podaj dwa uïamki oddzielone znakiem plusa: 5/6+3/4 Suma uïamków wynosi 38/24 4 WyraĪenia UĪywanie kalkulatorka to jeszcze nie programowanie, a juĪ nie matematyka. Jedną z waĪniejszych cech jĊzyka C jest nacisk, jaki jest w nim káadziony na wyra- Īenia — inaczej „wzory”, które mówią o sposobie obliczania wartoĞci. WyraĪenia są tu waĪniejsze niĪ instrukcje. Najprostsze wyraĪenia to zmienne i staáe programu. Zmienna reprezentuje wartoĞü, która jest obliczana w czasie dziaáania programu poprzez pobranie wartoĞci z pamiĊci skojarzonej ze zmienną. Staáa reprezentuje wartoĞü znaną juĪ w czasie kompilacji. Bardziej rozbudowane wyraĪenia obejmują operandy i operatory (przy czym operatory same w sobie są równieĪ wyraĪeniami). W wyraĪeniu a + (b * c) widzimy zastosowanie operatora + do operandów a oraz (b + c), natomiast obie strony operatora + (oba operandy) są peánopraw- nymi wyraĪeniami. Operatory są podstawowymi narzĊdziami budowania wyraĪeĔ, a jĊzyk C posiada bardzo bogaty zbiór operatorów. Przede wszystkim C obsáuguje podsta- wowe operatory obecne w wiĊkszoĞci innych jĊzyków programowania: Q Operatory arytmetyczne, w tym dodawanie, odejmowanie, mnoĪenie i dzielenie. Q Operatory relacji do obliczania wartoĞci wyraĪeĔ logicznych, takich jak „i jest wiĊksze od 0”. Q Operatory logiczne do budowania warunków logicznych, jak „i jest wiĊksze od 0 i jest mniejsze niĪ 10”. Na tym jednak nie koniec. W jĊzyku C mamy do dyspozycji dziesiątki innych operatorów. Jest ich tak wiele, Īe bĊdziemy zmuszeni do ich stopniowego wpro- wadzania na przestrzeni aĪ dwudziestu rozdziaáów tej ksiąĪki. Opanowanie takiej liczby operatorów wydaje siĊ zadanie
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Język C. Nowoczesne programowanie. Wydanie II
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: