Задаци: Учитавање серија бројева

Алгоритми и програми у програмском језику C: Учитавање серија бројева.

Збир n бројева

Прочитај текст задатка.

Пошто је познат укупан број \(n\) бројева које треба учитати, централно место у програму биће петља чије тело (у којем се учитава и обрађује следећи број) треба да се изврши тачно \(n\) пута. Пошто програмски језици обично немају наредбу облика ponovi n puta, извршавање наредби \(n\) пута најчешће се остварује петљом облика for (int i = 0; i < n; i++).

За одређивање збира учитаних бројева користимо променљиву zbir у којој редом акумулирамо збир тренутно прочитаних бројева са стандардног улаза. Вредност променљиве zbir иницијализујемо на 0. Након тога, кроз петљу пролазимо \(n\) пута, а у сваком проласку учитавамо број са стандардног улаза и сваки прочитани број додајемо на збир. По завршетку петље, вредност збира приказујемо на стандардном излазу. На пример, ако се учитавају редом бројеви \(1\), \(2\), \(3\) и \(4\), променљива zbir ће редом имати вредности \(0\), \(1\), \(3\), \(6\) и \(10\). Нагласимо и да није било потребе истовремено памтити све бројеве да би се одредио њихов збир.

Збир серије бројева представља једну од основних њених статистика. У каснијим задацима показаћемо како можемо израчунавати и друге важне статистике (број елемената, производ, просек, минимум, максимум итд.).

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n, broj, zbir = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &broj);
        zbir += broj;
    }
    printf("%d", zbir);
    return 0;
}

Читање до нуле

Прочитај текст задатка.

Задатак ћемо решити помоћу разних врста петљи. У свим случајевима услов за излазак из петље је када је учитани број једнак 0.

У решењу помоћу петље while први број учитавамо пре петље, а у телу петље прво увећавамо бројач за 1 а затим учитавамо следећи број. На овај начин 0 као последњи учитани број неће довести до промене бројача.

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int i = 0, n;
    scanf("%d", &n);
    while (n != 0)
    {
        i++;
        scanf("%d", &n);
    }
    printf("%d", i);
    return 0;
}

Ако користимо петљу do-while сва учитавања ћемо вршити у телу петље и при томе увећавати бројач за 1. На овај начин ћемо избројати све бројеве укључујући и 0, па се након изласка из петље вредност бројача умањује за 1.

Предложено решење задатка (2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int i = 0, n;
    do
    {
        scanf("%d", &n);
        i++;
    } while (n != 0);
    i--;
    printf("%d", i);
    return 0;
}

Још једна могућност је да се испитивање услова прекида петље врши унутар њеног тела, непосредно након учитавања броја. То се може остварити тиме што се креира бесконачна петља облика while (1), чији је услов стално испуњен, а унутар чијег тела се налази наредба if (n == 0) break;.

Предложено решење задатка (3)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int i = 0, n;
    while (1)
    {
        scanf("%d", &n);
        if (n == 0)
            break;
        i++;
    }
    printf("%d", i);
    return 0;
}

Читање до краја улаза

Прочитај текст задатка.

И у овом задатку врши се пребројавање серије елемената. Бројач се иницијализује на нулу и увећава се за сваки учитани број. Кључно питање је како организовати петљу у којој се учитавају бројеви све док се не достигне крај улаза.

У програмском језику C, ако је читање било успешно, функција scanf() враћа број успешно попуњених ставки листе аргумената функције. Ако се деси грешка приликом читања или крај датотеке (енгл. end-of-file), функција scanf() враћа EOF (притисaк тастера CTRL+Z на Windows оперативним системима, односно CTRL+D на Linux оперативним системима). Тако се читање до краја улаза може постићи петљом облика while (scanf("%d", &vrednost) != EOF).

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int i = 0, n;
    while (scanf("%d", &n) != EOF)
        i++;
    printf("%d", i);
    return 0;
}

Читање до -1 или до n-тог броја

Прочитај текст задатка.

Задатак захтева израчунавање збира квадрата учитаних елемената. То се ради веома слично израчунавању збира елемената, једино што се на збир уместо сваког учитаног броја \(x\) додаје његов квадрат. Основна тежина овог задатка не лежи у израчунавању збира квадрата, већ у организацији уноса података тако да се бројеви учитавају све док се не учита број \(-1\) или док се не учита \(n\) бројева.

Један начин да се то уради је да се организује петља у којој се учитава \(n\) бројева, да се у телу те петље учитава број, да се затим проверава да ли је учитан број \(-1\) и ако јесте да се прекине петља (наредбом break), а ако није, да се збир увећа за квадрат учитаног броја. Напоменимо да се увећавање не мора вршити у грани else, већ може и након наредбе гранања - ако је услов да је учитан број \(-1\) испуњен, извршиће се наредба break, петља ће се прекинути и неће се ни стићи до наредбе иза наредбе гранања.

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n, x, zbir = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &x);
        if (x == -1)
            break;
        zbir += x * x;
    }
    printf("%d", zbir);
    return 0;
}

Један начин је да услов изласка из петље обухвати оба услова (да је број \(x\) различит од \(-1\) и да је тренутни број учитаних елемената мањи од \(n\)). Пошто је због случаја \(n=0\) услов потребно проверавати пре читања и једног броја, морамо користити петљу са провером услова на почетку (петљу for или петљу while). Да би услов да је \(x\) различит од \(-1\) био испуњен при првом уласку у петљу, променљиву \(x\) пре петље морамо иницијализовати на вредност различиту од \(-1\) (иницијализоваћемо је, на пример, на вредност \(0\)). Након учитавања броја, пре додавања његовог квадрата поново морамо проверити да ли је учитани број различит од -1.

Предложено решење задатка (2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n, i = 0, x = 0, zbir = 0;
    scanf("%d", &n);
    while (i < n && x != -1)
    {
        scanf("%d", &x);
        i++;
        if (x != -1)
            zbir += x * x;
    }
    printf("%d", zbir);
    return 0;
}

Модификација овог решења уместо наредбе break може да користи променљиву kraj којом се одређује да ли је учитана вредност \(-1\). Њену вредност иницијализујемо на 0 као и да је учитано мање од \(n\) елемената, док се у телу петље, након учитавања броја проверава да ли је он \(-1\) и ако јесте, вредност kraj се поставља на 1, а у супротном се збир увећава за квадрат учитаног броја.

Предложено решење задатка (3)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n, x, zbir = 0, kraj = 0;
    scanf("%d", &n);
    for (int i = 0; !kraj && i < n; i++)
    {
        scanf("%d", &x);
        if (x == -1)
            kraj = 1;
        else
            zbir += x * x;
    }
    printf("%d", zbir);
    return 0;
}