ошибка компилятора xcode необъявленный идентификатор c++

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

У меня есть 2 вопроса:

1: Я получаю красную ошибку в XCODE при вызове подпрограммы Print_Values, которая говорит, что outfil является необъявленным идентификатором?? Хотя я идентифицирую файл прямо в начале моей основной функции??

2: Можно ли в любом случае оптимизировать или векторизовать этот код для краткости или скорости, я бы очень признателен за любые указатели, поскольку это моя первая программа на реальном языке программирования (я пришел из Matlab) ?? (например, у меня есть 2 подпрограммы получения значений, одна из которых использует atoi для чтения целых чисел, а другая - strtod для чтения двойных значений, я не могу придумать способ превратить их в одну??)

изменить: с помощью компилятора cygwin gcc-c++ -std=c++11

Удачи и большое спасибо

Код пока:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
#include <cstdlib>

std::vector<double> GetValues_n(const std::vector<std::string>& src, int start, int end)
{
    std::vector<double> ret;
    for(int i = start; i <= end; ++i)
    {
        ret.push_back(std::strtod(src[i].c_str(), nullptr));
    }
    return ret;
}

std::vector<int> GetValues_c(const std::vector<std::string>& src, int start, int end)
{
    std::vector<int> ret;
    for(int i = start; i <= end; ++i)
    {
        ret.push_back(std::atoi(src[i].c_str()));
    }
    return ret;
}

std::vector<double> polycentre(const std::vector<double>&  x,const std::vector<double>&  y,size_t ID)
{
    std::vector<double> C(3, 0);
    std::vector<double> x1(x.size(),0);
    std::vector<double> y1(y.size(),0);
    size_t sizx = x.size();
    size_t sizy = y.size();
    if(sizy != sizx)
    {
        std::cerr << "polycentre inputs not equal length";
    }
    double x0 = x[0];
    double y0 = y[0];
    for(int aa = 1; aa < sizx; ++aa)
    {
        if(x[aa] < x0){x0 = x[aa];}
        if(y[aa] < y0){y0 = y[aa];}
    }
    double A = 0.0;
    double B = 0.0;
    for(size_t aa = 0; aa < sizx; ++aa)
    {
        x1[aa] = x[aa] - x0;
        y1[aa] = y[aa] - x0;
        if(aa != sizx-1)
        {
            A = A + (x1[aa]*y1[aa+1] - x1[aa+1]*y1[aa]);
            B = B + ((x1[aa]+x1[aa+1])*(x1[aa]*y1[aa-1]-x1[aa-1]*y1[aa]));
        }
        else if(aa == sizx-1)
        {
            A = A + (x1[aa] - y1[aa]);
            B = B + ((x1[aa]+1)*(x1[aa]*1-1*y1[aa]));
        }
    }
    A = A*0.5;
    C[0] = ID;
    C[1] = ((1/6/A)*B)+x0;
    C[2] = ((1/6/A)*B)+y0;
    return C;
}

template <typename T>

void PrintValues(const std::string& title, std::vector<std::vector<T>>& v, std::ofstream outfil)
{
    if(outfil.is_open())
    {
        outfil << "ID,X,Y,Z \n";
        std::cout << title << std::endl;
        for(size_t line = 0; line < v.size(); ++line)
        {
            for(size_t val = 0; val < v[line].size(); ++val)
            {
                std::cout << v[line][val] << " ";
                outfil << v[line][val] << ",";
            }
            outfil << "\n";
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
}

int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        std::cerr << argv[0] << " needs to get input file (2dm)" << std::endl;
    }

    else if (argc == 3)
    {
        std::ofstream outfil(argv[2]);
    }

    else
    {
        std::ofstream outfil(std::string(argv[1]) + ".csv");
    }

    std::vector<std::vector<std::string>> values;
    std::ifstream fin(argv[1]);

    for (std::string line; std::getline(fin, line); )
    {
        std::istringstream in(line);
        values.push_back(
                         std::vector<std::string>(std::istream_iterator<std::string>(in),
                                                  std::istream_iterator<std::string>()));
    }

    std::vector<std::vector<int>> cells;
    std::vector<std::vector<double>> nodes;

    for (size_t i = 0; i < values.size(); ++i)
    {
        if(values[i][0] == "E3T")
        {
            cells.push_back(GetValues_c(values[i], 1, 5));
        }
        else if(values[i][0] == "E4Q")
        {
            cells.push_back(GetValues_c(values[i], 1, 6));
        }
        else if(values[i][0] == "ND")
        {
            nodes.push_back(GetValues_n(values[i], 1, 4));
        }
    }

    std::vector<std::vector<double>> cell_centres;

    for (size_t aa = 0; aa < cells.size(); ++aa)
    {
        if(cells[aa].size() == 5)
        {
            std::vector<double> xs = {nodes[(cells[aa][1]) - 1][1], nodes[(cells[aa][2]) - 1][1], nodes[(cells[aa][3]) - 1][1]};
            std::vector<double> ys = {nodes[(cells[aa][1]) - 1][2], nodes[(cells[aa][2]) - 1][2], nodes[(cells[aa][3]) - 1][2]};
            cell_centres.push_back(polycentre(xs,ys,aa+1));
        }
        else if(cells[aa].size() == 6)
        {
            std::vector<double> xs = {nodes[(cells[aa][1]) - 1][1], nodes[(cells[aa][2]) - 1][1], nodes[(cells[aa][3]) - 1][1], nodes[(cells[aa][4]) - 1][1]};
            std::vector<double> ys = {nodes[(cells[aa][1]) - 1][2], nodes[(cells[aa][2]) - 1][2], nodes[(cells[aa][3] - 1)][2], nodes[(cells[aa][4]) - 1][2]};
            cell_centres.push_back(polycentre(xs,ys,aa+1));
        }
    }

    PrintValues("Cell Centres", cell_centres, outfil);
    //PrintValues("Cells", cells, outfil);
    //PrintValues("Nodes", nodes, outfil);

    return 0;
}

Входной файл:

MESH2D
MESHNAME "default coverage"
NUM_MATERIALS_PER_ELEM 1 
E4Q 1 19 20 14 16 2
E4Q 2 17 16 15 23 2
E4Q 3 22 15 14 21 2
E4Q 4 4 3 21 20 1
E4Q 5 6 20 19 7 1
E4Q 6 18 17 10 9 1
E4Q 7 17 23 12 11 1
E4Q 8 7 19 18 8 1
E4Q 9 22 1 13 23 1
E3T 10 14 20 21 2
E3T 11 21 2 22 1
E3T 12 21 3 2 1
E3T 13 22 2 1 1
E3T 14 5 20 6 1
E3T 15 20 5 4 1
E3T 16 16 14 15 2
E3T 17 23 13 12 1
E3T 18 22 23 15 2
E3T 19 17 11 10 1
E3T 20 17 18 16 2
E3T 21 8 18 9 1
E3T 22 18 19 16 2
ND 1 -3.25811078e+002 7.70285567e+001 0.00000000e+000
ND 2 -3.24209146e+002 7.60394871e+001 0.00000000e+000
ND 3 -3.23012110e+002 7.44783503e+001 0.00000000e+000
ND 4 -3.22754089e+002 7.25326647e+001 0.00000000e+000
ND 5 -3.23617358e+002 7.08079432e+001 0.00000000e+000
ND 6 -3.25161538e+002 6.98134116e+001 0.00000000e+000
ND 7 -3.27128620e+002 6.98759747e+001 0.00000000e+000
ND 8 -3.29095703e+002 6.99385378e+001 0.00000000e+000
ND 9 -3.30301095e+002 7.14667646e+001 0.00000000e+000
ND 10 -3.30786908e+002 7.33241555e+001 0.00000000e+000
ND 11 -3.30835733e+002 7.52916270e+001 0.00000000e+000
ND 12 -3.29587322e+002 7.65401204e+001 0.00000000e+000
ND 13 -3.27743000e+002 7.72270000e+001 0.00000000e+000
ND 14 -3.26108525e+002 7.32067724e+001 0.00000000e+000
ND 15 -3.27041416e+002 7.42070316e+001 0.00000000e+000
ND 16 -3.27350377e+002 7.31716751e+001 0.00000000e+000
ND 17 -3.29153676e+002 7.40024406e+001 0.00000000e+000
ND 18 -3.28659180e+002 7.19967464e+001 0.00000000e+000
ND 19 -3.26845856e+002 7.14062637e+001 0.00000000e+000
ND 20 -3.25000347e+002 7.20534611e+001 0.00000000e+000
ND 21 -3.24701329e+002 7.39638966e+001 0.00000000e+000
ND 22 -3.26167714e+002 7.53360591e+001 0.00000000e+000
ND 23 -3.28060316e+002 7.54194849e+001 0.00000000e+000
BEGPARAMDEF
GM  "Mesh"
SI  0
DY  0
TU  ""
TD  0  0
NUME  3
BCPGC  0
DISP_OPTS entity   0 0 0 0 1 0 0 0
DISP_OPTS inactive 0 0 0 0 1 0 0 0
DISP_OPTS multiple 0 0 0 0 1 0 0 0
BEFONT  0 1
DISP_OPTS entity   1 0 0 0 1 0 0 0
DISP_OPTS inactive 1 0 0 0 1 0 1 0
DISP_OPTS multiple 1 0 0 0 1 0 1 0
BEFONT  1 1
DISP_OPTS entity   2 0 0 0 1 0 0 0
DISP_OPTS inactive 2 0 0 0 1 0 1 0
DISP_OPTS multiple 2 0 0 0 1 0 1 0
BEFONT  2 1
MAT 1 "material 01"
MAT 2 "material 02"
MAT_MULTI 0
ENDPARAMDEF
BEG2DMBC
END2DMBC
BEGCURVE Version: 1
ENDCURVE 

person Alex Byasse    schedule 22.09.2013    source источник


Ответы (2)


Переменные находятся внутри блока, в котором они объявлены. То есть вы std::ofstream в

...
else if (argc == 3)
{
    std::ofstream outfil(argv[2]);
}
...

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

std::ofstream outfil;
...
else if (argc == 3)
{
    outfil.open(argv[2]);
}
person Dietmar Kühl    schedule 22.09.2013

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

Однако между этими двумя типами чисел существует огромная функциональная разница в том, как вы их используете. Целые числа — это индексы, а двойные значения — это координаты. Поскольку вы не можете использовать двойные числа в качестве индексов, они должны быть приведены к типу int перед каждым использованием. Это не приводит к «оптимизированному коду», а скорее к прямо противоположному!

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

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

Если вам нужна одна конкретная процедура — чтение из внешнего файла и анализ результата — чтобы быть быстрой, то прочитайте весь файл данных в память, обработайте и отбросьте. Вам по-прежнему нужны strtod и atoi (любой код, который вы придумали бы сами, вероятно, медленнее), но вы можете написать простой сканер строк, который перебирает данные один раз. Но вы должны учитывать это только в том случае, если чтение является узким местом.

Навскидку я не вижу никаких оптимизаций в вычислительной части. Единственное, что вы можете сделать, это сразу же сохранить минимальные значения при чтении в вашей подпрограмме Getvalue_C.

Но остерегайтесь преждевременной оптимизации! Чтобы увидеть, где ваш код «медленный», используйте профайлер.

person Jongware    schedule 22.09.2013