Посчитать значение функции в точке с помощью формулы Тейлора

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

Вот код:

#include "stdio.h"
#include "locale.h"
#include "stdlib.h"
#include "math.h"

typedef double(*function1)(double);
typedef double(*function2)(double);

int fact(int n)
{
    int i, t = 1;
    for (i = 1; i <= n; i++)
        t = t * i;
    return t;
}

double Ch1(double x)
{
    return 1;
}

double Ch2(double x, int i)
{
    return x * x / (double)(2 * i * (2 * i - 1));
}

double ln1(double x)
{
    return x;
}

double ln2(double x, int i)
{
    return((-1) * x * (i - 1) / (i));
}

double cos1(double x)
{
    return 1;
}

double cos2(double x, int i)
{
    return ((pow(-1, i) * pow(x, 2 * i)) / fact(2 * i));
}

double func(function1 fun1, function2 fun2, double x, int num, double rf, double* diff, int* k, double eps)
{
    double f1, f2, sum;
    *k = 1;
    f1 = fun1(x);
    sum = f1;
    *diff = fabs(sum - rf);
    while ((*k < num) && (*diff > eps))
    {
        f2 = f1 * fun2(x, *k);
        sum += f2;
        f1 = f2;
        (*k)++;
        *diff = fabs(sum - rf);
    }
    return sum;
}

void print(double* x, double* n, double* eps)
{
    printf("Введите х \n");
    scanf_s("%lf", &*x);
    printf("Введите число элементов ряда \n");
    scanf_s("%d", &*n);
    printf("Введите точность вычислений\n");
    scanf_s("%lf", &*eps);
}
void menu()
{
    printf("Расчёт значений функций в заданной точке с помощью разложения в ряд Тейлора\n");
    printf("MENU\n");
    printf("1.cos(x)\n");
    printf("2.ch(x)\n");
    printf("3.ln(1+x)\n");
    printf("4.Выход\n");
}

void main()
{
    setlocale(LC_ALL, "Russian");
    double rf; // эталонное значение
    double f; // вычислительная оценка
    double x; // аргумент функции
    double eps; // точность 
    int k; // кол-во слагаемых
    double diff; // разность
    int n;
    int t = 4;
    while (t != 0)
    {
        menu();
        scanf_s("%d", &t);
        k = 0;
        switch (t)
        {
            case 1:
            {
                printf("cos(x)\n");
                print(&x, &n, &eps);
                rf = cos(x);
                f = func(cos1, cos2, x, n, rf, &diff, &k, eps);
                printf("эталонное значение: %.15f \n", rf);
                printf("вычислительная оценка: %.15f \n", f);
                printf("разница между оценкой и эталонным значением: %.15f \n", diff);
                printf("количество слагаемых: %d \n", k);
                break;
            
            }
            case 2:
            {
                printf("ch(x)\n");
                print(&x, &n, &eps);
                rf = cosh(x);
                f = func(Ch1, Ch2, x, n-1, rf, &diff, &k, eps);
                printf("Эталонное значение: %.15f\n", rf);
                printf("Вычислительная оценка: %.15f\n", f);
                printf("Разность между эталонным значением и оценкой: %.15f\n", diff);
                printf("Количество слагаемых: %d\n", k);
                break;
            }
            case 3:
            {
                printf("ln(1+x)\n");
                print(&x, &n, &eps);
                rf = log(1 + x);
                f = func(ln1, ln2, x, n-1, rf, &diff, &k, eps);
                printf("Эталонное значение: %.15f\n", rf);
                printf("Вычислительная оценка: %.15f\n", f);
                printf("Разность между эталонным значением и оценкой: %.15f\n", diff);
                printf("Количество слагаемых: %d\n", k);
                break;
            }
        }
    }

}

Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Предположу что вы вводите значение в виде 1.1. scanf_s читает его до точки и останавливается, так как точка не разделитель десятичной части в этой локали. Все остальные вызовы scanf_s тоже спотыкаются об эту точку и больше ничего не читают.

Поправить так:

  1. Как минимум проверять что вернул scanf_s и обрабатывать ошибки.

  2. Дублировать введённое значение на экране для контроля.

  3. А самое лучшее поменять ввод: читать целиком строку, затем преобразовывать её strtod в число и тоже проверять что преобразована строка целиком.

Вот код. Принимаются предложения по упрощению. Формат ввода: в строке только число и пробелы.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

double input_double() {
    const int size = 100;
    char line[size];

    char *read = fgets(line, size, stdin);
    if (read == 0) {
        fprintf(stderr, "Input error: something wrong\n");
        exit(1);
    }

    size_t len = strlen(line);
    if (len == 0) {
        fprintf(stderr, "Input error: empty line\n");
        exit(1);
    }

    if (line[len - 1] != '\n') {
        fprintf(stderr, "Input error: incomplete or too long line\n");
        exit(1);
    }

    // find last nonspace char
    int i;
    for (i = len - 1; i >= 0; --i) {
        if (!isspace(line[i])) {
            break;
        }
    }

    // all chars are space chars
    if (i == -1) {
        fprintf(stderr, "Input error: empty line\n");
        exit(1);
    }

    // trim the line after last nonspace char
    line[i + 1] = '\0';

    char *end;
    double value = strtod(line, &end);

    // strtod should consume all characters from the trimmed line
    if (*end != '\0') {
        fprintf(stderr, "Input error: invalid format\n");
        exit(1);
    }

    return value;
}

int main() {
    for (; ; ) {
        printf("%lf\n", input_double());
    }
}
→ Ссылка