lee.lion Ответов: 1

Как я могу наложить цикл на часть моего кода?


У меня есть такой вклад :
STEP
10
NUMBER line
2
cc
aa
ab
ac
ad
1 1 81 91 101
2 1 82 92 102
STEP
20
NUMBER line
2
cc
aa
ab
ac
ad
1 1 51 61 71
2 1 52 62 72
STEP
30
NUMBER line
2
cc
aa
ab
ac
ad
1 1 51 61 71
2 1 52 62 72

и у меня есть такой фрагмент кода :
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
#include <vector>
using Matrix = std::vector<std::vector<float>>;

void addRow(Matrix& M, const int rowNum, const int id, const float type, const float x, const float y,const float z) {
    M[rowNum][0] = id;
    M[rowNum][1] = type;
    M[rowNum][2] = x;
    M[rowNum][3] = y;
    M[rowNum][4] = z;
}

int main() {
    string line;
    float x0, y0, z0, x1, y1, z1, type;
    int NUMBER_line=0, id=0,NUMBER_line1=0;

    ifstream myfile("1.txt");
    string namefile;
    if (myfile.is_open()) {
        for (int lineno = 0; getline(myfile, line) && lineno < 7; lineno++) {
            if (lineno == 2)  myfile >> NUMBER_line;
        }
        cout << " NUMBER_line: " << NUMBER_line << endl;

        Matrix Input0(NUMBER_line, std::vector<float>(5));
        for (float linenoq = 0; getline(myfile, line) && linenoq < NUMBER_line; linenoq++) {
            myfile >> id >> type >> x0 >> y0 >> z0;
            addRow(Input0, linenoq, id, type, x0, y0, z0);
        }

        for (int lineno = 0; getline(myfile, line) && lineno < 7; lineno++) {
			if (lineno == 2)  myfile >> NUMBER_line1;
        }

        Matrix Input1(NUMBER_line1, std::vector<float>(5));
        for (int linenoq = 0; getline(myfile, line) && linenoq < NUMBER_line1; linenoq++) {
            myfile >> id >> type >> x1 >> y1 >> z1;
            addRow(Input1, linenoq, id, type, x1, y1, z1);
        }

        Matrix Output(NUMBER_line, std::vector<float>(5));
        for (size_t row = 0; row < Output.size(); ++row) {
            for (size_t col = 0; col < Output[0].size(); ++col) {
                if (col < 2) {
                    Output[row][col] = Input0[row][col];
                }
                else {
                    Output[row][col] = Input1[row][col] - Input0[row][col] ;
                }
            }
        }

        std::for_each(Output.cbegin(), Output.cend(),
            [](auto const& row) {
                std::for_each(row.cbegin(), row.cend(),
                    [](const float value) { cout << value << " "; });

                cout << endl;
            });
    }
    else cout << "Unable to open file";
    return 0;
}

этот код вычитает три последних числа в строках 21 и 22 из 10 и 11 моего входного файла, то есть 51 и 81 или 72 и 102. этот код просто рассматривает два первых "шага"( например, первые звезды "шага" от строки 1 до конца строки 10). Теперь, как можно изменить код, чтобы код вычитал числа 2-го,3-го,... "шага" из первого "шага".(У меня есть более 1000 шагов)

Что я уже пробовал:

Если я хочу сделать это вычитание, я должен добавить этот кусок кода в конце кода и повторить его для другого "шага", но это очевидно, не будучи правдоподобным способом:
for (int lineno = 0; getline(myfile, line) && lineno < 7; lineno++) {
    if (lineno == 2)  myfile >> NUMBER_line3;
}
        Matrix Input2(NUMBER_line3, std::vector<float>(5));
for (int linenoq = 0; getline(myfile, line) && linenoq < NUMBER_line3; linenoq++) {
    myfile >> id >> type >> x1 >> y1 >> z1;
    addRow(Input2, linenoq, id, type, x1, y1, z1);
}

Matrix Output2(NUMBER_line, std::vector<float>(5));
for (size_t row = 0; row < Output2.size(); ++row) {
    for (size_t col = 0; col < Output2[0].size(); ++col) {
        if (col < 2) {
            Output2[row][col] = Input0[row][col];
        }
        else {
            Output2[row][col] = Input2[row][col] - Input0[row][col] ;
        }
    }
}

std::for_each(Output2.cbegin(), Output2.cend(),
 [](auto const& row) {
     std::for_each(row.cbegin(), row.cend(),
         [](const float value) { cout << value << " "; });

     cout << endl;
 });


Теперь, как я могу предотвратить это добавление, поставив петлю? заранее спасибо за любую подсказку или помощь

1 Ответов

Рейтинг:
11

Stefan_Lang

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

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

1. создайте структуру для хранения данных для одного шагового блока. На данный момент ваш код использует только две строки чисел, но, возможно, это может измениться: для чего нужны все остальные строки? Для строк чисел вы использовали вложенный вектор, но внутренний вектор всегда имеет один и тот же размер, поэтому вместо него следует использовать std::array:

struct Step {
    std::vector<std::array<int,5>> rows;
};


2. Регулировать addRow() функция: в настоящее время он не добавляет строку, а только записывает данные в уже существующую строку. Однако нет ничего плохого в том, чтобы на самом деле добавить строку, так что давайте сделаем это:
void addRow(Step& M, const int id, const float type, const float x, const float y,const float z) {
    std::array<int,5> columns;
    columns[0] = id;
    columns[1] = type;
    columns[2] = x;
    columns[3] = y;
    columns[4] = z;
    M.rows.push_back(columns);
}
Кроме того, я предлагаю соответствующим образом переименовать вашу функцию.

3. Экстракт функция 'ReadStep ()', который считывает один шаг блоков из указанного файла. Он должен получить файл, который он должен прочитать, и он должен вернуть подходящую структуру, которая содержит данные. Кроме того, он должен указывать, когда он не может прочитать данные, будь то потому, что файл находится в его конце, или по любой другой причине. Конечно, для этой цели мы можем просто проверить, есть ли в возвращаемой структуре какие - либо строки-что на самом деле имеет смысл, если строки действительно добавляются только тогда, когда есть какие-либо данные! Вот почему я предпочел сделать addRow фактически добавляющим строку.

Одна вещь, на которую следует обратить внимание в этой функции, - это сочетание вызовов getline() и cin::operator>>(). Это опасная вещь, потому что первый всегда удаляет символ(ы) конца строки из входного потока, но второй не гарантирует, что сделает то же самое!

Однако, предполагая, что ваш код работал до сих пор, давайте не будем его менять:
Step ReadStep(ifstream& input)
{
    Step result;
    for (int lineno = 0; getline(input, line) && lineno < 7; lineno++) {
        if (lineno == 2)  input >> NUMBER_line;
    }
    // cout << " NUMBER_line: " << NUMBER_line << endl; // not here!

    result.rows.resize(NUMBER_line); // see Step type definition below
    for (float linenoq = 0; getline(myfile, line) && linenoq < NUMBER_line; linenoq++) 
    {
        input >> id >> type >> x0 >> y0 >> z0;
        addRow(result.rows, id, type, x0, y0, z0);
    }
    return result;
}

Этот последний цикл for можно было бы улучшить, проверив, что действительно есть данные для чтения, и состояние ввода остается действительным. На самом деле, вся функция может быть улучшена путем проверки состояния ввода, чтобы убедиться, что мы не достигли его конца, прежде чем пытаться прочитать какие-либо данные.

4. Как только у вас есть эта функция, ReadStep(), ее достаточно легко вызвать в цикле, сохранить данные и обработать их по мере необходимости.

Еще одно предложение: вы можете превратить две функции ReadStep и addRow в функции-члены шага struct. Но, конечно, вам это не нужно, чтобы исправить ваш код.