Skip to content

Latest commit

 

History

History
206 lines (168 loc) · 10.3 KB

Обработка-последовательно-вводимых-значений.md

File metadata and controls

206 lines (168 loc) · 10.3 KB

Предположим, мы хотим написать программу, которая анализирует набор значений.

С математической точки зрения, порядок, в котором значения вводятся, может иметь значение, а может не иметь, но с точки зрения вычислительной техники, операции ввода-вывода через одно устройство принципиально последовательны (с некоторыми оговорками).

Важно, что программа должна как-то понимать, когда еще надо считывать значения, а когда все значения уже считаны. Таким образом надо договориться о формате данных, в котором преставлена последовательность значений.

Принципиальных способа организации два:

  • последовательность с известным количеством элементов,
  • последовательность со специальным последним значением.

Обработка последовательности с известным количеством элементов

Известное количество элементов, означает, что до начала считывания значений, программа может узнать, сколько надо считать значений - например, это количество - некоторая константа (может быть, всегда надо обработать именно 10 значений - не меньше и не больше) или это количетсов вычислить на основе предыдущих введённых данных.

Самый простой вариант - это когда програма может явно запросить у пользователя, сколько ему надо проанализировать значений, а потом считывает сами вводимые значения.

Пример: Вычисление произведения.

#include <stdio.h>

int main() {
    printf("How many values do you want to multiply?\nEnter an integer number: ");
    int n;
    scanf("%d", &n);
    float product = 1;
    for (int i = 1; i <= n; ++i) {
        float current;
        printf("Step %d. Enter a value to process: ", i);
        scanf("%f", &current);
        product *= current;
    }
    printf("The product of entered values is: %f\n", product);
    return 0;
}

Пример: Вычисление максимума введенных чисел. Напишем программу, которая запрашивает количество чисел для анализа, а затем печатает значение максимальное из введенных чисел.

#include <stdio.h>

int main() {
    printf("How many numbers do you want to analyze? n = ");
    int n;
    scanf("%d", &n);
    if (n <= 0) {
        printf("There is no need to analyze anything...\n");
    } else {
        printf("Input number %d of %d: ", 1, n);
        double a;
        scanf("%lf", &a);
        double max = a;
        for (int i = 2; i <= n; ++i) {
            printf("Input number %d of %d: ", i, n);
            scanf("%lf", &a);
            if (a > max) {
                max = a;
            }
        }
        printf("Maximum: %g\n", max);
    }
    return 0;
}

Как то же самое можно сделать немного по-другому:

#include <stdio.h>

int main() {
    printf("How many numbers do you want to analyze? n = ");
    int n;
    scanf("%d", &n);
    if (n <= 0) {
        printf("There is no need to analyze anything...\n");
    } else {
        double max;
        for (int i = 1; i <= n; ++i) {
            double a;
            printf("Input number %d of %d: ", i, n);
            scanf("%lf", &a);
            if (i == 1) {
                max = a;
            } else {
                if (a > max) {
                    max = a;
                }
            }
        }
        printf("Maximum: %g\n", max);
    }
    return 0;
}

Обработка последовательности со специальным последним значением

Можно выделить какое-то значение из всех возможных значений вводимых элементов как специальное, которое будет означать конец ввода. Другие варианты такого подхода - когда выделенных значений несколько или есть некоторое условие, выполнение (или, наоборот, невыполнение) которого для очередного значения означает, что оно последнее.

Важно понимать, что выделение таких специальных значений может существенно ограничивать гибкость программы, так как такое значение может встретиться среди вводимых только один раз - в конце ввода.

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

Отдельным вопросом о котором надо договориться - участвуют ли специальные значения в вычислении результатов программы или они играют исключительно служебную роль.

Пример: Вычисление произведения.

Напишем программу, которая будет вычислять произведение целых чисел, которые ввёдет пользователь.

Договоримся с пользователем, что 0 (ноль) будет означать конец ввода.

Смысл выбора нуля в качестве такого значения в данном случае прост: если хотя бы одно из тех значений, которые нам надо перемножить равно 0, результат тривиален - это 0. Так что мы не так много теряем, "запрещая" тем самым, чтобы 0 встречался в качестве "обычных" значений. Естественно, логично договориться, что этот 0 не будет учитываться в вычислении произведения.

#include <stdio.h>

int main() {
    printf("Enter integer numbers to multuply (enter 0 in the end");
    printf("Input number: ");
    int x;
    scanf("%d", &x);
    int p = 1;
    while (x != 0) {
        p *= x;
        printf("Input number: ");
        scanf("%d", &x);
    }
    printf("Product is: %d\n", p);
    return 0;
}

Если не печатать перед каждым значением запрос на его ввод, этот цикл можно записать и в виде цикла for (хотя в данном случае так обычно и не поступают):

#include <stdio.h>

int main() {
    printf("Enter integer numbers to multiply (enter 0 in the end)");
    int p = 1;
    int x;
    for (scanf("%d", &x); x != 0; scanf("%d", &x)) {
        p *= x;
    }
    printf("Product is: %d\n", p);
    return 0;
}

Хотя пользователь и не вводит явно количество чисел, программа вполне в состоянии вычислить его сама (естественно, только к тому моменту, когда вводи чисел окончен):

#include <stdio.h>

int main() {
    printf("Enter integer numbers to multiply (enter 0 in the end)");
    printf("Input number: ");
    int x;
    scanf("%d", &x);
    int p = 1;
    int i;
    for (i = 1; x != 0; ++i) {
        p *= x;
        printf("You entered %d numbers, input number: ", i);
        printf("Input number: ");
        scanf("%d", &x);
    }
    printf("You entered %d numbers to multiply\n", i);
    printf("Product is: %d\n", p);
    return 0;
}

Обратите внимание, что условие окончания цикла for в последнем примере никак не связано с переменной-счётчиком цикла.

Считывание и обработка строки символов

Обычно считывание символов происходит до нажатия клавиши Enter, т.е. до ввода символа перехода на новую строку '\n'. Значит, обработка строки символов - это тоже обработка последовательности со специальным последним значением.

Пример: вводится строка, вычислить количество символов "звёздочка" в этой сроке.

#include <stdio.h>

int main() {
    printf("Enter a line of characters");
    char c;
    scanf("%c", &c);
    int n = 0;
    while (c != '\n') {
        if (c == '*') {
            n++;
        }
        scanf("%c", &c);
    }
    printf("Entered line contains %d characters '*'\n", n);
    return 0;
}

Обратите внимание: в этой задаче совершенно не обязательно сохранять все введённые символы. Если это необходимо, для хранения строки в программе можно использовать массив.