3 STEROWANIE --------•
Przecinki oddzielające argumenty funkcji, zmienne w deklaracjach ilp. nie są operatoJ rami i nie gwarantuję obliczeń od lewej strony do prawej. ;
Przecinek jako operator powinien być używany oszczędnie. Najbardziej właściwymi zastosowaniem są konstrukcje, w których elementy są ściśle ze sobą powiązane, jak w naszej pętli for w funkcji reverse, a także makra, w których wielokrokowe oblicze-1 nie musi być pojedynczym wyrażeniem. Wyrażenie przecinkowe byłoby również od-powiędnie do odwracania tekstu w funkcji reverse, gdyż zamianę znaków można potraktować jak pojedynczą operację: I
for (i = 0, j = strlen(s)-1; i < j; i++, j—) I
c = s[i], s[i] = s[j], s[j] = c;
Ćwiczenie 3.3. Napisz funkcję expand(s1 ,s2), która przepisując tekst z argumentu s1 do s2, rozwija skrócone zapisy typu a-z do równoważnych im pełnych ciągów abc...xyz. Uwzględnij wielkie i małe litery alfabetu oraz cyfry. Bądź również przygotowany na obsłużenie zapisów w rodzaju a-b-c oraz a-zO-9. a także -a-z. Przyjmij, że początkowe i końcowe znaki są traktowane literalnie.
Pętla do-while
Jak już pisaliśmy w rozdz. 1, warunek zatrzymania w pętlach while i for jest spraw dzany na początku pętli. W trzeciej pętli języka C, do-while, jest przeciwnie: warunek zatrzymania sprawdza się na końcu, po każdym obrocie pętli. Pętlę tę zatem zawsze wykonuje się co najmniej raz. r*
Składnia pętli do jest następująca: do
instrukcja \ I
while (wyrażenie)]
Najpierw wykonuje się instrukcję, a następnie oblicza wyrażenie. Jeżeli jest prawd* we, to ponownie wykonuje się instrukcję i tak dalej. Pętla zostanie zatrzymań* wtedy, kiedy wyrażenie stanie się fałszywe. Z wyjątkiem interpretacji warunku pęt; do-while jest równoważna instrukcji repeat-until w Pascalu.
Doświadczenie mówi, że pętla do-while jest stosowana o wiele rzadziej niż wh'1’ i for. Niemniej jednak czasami bywa wartościowa, jak w następującej funkcji ^ która zamienia liczbę na ciąg znaków (przeciwnie do funkcji atoi). Zadanie jest od^ binę bardziej skomplikowane, niż się wydaje na pierwszy rzut oka, ponieważ lat"
3.6 PĘTLA DO-WHILE ____I powered by
metody generowania cyfr tworzą liczbę w odwrotnej kolejności. My w rttjj.ł}mi*
todę generowania ciągu cyfr od końca, a następnie odwrócenia go.
/* itoa: zamień liczbę n na znaki w tablicy s */ void itoa(int n, char s[J)
{
int i, sign;
if ((sign = n) < 0) /* zanotuj znak liczby */ n = -n; /* n będzie dodatnie */
i = 0;
do { /* generuj cyfry w odwrotnym porządku */
sfi-H-j = n % 10 + ’0’; /* weź następną cyfrę */
} while ((n /= 10) > 0); /* usuń ją */
if (sign < 0) s[h-f] = s|i] = ’\0’;
reverse(s); /* odwróć kolejność cyfr */
Pętla do-while jest tu konieczna, a przynajmniej wygodna, ponieważ co najmniej jeden znak należy wstawić do tablicy s nawet wtedy, kiedy wartością n jest zero. Użyliśmy także nawiasów klamrowych otaczających jedyną instrukcję tworzącą treść pętli do-while. Choć są niepotrzebne, to nieuważny czytelnik na pewno nie pomyli części while z poczQtkiem pętli while.
Ćwiczenie 3.4. W notacji uzupełnieniowej do 2 nasza wersja funkcji itoa nie obsłuży największej liczby ujemnej, gdy wartość n jest równa -(2rozmuir-5łtJHa~l). Wyjaśnij, dlaczego. Zmień tę funkcję tak, aby wypisywała poprawną wartość liczby niezależnie od maszyny, na której będzie uruchamiana.
Ćwiczenie 3.5. Napisz funkcję itob(n,s,b) zamieniającą wartość całkowitą n na znakową reprezentację liczby w systemie o podstawie b i zapisującą wynik w s.
W szczególności itob(n,s,16) przekształca n na postać szesnastkową, którą umieszcza w s.
Ćwiczenie 3.6. Napisz inną wersję funkcji itoa tak, aby akceptowała nie dwa, a trzy argumenty. Niech trzeci argument określa minimalny rozmiar pola; jeśli przekształcona liczba będzie za krótka, to należy ją uzupełnić z lewej strony znakami odstępu.
95