0

I am trying to read the unknown contents of a text file into a 2D array and have it come out looking like:

M [0] [0]=2 M [0] [1]=1 M [0] [2]=0
M [1] [0]=0 M [1] [1]=1 M [1] [2]=3
M [2] [0]=8 M [2] [1]=9 M [2] [2]=1
M [3] [0]=3 M [3] [1]=5 M [3] [2]=2

when the text file looks like this:

2
1 0
0 1
3
8 9 1
3 5 2
-2 3 -1
0

The zero at the end shows the end of the file.

My problem is the array can be a max size of 10X10 so there is no way of knowing what the size of the 2D array is and how to get it to look like i have shown above.

Any ideas?

Mike Webb
  • 8,855
  • 18
  • 78
  • 111
Zud
  • 4,247
  • 4
  • 24
  • 25
  • Does the array have to be NxN? Otherwise, there are multiple valid array dimensions for some inputs... which one to choose? –  Nov 02 '10 at 16:52
  • Maybe I just misunderstand your intent here, but I see M[2][0], M[2][1] and M[2][2] twice in your matrix display, and not the -2,3 and -1 values in the file example. You should clear that up if you want to help people understand your problem. – haylem Nov 02 '10 at 17:08
  • You should also be aware that having a 0 denote the end of the file means that you have to have extended logic for determining whether or not a 0 inside the body of the matrix is a real zero or the "end" zero that gets excluded. – SubSevn Nov 02 '10 at 17:13
  • @haylem - that was a mistake on my part in typing it out. Im sorry. It is suppose to be a third line. – Zud Nov 02 '10 at 17:20
  • @SubSevn the zero thing is not my idea. Its the professors. Stupid idea if you ask me but i cant change it. – Zud Nov 02 '10 at 17:20
  • @Alec: it's OK. But then why don't you edit your question to fix this? Or people try to help will keep getting confused. – haylem Nov 02 '10 at 17:24

6 Answers6

1

For some dimensions N x M

char c;
int x;
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
  c = fgetc(file);
  if(c == ' ') continue;
  if(c == EOF) return;
  if(c == '-')
  {
      c = fgetc(file);
      x = -1 * ((int)c);
  } else {
      x = c;
  }
  if(x == 0)
  {
      array[i][j] = x;
  } else {
      return;
  }
}
}

But if you're talking about "what's the size of the matrix required to store these" then you're going to need a way to figure out what dimensions you want.

SubSevn
  • 1,008
  • 2
  • 10
  • 27
  • this is what i was thinking to read in the array but if i do this all of those number will end up in the first two rows and i wont get anywhere. – Zud Nov 02 '10 at 16:56
  • That's the thing, you have to know what dimensions you want. I'll clean up the code a bit. – SubSevn Nov 02 '10 at 16:57
  • The fstream method mentioned by Mike Webb with some modifications for the '-' character (and other things) is a more C++ way of doing this (using streams as opposed to fgetc). That and my code isn't tested heh.. – SubSevn Nov 02 '10 at 17:10
1

Just use 'fstream'. It ignores new lines and works just like 'iostream'. You just need to keep track of your matrix row and column.

//open "myFileName.txt" with an input file stream
std::ifstream inputFile("myFileName.txt");

while(!inputFile.eof()) //Check for end-of-file character
{
    //do this while keeping track of your matrix position
    inputFile >> M [curRow] [curColumn]
}

inputFile.close();

And don't forget to include the library:

#include <fstream>

Edit: The >> operator will also attempt to auto-cast the input as whatever type you are using:

double dTemp;
int iTemp;
std::string sTemp;

std::ifstream in("myFile.txt");

in >> dTemp; //input cast as double
in >> iTemp; //input cast as integer
in >> sTemp; //input cast as string

in.close();

Edit: Get the number of elements of the file

int temp, numberOfInputs;
while(!inputFile.eof())
{
    inputFile >> temp;
    ++numberOfInputs;
}

inputFile.seekg(0, std::ios::beg); //Go to beginning of file

Once you have the number of inputs you can use that to figure out the number of rows and colums.

Mike Webb
  • 8,855
  • 18
  • 78
  • 111
  • This would work if i knew the size of the file and how many rows/column i wanted but i don't. There is a max of 10X10 and i can take anything in up to that. – Zud Nov 02 '10 at 17:10
  • @Alec - Read the contents of the file first, go to the beginning, and then read in the contents. I'll update the answer. – Mike Webb Nov 02 '10 at 17:20
  • Don't test for eof in the while condition. As you enter the loop even if you have reached the end of file. – Martin York Nov 02 '10 at 18:30
  • @Martin York - What is the reason? When do you test for it? Is a do-while better? The above way was how I was taught and how I've always done it. – Mike Webb Nov 02 '10 at 18:45
  • @MikeWebb: This is now how you were taught (I bet :-) or we should shoot your teacher ;-)). You test for `eof` after a read not before. The best way to loop and read is `while( inputFile >> temp)` This is actually the anti pattern `numberOfInputs` will be off by one. Because the last read will fail. [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/q/5431941/14065) – Martin York Jan 30 '16 at 17:37
1

Try:

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


int main()
{
    std::ifstream   file("plop.dat");
    if(!file)
    {
        std::cerr << "Failed to open File\n";
        return 1;
    }

    // Keep looping until we are done.
    while(true)
    {
        int size;
        file >> size;

        // You said a size zero indicates termination.
        if (size == 0)
        {    break;
        }

        // Create a square 2D vector (Vector inside a Vector)
        std::vector<std::vector<int> >      matrix(size, std::vector<int>(size, 0));

        // Loop over each axis
        for(int x = 0;x < size; ++x)
        {
            for(int y = 0;y < size; ++y)
            {
                // Read one number for each location.
                // The operator >> automatically skips white space
                // White Space includes newline and tab. So it should work
                // perfectly if the input is OK. But it is hard to detect
                // an error in the format of the file.
                file >> matrix[x][y];
            }
        }
    }
}

~

Martin York
  • 257,169
  • 86
  • 333
  • 562
0

So all row of the array have 3 values?
Simply read the values into the array keeping a count of which column you are in and ignore the newlines?

Look at getline

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • the rows all need to end up the same length the special value marks the end of the file. It needs to look like a Matrix. – Zud Nov 02 '10 at 16:51
  • What you have would work but the input can be anything up to 10 values for each row. There is no way of knowing until you get the input from the file. – Zud Nov 02 '10 at 16:53
  • A matrix isn't always "square", you can have one that's (for example) 1x100 and storing 100 entries, or a 10x10 doing the same thing. – SubSevn Nov 02 '10 at 16:55
  • Well according to my teacher it has to come out "square" this is why i dont understand how to do this. I could easily read this into an array 1X100 but that's not what he wants. – Zud Nov 02 '10 at 16:59
  • Well then you have to read them in, and come up with a way of determining the correct dimensions. If you know every time that they will be "square" then you can just count them and find the square root. That is, if you read in 49, you know to have a 7x7 matrix. – SubSevn Nov 02 '10 at 17:08
0

getline and stringstream to read, vector< vector<int> > to store.

Edit: Oh, so the size is always N*N? Then just read using while(cin>>x) { if (cin.good()) ...; } into a vector<int>, check the total size, and split into vector< vector<int> >

Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151
0

Single and multi-dimensional C arrays are just contiguous pieces of memory. The difference is more syntactical in terms of what indexing into the array does: for a 2-dimensional array it just multiplies one dimension by the size of the other dimension before adding the second dimension to find the offset.

So to solve:

  1. read the values into a std::vector (other answers have sugegsted ways to do this)
  2. work out the size (integer square root of myArray.size())
  3. calculate the index as, e.g.:

    int idx(int size, int d1, int d2)
    {
        return (d1*size)+d2;
    }
    
  4. Return the vector element at the index e.g.:

    for (int d1 = 0; d1 < size; d1++)
    {
        for (int d2 = 0; d2 < size; d2++)
            std::cout << "M [" << d1 << "] [" << d2 << "]=" << myArray[idx(size, d1, d2)] << " ";
        std::cout << std::endl;
    }
    

gives me:

$ g++ arr.cpp && ./a.out
M[0][0]=2 M[0][1]=1 M[0][2]=0
M[1][0]=0 M[1][1]=1 M[1][2]=3
M[2][0]=8 M[2][1]=9 M[2][2]=1
danio
  • 8,548
  • 6
  • 47
  • 55