понедельник, 22 октября 2012 г.

Ответы к упражнениям из книги Кернигана и Ричи "Язык программирования С"

В очередной раз начал изучать язык С, по книге Кернигана и Ричи "Язык программирования С". Надеюсь хоть в этот раз добью книжку до конца. Сюда буду выкладывать ответы на упражнения встречающиеся в книге по мере их решения.
Решения делал с учетом пройденного материала и не забегая вперед.
Итак, начнем пожалуй.

Упражнение 1.3. Усовершенствуйте программу преобразования температур таким образом, чтобы над таблицей она печатала заголовок.
Решение:
#include <stdio.h>
/* печать таблицы температур по Фаренгейту и Цельсию для
   fahr = 0, 20, ..., 300; */
main()
{
    float fahr, celsius;
    int lower, upper, step;

    lower = 0;   /* нижняя граница таблицы температур */
    upper = 300; /* верхняя граница */
    step = 20;   /* шаг */

    fahr = lower;

    printf("Fahr\tCels\n------------\n"); /* Заголовок */

    while (fahr <= upper) {
        celsius = (5.0 / 9.0) * (fahr - 32.0);
        printf("%3.0f %8.1f\n", fahr, celsius);
        fahr = fahr + step;
    }
}

Упражнение 1.4. Напишите программу, которая будет печатать таблицу соответствия температур по Цельсию температурам по Фаренгейту.
Решение:
#include <stdio.h>
/* печать таблицы температур по Фаренгейту и Цельсию для
   cels = 0, 10, ..., 100; вариант с плавающей точкой   */
main()
{
    float fahr, celsius;
    int lower, upper, step;

    lower = 0;   /* нижняя граница таблицы температур */
    upper = 100; /* верхняя граница */
    step = 10;   /* шаг */

    celsius = lower;
    while (celsius <= upper) {
        fahr = (9.0 * celsius + 160) / 5.0;
        printf("%3.0f %6.0f\n", fahr, celsius);
        celsius = celsius + step;
    }
}

Упражнение 1.5. Измените программу преобразования температур так, чтобы она печатала таблицу в обратном порядке, т. е. от 300 до 0.
Решение:
#include <stdio.h>
/* печать таблицы температур по Фаренгейту и Цельсию
   в обратном порядке*/
main()
{
    int fahr;
    for (fahr = 300; fahr >= 0; fahr = fahr - 20)
        printf("%3d %6.1f\n", fahr, (5.0 / 9.0) * (fahr - 32));
}

Упражнение 1.6. Убедитесь в том, что выражение getchar() != EOF получает значение 0 или 1.
Решение:
#include <stdio.h>
/* Проверка выражения getchar() != EOF
   Для получения 0, необходимо нажать Ctrl+D в Linux-e
   или Ctrl+Z в Windows*/
main()
{
    int result;

    result = (getchar() != EOF);

    if(result == 0)
        printf("Равно 0\n");
    if(result == 1)
        printf("Равно 1\n");
}

Упражнение 1.7. Напишите программу, печатающую значение EOF.
Решение:
#include <stdio.h>
/* Вывод значения EOF */
main()
{
    printf("%d\n", EOF);
}

Упражнение 1.8. Напишите программу для подсчета пробелов, табуляций и новых строк.
Решение:
#include <stdio.h>
/* подсчет пробелов, табуляций и строк входного потока */
main()
{
    int c, nspace, ntab, nline;

    nspace = ntab = nline = 0;

    while((c = getchar()) != EOF){
        if(c == ' ')
            ++nspace;
        if(c == '\t')
            ++ntab;
        if(c == '\n')
            ++nline;
    }
    printf("Пробелы - %d, табуляции - %d, строки - %d\n", nspace, ntab, nline);
}

Упражнение 1.9. Напишите программу, копирующую символы ввода в выходной поток и заменяющую стоящие подряд пробелы на один пробел.
Решение:
#include <stdio.h>
/* замена стоящих подряд пробелов на один пробел */
main()
{
    int c, pred;

    pred = 0;

    while((c = getchar()) != EOF){
        if(c == ' '){
            if(pred == 0){   /* был ли ранее пробел */
                putchar(c);  /* если нет - печатаем */
                pred = 1;    /* и запоминаем */
            }
        }
        if(c != ' '){
            putchar(c);
            pred = 0;
        }
    }
}

Упражнение 1.10. Напишите программу, копирующую вводимые символы в выходной поток с заменой символа табуляции на \t, символа забоя на \b и каждой обратной наклонной черты на \\. Это сделает видимыми все символы табуляции и забоя.
Решение:
#include <stdio.h>
/* замена специальных символов */
main()
{
    int c, spec;
 
    while((c = getchar()) != EOF){
        spec = 0;
        if(c == '\t'){
            printf("\\t");
            spec = 1;
        }
        if(c == '\\'){
            printf("\\\\");
            spec = 1;
        }
        if(c == '\b'){
            printf("\\b");
            spec = 1;
        }
        if(spec == 0)
            putchar(c);
    }
}

Упражнение 1.12. Напишите программу, которая печатает содержимое своего ввода, помещая по одному слову на каждой строке.
Решение:
#include <stdio.h>

#define IN 1
#define OUT 0

/* печать по одному слову в каждой строке */
main()
{
    int c, state;
 
    state = OUT;
 
    while((c = getchar()) != EOF){
        if(c == ' ' || c == '\n' || c == '\t'){
            if(state == IN){
                putchar('\n');
                state = OUT;
            }
        }
        else{
            state = IN;
            putchar(c);
        }
    }
}

Упражнение 1.13. Напишите программу, печатающую гистограммы длин вводимых слов. Гистограмму легко рисовать горизонтальными полосами. Рисование вертикальными полосами - более трудная задача.
Решение:
#include <stdio.h>

#define IN 1
#define OUT 0

/* гистограмма длин слов (горизонтальная) */
main()
{
    int c, state;
 
    state = OUT;
 
    while((c = getchar()) != EOF){
        if(c == ' ' || c == '\n' || c == '\t'){
            if(state == IN)
                putchar('\n');
            state = OUT;
        }
        else{
            if(state == OUT)
                state = IN;
            putchar('#');
        }
    }
}


#include <stdio.h>

#define IN 1
#define OUT 0
#define MAXWORD 80 /* максимальное количество слов  */
                   /* т. е. длина нашей гистограммы */

/* гистограмма длин слов (вертикальная) */
main(){
    int i, j, c, state;
    int lenword[MAXWORD], nextword, maxword;

    nextword = maxword = 0;
    for(i = 0; i < MAXWORD; i++)
        lenword[i] = 0;
    state = OUT;

    while((c = getchar()) != EOF && nextword < MAXWORD){
        if(c == ' ' || c == '\n' || c == '\t'){
            if(state == IN){
                /* запоминаем самое длинное слово,
                   это будет высота нашей гистограммы */
                if(lenword[nextword] > maxword)
                    maxword = lenword[nextword];
                nextword++;
                state = OUT;
            }
        }
        else{
            if(state == OUT)
                state = IN;
            lenword[nextword]++;
        }
    }
    /* печатаем гистограмму */
    for(i = maxword; i > 0; i--){
        for(j = 0; j < nextword; j++){
            if(lenword[j] >= i)
                putchar('#');
            else
                putchar(' ');
        }
        putchar('\n');
    }
}

Упражнение 1.14. Напишите программу, печатающую гистограммы частот встречаемости вводимых символов.
Решение:
#include <stdio.h>

/* гистограмма частот встречаемости введенных символов
   подсчитываются символы с ASCII-кодами от 0 до 256 */
main(){
    int c, i, j, symbols[256];
    for(i = 0; i < 256; ++i)
        symbols[i] = 0;
 
    while((c = getchar()) != EOF){
        ++symbols[c];
    }
    for(i = 0; i < 256; i++)
        if(symbols[i] > 0){
            if(i >= 32)
                printf("Симв '%c- ", i);
            else
                printf("Код '%2d' - ", i);
            for(j = 0; j < symbols[i]; ++j)
                putchar('#');
            putchar('\n');
        }
}




7 комментариев:

  1. Скажи а скільки часу, десь в тебе на одну програму йшло, десь так з 1.8?

    ОтветитьУдалить
  2. Спасибо, очень познавательно.

    ОтветитьУдалить
  3. Упражнение 1.6. Убедитесь в том, что выражение getchar() != EOF получает значение 0 или 1.

    printf("%d\n",getchar());

    ОтветитьУдалить
  4. 1.13 вертикаль-отличное решение!

    ОтветитьУдалить
  5. Не могу понять где применяется программа, описанная в параграфе 1.5 "Ввод-вывод символов". Вроде бы написано всё складно , понятны назначения функций putchar() и getchar(), но прогоняю программу получаю пустой экран. Если кто знает прошу откликнуться. (моя почта moiseevgrigor@mail.ru)

    ОтветитьУдалить
  6. Situs Judi Slot Online - Filmfile Europe
    Daftar Situs Judi Slot Online · CMD88 토토 마틴 넷마블 · JAVA303 · 세월호 사설토토 유니88 IDN789 · QQDK · DAFTAR ISI · QQEMAS · QQCOM 샤오미 토토 · 해외 스포츠 실시간 중계 벳피스트 JUDI388 보증 업체 · QQEMAS.

    ОтветитьУдалить