1

Потребовалось написать программу, которая считает с текстового файла числовые данные, запишет их в массив, затем проведет некую математическую обработку и запишет результат в текстовый файл. Проблема в том, что при записи в результирующий файл записывается только "0 ," и всё, хотя подсчёт происходит правильно. В чём проблема? Исходный текстовый файл имеет вид:

-0.00276953502907418,-0.0026706230637501,-0.00237388716777787,-0.00227497520245379,-0.00296735895972233,-0.00227497520245379,-0.00257171109842602,-0.00197823930648156,-0.00257171109842602,-0.00217606323712971,-0.00306627092504641,-0.00237388716777787,-0.00217606323712971,-0.00296735895972233,-0.00227497520245379,-0.00237388716777787,-0.00227497520245379,-0.00207715127180563,-0.00257171109842602,-0.00227497520245379,-0.00197823930648156,-0.00217606323712971,-0.00257171109842602,-0.00237388716777787,-0.00257171109842602,-0.00247279913310194,-0.0026706230637501,-0.00237388716777787,-0.00286844699439826,-0.00227497520245379,-0.00257171109842602,-0.00286844699439826,-0.0026706230637501,-0.00217606323712971,-0.00247279913310194,-0.00207715127180563,-0.00276953502907418,-0.00296735895972233,-0.0026706230637501,-0.00257171109842602,-0.00296735895972233,-0.00227497520245379,-0.00237388716777787,-0.00237388716777787,-0.00257171109842602,-0.00227497520245379,-0.00286844699439826,-0.00257171109842602

Сама программа:

# include <iostream>
# include <fstream>
# include <string>
# include <vector>
# include <cstdlib>

int main() {
    const double m = 0.0008;
    double h = 1/200000000.;
    int rpt = 1;
    int count = 0;
    int i, j, k;
    double c;
    std::string filename, outname;
    std::vector<double> signal;

    setlocale(LC_ALL, "rus");

    //Открываем файл
    std::cout << "Введите имя файла" << std::endl;
    std::cin >> filename;
    std::ifstream infile(filename);

    if (!infile.is_open())
        std::cout << "File not found!" << std::endl;
    else {
        std::cout << "File opened!" << std::endl;
        std::string buffer = "";

    //Считываем в массив
        while (!infile.eof()) {

            std::getline(infile, buffer, ',');
            double value = atof(buffer.c_str());
            signal.push_back(value);
            count++;
        }

        double b[count];
        double x[count];
        double t[count];
        double res[count];

    //Математическая обработка 
        for (i = 0; i < count; i++) { 
            b[i] = 0.0;
            x[i] = 0.0;
        }

        for (i = 0; i < rpt; i++) {

            for (j = 0; j < count; j++) {

                double y = 0.0;
                for (i = count; i > 0; i--)
                    x[i] = x[i-1];
                x[1] = signal[j];

                for (k = 0; k < count; k++)
                    y += x[k]*b[k];

                if (y>1.0)
                    y = 1.0;
                else if (y<-1.0)
                    y = -1.0;

                res[j] = signal[j] - y;

                if (res[j]>1.0)
                    res[j] = 1.0;
                else if (res[j]<-1.0)
                    res[j] = -1.0;


                if (j==0)
                    t[j] = 0;
                else 
                    t[j] = t[j-1] +h;

                c = 2*m*res[j];
                for (k = 0; k < count; k++)
                    b[k] += x[k]*c;
            }
        }

    // Запись в файл (Проблема!)
        std::cout << "Введи имя файла для записи" << std::endl;
        std::cin >> outname;
        std::ofstream outfile;
        outfile.open(outname);
        if (outfile.is_open()) {
            for (i = 0; i < count; i++)
                outfile << res[i] << ", ";
        }
        outfile.close();
    }

    infile.close();

    return 0;
}

Компилятор GCC.

eanmos
  • 6,651
  • Как минимум здесь: for (i = count; i > 0; i--) x[i] = x[i-1]; выход за границы массива, наверное подразумевалось for (i = count - 1; i > 0; i--) и последующее x[0] = signal[j];. – Vladimir Gamalyan Jul 22 '19 at 07:50
  • 1
    Безотносительно к ошибке в расчетах... Не пользуйтесь массивами с неизвестным во время компиляции размером - непереносимо. Замените ваши double b[count] на vector<double>b(count). И еще - см. этот вопрос. – Harry Jul 22 '19 at 07:54
  • А ваш подсчет именно и дает - нули. Простите, копаться в нем, не понимая, что именно вы хотите подсчитать - нет ни малейшего желания... – Harry Jul 22 '19 at 07:55
  • 1
    @Harry, вероятно, дело в функции atof, которая из-за русской локали, считает, что плавающая точка отделена запятой, а входные данные в качестве разделителя используют точку. – eanmos Jul 22 '19 at 07:57
  • нули он и должен давать, но его основная цель - фильтрация, нужно настроить коэффициенты массива b так, чтобы при вычитании их из исходного файла получались нули. Проблема в том, что он не выдаёт количество нулей по количеству исходных точек, а только и единственный 0 и запятую после него. При этом считывание массива из исходного файла и расчёт происходят корректно, на выводе в консоль имеем набор чисел значением около -0.00001, но они в файл не записываются – Дмитрий Jul 22 '19 at 08:01
  • @Дмитрий, ваш расчет не может происходить корректно, как минимум из-за выхода за границы массива, на который указал Vladimir Gamalyan в первом комментарии. – eanmos Jul 22 '19 at 08:15
  • да, Вы правы, спасибо, исправил – Дмитрий Jul 22 '19 at 10:01

1 Answers1

1

Ваша проблема заключается не в записи в результирующий файл, а в чтении исходных данных. Функция atof, которую вы используете для преобразования считанной строки в число локально зависима, т. е. в зависимости от локали символ десятичного разделителя разный. Исходя из того, что вы задали русскую локаль функция atof считает, что в качестве десятичного разделителя используется символ запятой ,, а числа в ваших исходных данных используют в качестве разделителя точку ..

Решив проблему можно убрав setlocale(LC_ALL, "rus"); из кода или вручную менять локаль на "C" перед вызовом atof, а после — восстанавливать в исходное значение.


Вообще вам стоит подумать над организацией своей программы. Разбейте ее на три независимых части: а) считывание данных; б) работа над данными; в) запись модифицированных данных в выходной файл:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>

std::vector<double> readDoublesFromFile(std::ifstream &file)
{
    std::vector<double> doubles;

    std::string line;

    while (std::getline(file, line)) {
        std::stringstream linestream(line);
        std::string numberAsString;

        while (std::getline(linestream, numberAsString, ','))
            doubles.push_back(std::stod(numberAsString));
    }

    return doubles;
}

void writeCommaSeparatedDoublesToFile(std::ofstream &file, const std::vector<double> &doubles)
{
    for (const auto d : doubles)
        file << d << ", ";
}

void transformDoubles(std::vector<double> &doubles)
{
    for (auto &d : doubles)
        d += 1.0;
}

int main()
{
    /* Считываем числа из файла в вектор: */
    std::ifstream infile("in.txt");
    std::vector<double> doubles = readDoublesFromFile(infile);

    /* Выполняем какие-то «расчеты» над числами: */
    transformDoubles(doubles);

    /* Записываем преобразованные значения в выходной файл:  */
    std::ofstream outfile("out.txt");
    writeCommaSeparatedDoublesToFile(outfile, doubles);
}
eanmos
  • 6,651