I am trying to read and write a text file into an array and then store it back into the text file. The main problem i am having is the storing the file character by character into the 3D array.

Here is my code:

#include <iostream>
#include <fstream>
using std::ofstream;
using namespace std;

int main()
{
    char cabin[2][3][12];
    char ch, res;
    int num, lvl=0, row=0, col=0;

    
    ifstream indata;
    indata.open("littleswandb.txt");
    
    if(!indata) 
    { 
      cout << "File could not be opened" << endl;
      system("pause");
      return 0;
    }

      indata >> ch;
       while (!indata.eof()) 
       { // keep reading until end-of-file
       num=0;
         while(num<4)
         {
          cout << ch;
          indata >> ch;
          num =num +1;
          } // sets EOF flag if no value found
          cout << endl;
       }
       indata.close();
    system("pause");

    cout << "Would you like to make a reservation? Y/N" << endl;
    cin >> res;
    while ((res == 'Y') || (res == 'y'))
       {  
                
             cout << "Which Level Would you like to reserve? 1-3" << endl;
             cin >> lvl;
             cout << "Which Row Would you like to reserve? 1-13" << endl;
             cin >> row;
             cout << "Which Colunm Would you like to reserve? 1-4" << endl;
             cin >> col;
             lvl = lvl - 1; //Minus 1 for array
             row = row - 1; //Minus 1 for array
             col = col - 1; //Minus 1 for array
             
             if (cabin[lvl][row][col] != 'X')
             {
                cabin[lvl][row][col] = 'X';
                lvl = lvl + 1; //Plus 1 after array use
                row = row + 1; //Plus 1 after array use
                col = col + 1; //Plus 1 after array use
                cout << "You have booked the Cabin on Level: " << lvl 
                     << " Row: " << row 
                     << " Colunm: " << col << endl;
                
                //output the array onto the screen     
                for(int a=0; a<3; a++)//Levels
                {
                    for(int b=0; b<13; b++)//Rows
                    {
                       for(int c=0; c<4; c++)//Colunms
                       {
                          cout << cabin[a][b][c];
                       }
                       cout << endl;
                    }
                cout << endl;
                }                
                               
             ofstream outdata("littleswandb.txt");
             for(int d=0; d<3; d++) // Levels
             {
                 for(int e=0; e<12; e++) //Rows
                 {
                     for(int f=0; f<4; f++) // Colunms
                             outdata<<cabin[d][e][f]; // store array into file
                     outdata<< endl;
                 }
                 outdata<< endl;
             }
             outdata.close(); 
                system("pause");
             }
             else
                 cout << "That cabin is already booked" << endl;
                 cout << "Would you like to try another cabin? Y/N" << endl;
                 cin >> res;
       }
    cout << "Thank you. Good bye." << endl;
       system("pause");
    return 0;
}

Can you show an example data file? I think if you know all the dimensions ahead of time you could just use a for loop to read in the data and make things slightly easier on yourself.

the text file is representing a cruise chip database where 'B' is a balcony cabin, 'W' is a window cabin, and 'I' is an inside cabin. there are 3 levels in the cruise ship, with 4 colunms and 13 rows. that is where the 3d array comes in "cabin[2][3][12]".
the following is what is inside a text file named "littleswandb.txt"

BIIB
BIIB
BIIB
BIIB
BIIB
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
BIIB
BIIB
BIIB
BIIB
BIIB
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
BIIB
BIIB
BIIB
BIIB
BIIB
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW
WIIW

A quick point before anything else

there are 3 levels in the cruise ship, with 4 colunms and 13 rows. that is where the 3d array comes in "cabin[2][3][12]".

is incorrect. If you had a cruiseship of those dimensions the indexes of your array would go from cabin[0][0][0] to cabin[2][3][12] but your array must be declared

char cabin[3][4][13];

Actually that may be a big part of your problem. Are you overrunning the array when you try to write it out? I'm not convinced you're reading it in as you want to either...

i changed the array and the output is still the same. (random symbols). Also i thought that array[3] had 4 memory slots. so that is why i had the array number set to 1 less then wat i needed

i changed the array and the output is still the same. (random symbols). Also i thought that array[3] had 4 memory slots. so that is why i had the array number set to 1 less then wat i needed

Why would array[3] have 4 slots? It only has 3, as the number signifies -- array[0] to array[2]

well i have changed them to cabin[3][4][13] now. should i change the for loop and get rid of the minus 1 to lvl, row, col and plus 1 parts lvl, row, col?

well i have changed them to cabin[3][4][13] now. should i change the for loop and get rid of the minus 1 to lvl, row, col and plus 1 parts lvl, row, col?

No, don't change the -1 for any of the dimensions, as you still need that since you are going from [0][0][0] to [2][3][12] over the range of the indexes.

so i should have:

char cabin[3][4][13];

Which gives me 156 slots
and
for the For loop

for(int a=0; a<3; a++)//Levels
      {
       for(int b=0; b<13; b++)//Rows
       {
        for(int c=0; c<4; c++)//Colunms
        {
            cout << cabin[a][c][b];
        }
        cout << endl;
       }
      cout << endl;
      }

Yes, except that's going to fill in a different order than 0,0,0 -> 0,0,1-> 0,0,2->... since the middle index will progress first. If you're going to have to read the file ( you wrote out) back into the program at a later time you'll want to keep a consistent format. That way your reading and writing loops will be similar to each other.

That looks good....

yep thats the order i want to read/write. e.g 0,0,1 | 0,0,2.
if i swap 'b' and 'c' i am still getting the random symbols.

cout << cabin[a][c][b];

also if i swap

if (cabin[lvl][row][col] != 'X')
{
      cabin[lvl][row][col] = 'X';

TO:

if (cabin[lvl][col][row] != 'X')
      {
      cabin[lvl][col][row] = 'X';

i still get errors

Can you put up your current code. Also, specify where you are getting the random symbols.

Here is the current code

#include <iostream>
#include <fstream>
      
using std::ofstream;
using namespace std;

int main()
{
      char cabin[3][4][13];
      char ch, res;
      int num, lvl=0, row=0, col=0;

      ifstream indata;
      indata.open("littleswandb.txt");
      if(!indata)
      {
                 cout << "File could not be opened" << endl;
                 system("pause");
                 return 0;
      }
      indata >> ch;
      while (!indata.eof())// keep reading until end-of-file
      { 
      num=0;
      while(num<4)
      {
          cout << ch;
          indata >> ch;
          num =num +1;
      } // sets EOF flag if no value found
      cout << endl;
      }
      indata.close();
      system("pause");
      
      cout << "Would you like to make a reservation? Y/N" << endl;
      cin >> res;
      while ((res == 'Y') || (res == 'y'))
      {
       cout << "Which Level Would you like to reserve? 1-3" << endl;
       cin >> lvl;
       cout << "Which Row Would you like to reserve? 1-13" << endl;
       cin >> row;
       cout << "Which Colunm Would you like to reserve? 1-4" << endl;
       cin >> col;

      //lvl = lvl -1; //Minus 1 for array
      //row = row -1; //Minus 1 for array
      //col = col -1; //Minus 1 for array

      if (cabin[lvl][row][col] != 'X')
      {
      cabin[lvl][row][col] = 'X';
      //lvl = lvl + 1; //Plus 1 after array use
      //row = row + 1; //Plus 1 after array use
      //col = col + 1; //Plus 1 after array use
      cout << "You have booked the Cabin on Level: " << lvl
           << " Row: " << row
           << " Colunm: " << col << endl;
      //output the array onto the screen
      for(int a=0; a<3; a++)//Levels
      {
       for(int b=0; b<13; b++)//Rows
       {
        for(int c=0; c<4; c++)//Colunms
        {
            cout << cabin[a][c][b];
        }
        cout << endl;
       }
      cout << endl;
      }
      /*ofstream outdata("littleswandb.txt");
      for(int d=0; d<3; d++) // Levels
      {
         for(int e=0; e<13; e++) //Rows
            {
                 for(int f=0; f<4; f++) // Colunms
                 { 
                    outdata<<cabin[d][e][f]; // store array into file
                 }
                 outdata<< endl;
            }
            outdata << endl;
      }
      outdata.close();
      system("pause");*/
      }
      else
      cout << "That cabin is already booked" << endl;
      cout << "Would you like to try another cabin? Y/N" << endl;
      cin >> res;
      }
cout << "Thank you. Good bye." << endl;
system("pause");
return 0;
}

im getting the random symbols as the output of the program in the command prompt. they seems to be in the format i want to display e.g 4 across, and then 13 down. then again for the 2nd and 3rd "level of the ship" / "dim of the array"

This is all happening from the output that's generated in lines 61-70? Ok, I was able to reproduce it. If that's not where it is we can look at some other areas.

I don't think it's related but you can eliminate the use of infile.eof() as your loop condition -- as using that can go one past the end of the list because of the way that method is designed.

Are you sure you're reading the file correctly? What are you doing with the data?

Where did you initialize the cabin matrix? When you define a variable, if you don't initialize it they contain garbage values.

Change line 9 to: char cabin[3][4][13]= {' '}; ** I should have thought of this earlier but the array was not initialized so you were printing out junk characters that were there when the array was created.
It may not solve all the problems but this explains what you were seeing.

I think the input is probably ok as it echos properly on the screen.

** This seems to work but I do not know if that's the proper way to do it. It won't allow any other characters in it's place.

Jonsca:
by "infile.eof()" do you mean "indata.eof()"? and if i take it out that will mean that it will not know when to stop reading the file.

WaltP:
when it reads a character i get it to display the character so that i can see that it is reading it right. am i doing it wrong?

what i want to do with the data later on is change one char, in a certatin spot in the file to an 'X' to represent a reserved spot in my database.

i had the cabin matrix initialized on line 9. is this wrong?

jonsca:
i changed line 9 to what u said but now i am getting a bunch of blank spaces and an 'X'. and then more spaces then another 'X', then spaces and random symbols again.

Jonsca:
by "infile.eof()" do you mean "indata.eof()"? and if i take it out that will mean that it will not know when to stop reading the file.

Yes I meant indata. I'm talking about a situation where you use your indata>>ch as the loop variable for the while loop so that when you run out of characters it returns null and the loop ends. The .eof method is prone to scanning in the last character multiple times. Read this post by Dave Sinkula it gives all the details. For right now, though I don't think it's the primary problem but I was examining it as a possibility before.

WaltP:
when it reads a character i get it to display the character so that i can see that it is reading it right. am i doing it wrong?

Unless you're doing something fluky both times and everything's coming out right side up by chance I think that part is ok. Don't quote me on that.

what i want to do with the data later on is change one char, in a certatin spot in the file to an 'X' to represent a reserved spot in my database.

jonsca:
i changed line 9 to what u said but now i am getting a bunch of blank spaces and an 'X'. and then more spaces then another 'X', then spaces and random symbols again.

And it seems to be doing that okay on my end it's just there's no other characters around it to reference where the X is. I was not getting the random symbols anymore.

i had the cabin matrix initialized on line 9. is this wrong?

You had declared it but not initialized it, in other words it had no values just whatever happened to be in memory at that location.
My approach had it take a blank space for each element of the array. However, I'm working from memory and I can find no written evidence to verify that technique works in all cases. You could initialize it with another character or a space by setting up 3 nested for loops. I'm 100 % confident that particular scenario will work. Give that a try and initialize it to stars or dashes or something so you can see the Xs falling in line over your diagram.

i changed my while loop to look like this:

while (indata != NULL)

Also i changed my array to initialize it, using a blank space, an 'X' and a 'B'. and it seems that is what is the first character that comes up when i output the data later in the program.

Also i put in a nested for loop for set the array as '*'. and put back the minus and plus 1's for the user input. and now have the 'X' falling in the spot that i was hoping to get.

now i jst need to put the 'B's,'W's and 'I's into place and right them to the file

i changed my while loop to look like this:

while (indata != NULL)

If it still works fine but my intention was something different. I'll show you what I mean when we get this other bit straightened out.

Also i changed my array to initialize it, using a blank space, an 'X' and a 'B'. and it seems that is what is the first character that comes up when i output the data later in the program.
Also i am still getting alot of spaces and then a few lines and spaces of the symbols still

Can you put up the code that you used to initialize it?

this is at the very top:

char cabin[3][4][13]={' '};
    char ch, res;
    int num, lvl=0, row=0, col=0;
    
    for(int a=0; a<3; a++)//Levels
      {
       for(int b=0; b<13; b++)//Rows
       {
        for(int c=0; c<4; c++)//Colunms
        {
            cabin[a][b][c] = '*';
        }
       }
      }

Here's a sample from one run. It doesn't seem to have booked the last entry but the first two worked:

You have booked the Cabin on Level: 1 Row: 3 Colunm: 2
****
****
****
****










****
****
***X
****










****
****
****
****










Would you like to try another cabin? Y/N

You have booked the Cabin on Level: 1 Row: 2 Colunm: 1
****
****
****
****










****
**X*
***X
****










****
****
****
****










Would you like to try another cabin? Y/N
y
Which Level Would you like to reserve? 1-3
3
Which Row Would you like to reserve? 1-13
13
Which Colunm Would you like to reserve? 1-4
4
You have booked the Cabin on Level: 2 Row: 12 Colunm: 3
****
****
****
****










****
**X*
***X
****










****
****
****
****










Would you like to try another cabin? Y/N

my out put is different to wat u are getting.
try this code i may have made small changes that got a better output

#include <iostream>
#include <fstream>
      
using std::ofstream;
using namespace std;

int main()
{
    char cabin[3][4][13]={' '};
    char ch, res;
    int num, lvl=0, row=0, col=0;
    
    for(int a=0; a<3; a++)//Levels
      {
       for(int b=0; b<13; b++)//Rows
       {
        for(int c=0; c<4; c++)//Colunms
        {
            cabin[a][b][c] = '*';
        }
       }
      }
      


      ifstream indata;
      indata.open("littleswandb.txt");
      if(!indata)
      {
                 cout << "File could not be opened" << endl;
                 system("pause");
                 return 0;
      }
      indata >> ch;
      while (indata != NULL)// keep reading until end-of-file
      { 
      num=0;
      while(num<4)
      {
          cout << ch;
          indata >> ch;
          num =num +1;
      } // sets EOF flag if no value found
      cout << endl;
      }
      indata.close();
      system("pause");
      
      cout << "Would you like to make a reservation? Y/N" << endl;
      cin >> res;
      while ((res == 'Y') || (res == 'y'))
      {
       cout << "Which Level Would you like to reserve? 1-3" << endl;
       cin >> lvl;
       cout << "Which Row Would you like to reserve? 1-13" << endl;
       cin >> row;
       cout << "Which Columm Would you like to reserve? 1-4" << endl;
       cin >> col;

      lvl = lvl -1; //Minus 1 for array
      row = row -1; //Minus 1 for array
      col = col -1; //Minus 1 for array

      if (cabin[lvl][row][col] != 'X')
      {
      cabin[lvl][row][col] = 'X';
      lvl = lvl + 1; //Plus 1 after array use
      row = row + 1; //Plus 1 after array use
      col = col + 1; //Plus 1 after array use
      cout << "You have booked the Cabin on Level: " << lvl
           << " Row: " << row
           << " Colunm: " << col << endl;
      //output the array onto the screen
      for(int a=0; a<3; a++)//Levels
      {
       for(int b=0; b<13; b++)//Rows
       {
        for(int c=0; c<4; c++)//Colunms
        {
            cout << cabin[a][b][c];
        }
        cout << endl;
       }
      cout << endl;
      }
      /*ofstream outdata("littleswandb.txt");
      for(int d=0; d<3; d++) // Levels
      {
         for(int e=0; e<13; e++) //Rows
            {
                 for(int f=0; f<4; f++) // Colunms
                 { 
                    outdata<<cabin[d][e][f]; // store array into file
                 }
                 outdata<< endl;
            }
            outdata << endl;
      }
      outdata.close();
      system("pause");*/
      }
      else
      cout << "That cabin is already booked" << endl;
      cout << "Would you like to try another cabin? Y/N" << endl;
      cin >> res;
      }
cout << "Thank you. Good bye." << endl;
system("pause");
return 0;
}

Yeah, I think I hadn't uncommented the spot where you add 1 back to all the values. Shouldn't have made a big deal. This time it adds two reservations to the ship the first time but I still don't get any junk output.

You have booked the Cabin on Level: 1 Row: 7 Colunm: 2
****
****
****
****
****
****
*X**
****
****
****
****
****
****

****
****
*X**
****
****
****
****
****
****
****
****
****
****

****
****
****
****
****
****
****
****
****
****
****
****
****

Would you like to try another cabin? Y/N
y
Which Level Would you like to reserve? 1-3
3
Which Row Would you like to reserve? 1-13
12
Which Columm Would you like to reserve? 1-4
4
You have booked the Cabin on Level: 3 Row: 12 Colunm: 4
****
****
****
****
****
****
*X**
****
****
****
****
****
****

****
****
*X**
****
****
****
****
****
****
****
****
****
****

****
****
****
****
****
****
****
****
****
****
****
***X
****

Would you like to try another cabin? Y/N

im still not sure why 'X' is coming up twice after saying where to book once

I haven't been able to find it either. I know on the test run that I just did I added a reservation at 2 4 4 and it showed up in array postion 1 3 3 like I expected but it also showed up in 0 7 3 (another run had 2 5 2 show up as 1 4 1 and 0 8 1. I'm sure you'll kick yourself when you find it...

Go back to this code:

char cabin[3][4][13]={' '};
    char ch, res;
    int num, lvl=0, row=0, col=0;
    
    for(int a=0; a<3; a++)//Levels
      {
       for(int b=0; b<13; b++)//Rows
       {
        for(int c=0; c<4; c++)//Colunms
        {
            cabin[a][b][c] = '*';
        }
       }
      }

and fix your indecies and loops. They must match, and yours do not. You have an abc confusion going on...

like this then:

char cabin[3][4][13]={' '};
    char ch, res;
    int num, lvl=0, row=0, col=0;
    
    for(int a=0; a<3; a++)//Levels
    {
       for(int b=0; b<4; b++)//Rows
       {
           for(int c=0; c<13; c++)//Colunms
           {
               cabin[a][b][c] = '*';
           }
       }
    }
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.