1

I have a text file with 2 columns and many rows. each column is separated by spaces. i need to read them to a 2D array for further calculations. my data file looks like

0.5 0.479425539
1   0.841470985
1.5 0.997494987
2   0.909297427
2.5 0.598472144
3   0.141120008
3.5 -0.350783228
4   -0.756802495
4.5 -0.977530118
5   -0.958924275  

And my feeble attempt is

#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <ctype.h>
using namespace std;

int main () {
  char line,element;
  std::ifstream myfile ("C:\\Users\\g\\Desktop\\test.txt");
  if (myfile.is_open())
  {
    while ( myfile.good() )
    {
      getline(myfile,line);
       cout << line<<endl;               
      _getch();
    }
    myfile.close();

  }

  else cout << "Unable to open file"; 

  return 0;

}

The problem is I'm not able to read them correctly.... its either reading the whole line... if I specify the delimiter as 'space' then, its not reading the next row.

Pls point out whats wrong. and what should i do to store the data into 2d array for further calculations. Thank you

Stals
  • 1,543
  • 4
  • 27
  • 52
user2024645
  • 21
  • 1
  • 2
  • 5
  • Does your program even compile? There is no overload of [`std::getline`](http://en.cppreference.com/w/cpp/string/basic_string/getline) that takes a single character as second argument. There are also lot of other weird things in your code, like the use of _bitwise or_ (the `|` operator), and the input operator from a `char` variable. – Some programmer dude Jan 30 '13 at 09:32
  • I Have edited the code now ... It does compile... – user2024645 Jan 30 '13 at 09:37

3 Answers3

1

You can read the whole line into a std::string, then use std::istringstream to extract the values from the line.


A complete working program:

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

int main()
{
    std::ifstream file("C:\\Users\\g\\Desktop\\test.txt");

    std::string line;

    // Read a line of input from the file
    while (std::getline(file, line))
    {
        // `istringstream` behaves like a normal input stream
        // but can be initialized from a string
        std::istringstream iss(line);

        float value;

        // The input operator `>>` returns the stream
        // And streams can be used as a boolean value
        // A stream is "true" as long as everything is okay
        while (iss >> value)
        {
            std::cout << "Value = " << value << '\t';
        }

        // Flush the standard output stream and print a newline
        std::cout << std::endl;
    }
}

Given the contents in the file being as in the question, the first three lines of output should be:

Value = 0.5 Value = 0.479425539
Value = 1   Value = 0.841470985
Value = 1.5 Value = 0.997494987

For a 2d-array, I would use a std::vector of std::array:

#include <vector>
#include <array>

...

std::vector<std::array<float, 2>> array;

...

float value1, value2;
if (iss >> value1 >> value2)
{
    std::cout << "Values = " << value1 << ", " << value2;

    array.emplace_back(std::array<int, 2>{{value1, value2}});
}

Now the first line values are array[0][0] and array[0][1], and the last lines values are array[array.size() - 1][0] and array[array.size() - 1][1].

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1
#include <fstream>
#include <string>
#include <sstream>
#include <iostream>
#include <vector>

int main(int argc, char** argv) {
   std::ifstream f(argv[1]);
   std::string l;
   std::vector<std::vector<double> > rows;
   while(std::getline(f, l)) {
       std::stringstream s(l);
       double d1;
       double d2;
       if(s >> d1 >> d2) {
           std::vector<double> row;
            row.push_back(d1);
            row.push_back(d2);
            rows.push_back(row);
        }
    }

    for(int i = 0; i < rows.size(); ++i)
        std::cout << rows[i][0] << " " << rows[i][1] << '\n';
}

The last for loop shows how to use the values in the "array". The variable rows is strictly speaking not an array, but a vector of vectors. However, a vector is much safer than c-style arrays, and allows access to its elements using [].

[As I posted this I saw a very similar program posted as a response. I wrote mine independently.]

  • std::ifstream f(argv[1]); std::string l; std::vector > rows; can u pls expalin me this part. – user2024645 Jan 30 '13 at 09:54
  • When you run the program, give the name of the file to be read as the first argument. –  Jan 30 '13 at 09:56
  • Alternatively replace `std::ifstream f(argv[1]);` with `std::ifstream f("C:\\Users\\g\\Desktop\\test.txt");` –  Jan 30 '13 at 09:56
  • `std::ifstream f(argv[1]);` creates and opens an input file stream for the file given as the first command line argument. If you are launching your program in visual studio, right click the project in the solution explorer, select Properties->Configuration Properties->Debugging and type the name of the file you want to read in the field "Command Arguments" –  Jan 30 '13 at 10:09
  • `std::vector rows;` creates a vector (think of it as an array, but but nicer). The vector stores doubles. Look here: http://www.cplusplus.com/reference/vector/vector/ –  Jan 30 '13 at 10:11
0

As C++ has evolved over the years, below is a Modern C++ version.

  • It uses auto where possible
  • Uses std::pair to hold 2 values (A std::pair is a specific case of a std::tuple with two elements)
  • Does not close file (destructor does that at end of block)
  • Does not read line by line, as the stream uses <space> and <enter> as delimiters
  • The variables have meaningful names, so the program "reads" easily,
  • Uses a range for loop to output the data.
  • Doesn't bring the whole std namespace into the code - Why is “using namespace std” considered bad practice?

.

#include <fstream>
#include <iostream>
#include <vector>
#include <utility>

int main( int argc, char** argv )
{
    if ( argc < 1 )
        return -1;

    const auto    fileName = argv[ 1 ];
    std::ifstream fileToRead( fileName );

    typedef std::pair< double, double > DoublesPair;
    std::vector< DoublesPair > rowsOfDoublesPair;
    DoublesPair                doublePairFromFile;

    while ( fileToRead >> doublePairFromFile.first >> doublePairFromFile.second )
    {
        rowsOfDoublesPair.push_back( doublePairFromFile );
    }

    for ( const auto row : rowsOfDoublesPair )
        std::cout << row.first << " " << row.second << '\n';
}
Community
  • 1
  • 1
Robert Andrzejuk
  • 5,076
  • 2
  • 22
  • 31