2

this is a progression from the question I posted c++ program for reading an unknown size csv file (filled only with floats) with constant (but unknown) number of columns into an array . Im now moving onto the real application where I read in a file like:

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 

called 'example.2dm' and try and write 3 2d vectors (or possibly (preferably) arrays) for the data stored in lines starting with E4Q E3T and ND. I want to use these cell difinitions to print a file with cell centres.

I think this sort of problem is very usefull to be documented on here as my last question keeps getting views.

My code so far is:

// Read in CSV
//
// Alex Byasse

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

enum case_name {e3t, e4q, nd};

case_name checkit(std::string const& inString)
{
  if (inString == "E3T") return e3t;
  if (inString == "E4Q") return e4q;
  if (inString == "ND") return nd;
}

int main()
{
    std::vector<std::vector<std::string>> values;
    std::ifstream fin("example.2dm");
    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>()));
    }

    int nc = 0;
    int nn = 0;

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

    for (int i = 0; i < values.size() - 1; i++) {
      switch (checkit(values[i][0])){
    case e3t:
        cells[nc].push_back(std::stod(values[i][1]));
            cells[nc].push_back(std::stod(values[i][2]));
        cells[nc].push_back(std::stod(values[i][3]));
            cells[nc].push_back(std::stod(values[i][4]));
            cells[nc].push_back(std::stod(values[i][2]));
            cells[nc].push_back(std::stod(values[i][5]));
        nc++;
        break;
      case e4q:
        cells[nc].push_back(std::stod(values[i][1]));
        cells[nc].push_back(std::stod(values[i][2]));
        cells[nc].push_back(std::stod(values[i][3]));
        cells[nc].push_back(std::stod(values[i][4]));
        cells[nc].push_back(std::stod(values[i][5]));
        cells[nc].push_back(std::stod(values[i][6]));
        nc++;
        break;
      case nd:
        nodes[nn].push_back(std::stod(values[i][1]));
        nodes[nn].push_back(std::stod(values[i][2]));
        nodes[nn].push_back(std::stod(values[i][3]));
        nn++;
        break;
     }
    }
}

Can I get some help fixing this code and also. Is this correct?

#include <cstdlib>

Im getting the following compilation error:

$ g++ read_csv2.cpp -std=c++0x
read_csv2.cpp: In function ‘int main()’:
read_csv2.cpp:44:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:45:33: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:46:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:47:33: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:48:33: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:49:33: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:53:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:54:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:55:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:56:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:57:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:58:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:62:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:63:26: error: ‘stod’ is not a member of ‘std’
read_csv2.cpp:64:26: error: ‘stod’ is not a member of ‘std’

I'm running g++ on cygwin. I've checked the man pages and -std=c++11 is an available option and I've tryed it yet I get the same error?

Community
  • 1
  • 1
Alex Byasse
  • 322
  • 2
  • 5
  • 16
  • 1
    `std::stod` is a c++11 thing, you need to add `-std=c++11` to the compile command line. As a side note, when you keep editing the code it makes the answers less relevant since they were based on the old code. – Retired Ninja Sep 17 '13 at 06:55
  • @RetiredNinja: Im using that as stated in my question under the error. Im using cygwin cgg-c++ 4.7.3 and -std=c++11 but still got the same error?? – Alex Byasse Sep 17 '13 at 07:36
  • http://stackoverflow.com/questions/16132176/problems-with-stdstoi-not-working-on-mingw-gcc-4-7-2 – Retired Ninja Sep 17 '13 at 07:39
  • @RetiredNinja: Im not using mingw and i have used stoi in the past... – Alex Byasse Sep 17 '13 at 07:44
  • Perhaps you should ask a question specific to that problem and maybe someone will have an answer for you. I don't use that compiler, but if I did I'd start looking through the header files and try and figure it out. There are numerous other ways to convert from string to double as well. – Retired Ninja Sep 17 '13 at 08:15
  • He did ask a question specific to that problem, it got closed as a dup of this one. – Jonathan Wakely Sep 17 '13 at 08:16
  • Too bad. This actually didn't start out as a `Why doesn't std::stod work` question, but he edited the original source so much there's nothing else left to talk about. – Retired Ninja Sep 17 '13 at 08:32
  • @RetiredNinja: I checked on StackOverflow-Meta and in a forum there about posting new questions following on from other questions the peeps responded the polite thing to do was edit original question. – Alex Byasse Sep 17 '13 at 08:36
  • @AlexByasse, please compile the code in my answer and report the results. – Jonathan Wakely Sep 17 '13 at 08:45
  • The thing is, you asked a very vague question about why your code didn't work. People spent time telling you what was wrong with it, and you edited all the mistakes out, so now that answer isn't relevant to the question we see at all. By the time you're done the question may as well be `Look at my perfect code!` – Retired Ninja Sep 17 '13 at 08:49

3 Answers3

2

There are a lot of compile errors produced by your program. I suggest you to give some more time in reading the basics of C++ and STL.

  1. std::vector<std::vector<std::string>> values; to std::vector<std::vector<std::string> > values;. Notice the difference, some C++ compilers will take >> as the right shift operator.

  2. In many places in your code, you've used just vector instead of std::vector. Correct this or consider adding using namespace std; before the main function.

  3. double is a primitive type. There is nothing called std::double.

  4. Change vector::size(values)-1 to values.size() - 1.

  5. Use ; instead of , to separate the three parts of the for statement.

  6. switch values[i][0] it should be switch (values[i][0]).

  7. E3T is a string, so you use "E3T" instead of 'E3T'. Single quote is for characters.

  8. And C++ doesn't support switch with strings, so use if-else-if instead.

Rafi Kamal
  • 4,522
  • 8
  • 36
  • 50
1

The places where you have cells[nc] and nodes[nd] are broken because those vectors are never increased in size.

Here's something that may do what you need without requiring std::stod. I changed it to use all of the values from the ND lines assuming that was what you meant, if not, change the 4 to a 3 in that GetValues call.

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

double ToDouble(const std::string& str)
{
    std::stringstream s(str);
    double d;
    s >> d;
    return d;
}

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

void PrintValues(const std::string& title, std::vector<std::vector<double>>& v)
{
    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] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

int main()
{
    std::vector<std::vector<std::string>> values;
    std::ifstream fin("example.2dm");
    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<double>> 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(values[i], 1, 5));
        }
        else if(values[i][0] == "E4Q")
        {
            cells.push_back(GetValues(values[i], 1, 6));
        }
        else if(values[i][0] == "ND")
        {
            nodes.push_back(GetValues(values[i], 1, 4));
        }
    }

    PrintValues("Cells", cells);
    PrintValues("Nodes", nodes);

    return 0;
}
Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
1

The std::stod problem is odd, I thought that worked on Cygwin. What happens if you compile this program with -std=c++11?

#include <string>
#if __cplusplus < 201103L
#warning No C++11 support
#endif

#if !defined(_GLIBCXX_USE_C99)
#warning No C99 library functions
#endif

#if defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
#warning Broken vswprintf
#endif

int main() { }

Those are the preprocessor conditions necessary for libstdc++ to define std::stod so if compiling that produces any warning then you won't be able to use std::stod. You might need to use strtod(values[i][3].c_str(), nullptr) instead.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521