Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#15| Dragon God
Demon's Souls |#14| Flamelurker
Demon's Souls |#13| Storm King
Demon's Souls |#12| Old Monk & Old Hero

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 120.46 Kb

Руководство полного идиота по программированию на C

Предыдущая страница Следующая страница
1 2 3 4 5 6 7  8 9 10 11

                /* Переход на новую строку вынесен
                   из функции в главный цикл */
                putchar('\n');
        }
}
     15.c

/* Задача:
        нарисовать таблицу вида

        кот     кот     кот     кошка   кошка   кот
        кот     кот     кошка   кошка   кот     ...

   Где идет последовательность
        кот, кот, кот, кошка, кошка...
   повторяющаяся много раз и располагаемая по 6 зверей в строку.
*/

#include       /* магическая строка */

/* Объявление глобальных переменных.
   В данном случае - констант.
 */

int TOMCATS     = 3;            /* три кота  */
int CATS        = 2;            /* две кошки */
int ANIMALS_PER_LINE    = 6;    /* шесть зверей в каждой строке */
int LINES       = 25;           /* число выводимых строк */

/* и нам понадобится еще одна переменная - общее число зверей.
   Ее мы вычислим через уже заданные, поэтому тут мы ее объявим...
   но вычислить что-либо можно только внутри функции.
   В нашем случае - в функции main().
*/
int ANIMALS;                    /* общее число зверей */

int nth_in_line = 0;            /* номер зверя в текущей строке */
/* Эта переменная не может быть локальной в функции, так как
 * тогда она уничтожится при выходе из функции. Нам же необходимо,
 * чтобы ее значение сохранялось. Поэтому переменная - глобальная.
 */

/* Функция, которая считает число зверей в одной строке
   и либо переводит строку, либо переводит печать в
   следующую колонку (табуляцией).
*/
void checkIfWeHaveToBreakLine(){
        nth_in_line++;  /* текущий номер зверя в строке (с единицы) */

        if(nth_in_line == ANIMALS_PER_LINE){
        /* Если строка заполнена зверьми... */
                putchar('\n');     /* новая строка */
                nth_in_line = 0;   /* в новой строке нет зверей */
        } else {
                putchar('\t');     /* в следующую колонку */
        }
}

void main(){
        int nanimal;    /* номер зверя */
        int i;          /* счетчик     */

        ANIMALS = ANIMALS_PER_LINE * LINES;
        nanimal = 0;

        while(nanimal < ANIMALS){

                for(i=0; i < TOMCATS; i++){
                        /* Оператор printf() выводит СТРОКУ СИМВОЛОВ.
                           СТРОКА заключается в двойные кавычки
                           (не путать с одиночными для putchar().
                         */
                        printf("кот");
                        nanimal++;      /* посчитать еще одного зверя */

                        /* и проверить - не надо ли перейти на новую строку ? */
                        checkIfWeHaveToBreakLine();
                }
                for(i=0; i < CATS; i++){
                        printf("кошка");
                        nanimal++;      /* посчитать еще одного зверя */

                        /* и проверить - не надо ли перейти на новую строку ? */
                        checkIfWeHaveToBreakLine();
                }
        }
        /* putchar('\n'); */
}
     16.c

/*
        Та же задача, но еще надо печатать номер каждого зверя.
        Ограничимся пятью строками.
*/

#include       /* магическая строка */

int TOMCATS     = 3;            /* три кота  */
int CATS        = 2;            /* две кошки */
int ANIMALS_PER_LINE    = 6;    /* шесть зверей в каждой строке */
int LINES       = 5;            /* число выводимых строк */
int ANIMALS;                    /* общее число зверей */

int nth_in_line = 0;            /* номер зверя в текущей строке */

void checkIfWeHaveToBreakLine(){
        nth_in_line++;

        if(nth_in_line == ANIMALS_PER_LINE){
                putchar('\n');
                nth_in_line = 0;
        } else
                printf("\t\t");         /* @ */

        /* Одинокий оператор может обойтись без {...} вокруг него */
}

void main(){
        int nanimal;
        int i;

        ANIMALS = ANIMALS_PER_LINE * LINES;
        nanimal = 0;

        while(nanimal < ANIMALS){

                for(i=0; i < TOMCATS; i++){
                /* Формат %d выводит значение переменной типа int
                   в виде текстовой строки.
                   Сама переменная должна быть в списке после формата
                   (список - это перечисление переменных через запятую).
                   Переменных ИЛИ выражений (формул).

                   Давайте выводить по ДВЕ табуляции --
                   это место отмечено в функции checkIfWeHaveToBreakLine()
                   как @.

                   Еще раз внимание - один символ мы выводим как
                        putchar('a');
                   Несколько символов - как
                        printf("abcdef");

                   Одиночные кавычки - для одной буквы.
                   Двойные кавычки   - для нескольких.
                */

                        printf("кот%d", nanimal);
                        nanimal++;

                        checkIfWeHaveToBreakLine();
                }
                for(i=0; i < CATS; i++){
                        printf("кошка%d", nanimal);
                        nanimal++;

                        checkIfWeHaveToBreakLine();
                }
        }
}
     17.c

/* Задача: напечатать корни из чисел от 1 до 100.

   Новая информация:
        Нам понадобится новый тип данных - ДЕЙСТВИТЕЛЬНЫЕ ЧИСЛА.
        Это числа, имеющие дробную часть (после точки).
        Как мы уже знаем, целые - это   int.
                          буква - это   char.
                          действительное число - это double.
        (есть еще слово float, но им пользоваться не рекомендуется).

   Для вычисления корня используется итерационный алгоритм Герона.

                q = корень из x;

                q[0]   := x;
                q[n+1] := 1/2 * ( q[n] + x/q[n] );

   Главное тут не впасть в ошибку, не клюнуть на q[n] и не
   завести массив. Нам не нужны результаты каждой итерации,
   нам нужен только конечный ответ. Поэтому нам будет вполне
   достаточно ОДНОЙ, но изменяющейся в цикле, ячейки q.
*/

#include

/* Еще одно новое ключевое слово - const. Обозначает константы.
   В отличие от переменных, такие имена нельзя изменять.
   То есть, если где-то потом попробовать написать epsilon = ... ;
   то это будет ошибкой.
 */
const double epsilon = 0.0000001;       /* точность вычислений */

/* Функция вычисления модуля числа */
double doubleabs(double x){
        if(x < 0) return -x;
        else      return x;
}

/* Функция вычисления квадратного корня */
double sqrt(double x){

        double sq = x;

        /* Такая конструкция есть просто склейка двух строк:
                double sq;
                sq = x;
           Называется это "объявление переменной с инициализацией".
         */

        while(doubleabs(sq*sq - x) >= epsilon){
                sq = 0.5 * (sq + x/sq);
        }
        return sq;
}

void main() {
        int n;

        for(n=1; n <= 100; n++)
                printf("sqrt(%d)=%lf\n",
                             n,  sqrt((double) n)
                      );

}

/*
   Здесь в операторе printf() мы печатаем ДВА выражения.
        ФОРМАТ          ЗНАЧЕНИЕ
        ------          --------
        %d      --      n
        %lf     --      sqrt((double) n)

        По формату %d печатаются значения типа int.
        По формату %c печатаются значения типа char.
        По формату %lf (или %g) печатаются значения типа double.

   Что значит "напечатать значение выражения sqrt(xxx)" ?
   Это значит:
        - вызвать функцию sqrt() с аргументом, равным xxx;
        - вычислить ее;
        - возвращенное ею значение напечатать по формату %lf,
          то есть как действительное число.

   Заметьте, что тут возвращаемое значение НЕ присваивается
   никакой переменной, мы не собираемся его хранить.

   Точно так же, как в операторе x = 12 + 34;
   12 и 34 не хранятся ни в каких переменных,
   а оператор

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

   печатает ЧИСЛО 12, а не переменную.

   Точно так же, как можно писать

        double z;

        z = sqrt(12) + sqrt(23);

   где значение, вычисленное каждой функцией, НЕ хранится
   в своей собственной переменной (такая переменная на самом
   деле существует в компьютере, но программисту она не
   нужна и недоступна).
   Или

        z = sqrt( sqrt(81));

        (корень из корня из 81 --> даст 3)

   Далее, что означает конструкция (double) n   ?
   Функция sqrt() требует аргумента типа double.
   Мы же предлагаем ей целый аргумент

        int n;

   Целые и действительные числа представлены в памяти
   машины ПО-РАЗНОМУ,
   поэтому числа

        12   и   12.0  хранятся в памяти ПО-РАЗНОМУ.

   Машина умеет преобразовывать целые числа в действительные
   и наоборот, надо только сказать ей об этом.
   Оператор (double) x
   называется "приведение типа к double".

   Заметим, что часто преобразование типа
   выполняется автоматически.

   Так, например, при сложении int и double
   int автоматически приводится к double, и результат
   имеет тип double.

        int    var1;
        double var2, var3;

        var1 = 2;
        var2 = 2.0;
        var3 = var1 + var2;

   что означает на самом деле

        var3 = (double) var1 + var2;

   var3 станет равно 4.0

   Более того, к примеру тип char - это тоже ЦЕЛЫЕ ЧИСЛА из интервала
   0...255. Каждая буква имеет код от 0 до 255.

*/
      * 18_POINTERS.txt *

УКАЗАТЕЛИ
=========
void f(int x){
        x = 7;
}

main(){
        int y = 17;
        f(y);
        printf("y=%d\n", y);       /* печатает: y=17 */
}

В аргументе x передаЛтся КОПИЯ значения y,
поэтому x=7; не изменяет значения у.
Как все же сделать, чтобы вызываемая функция
могла изменять значение переменной?

Отбросим два способа:

        - объявление y как глобальной
          (много глобальных переменных - плохой стиль),

        - y=f(y);
          (а что если надо изменить МНОГО переменных?
          return, к несчастью, может вернуть лишь одно значение).

Используется новая для нас конструкция: УКАЗАТЕЛЬ.
---------------------------------------------------------------------------

Пример (@)

void f(int *ptr){       /* #2 */
        *ptr = 7;       /* #3 */
}

main (){
        int y=17;

        f(&y);          /* #1 */
        printf("y=%d\n", y);       /* печатает: y=7 */
}

Ну как, нашли три отличия от исходного текста?
---------------------------------------------------------------------------

Мы вводим две новые конструкции:

        &y              "указатель на переменную y" или
                        "адрес переменной y"

        *ptr            означает "разыменование указателя ptr"
                        (подробнее - позже)

        int *ptr;       означает объявление переменной ptr,
                        которая может содержать в себе
                        указатель на переменную,
                        хранящую int-число.

Для начала определим, что такое указатель.

        int var1, var2, z;      /* целочисленные переменные */
        int *pointer;           /* указатель на целочисленную переменную */

        var1    = 12;
        var2    = 43;
        pointer = &var1;

Мы будем изображать указатель в виде СТРЕЛКИ;
это хороший прием и при практическом программировании.
        ________
       /pointer/
     _/_______/_
     | значение|        Переменная, хранящая указатель
     |   есть  |        (адрес другой переменной)
     |         |
     |  &var1  |
     |         |
     |_______|_|
             |
             |&var1     - сам указатель на var1 -
             |            "стрелка, указывающая на переменную var1".
             V            Она обозначается &var1
        ________
       / var1  /
     _/_______/_
     | значение|
Предыдущая страница Следующая страница
1 2 3 4 5 6 7  8 9 10 11
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (6)

Реклама