2D pointer Array does not cointain value in element after initialization












0














My main.cpp looks like this.



int row = 7, column = 7, size = 7, userChoice;
char typeOfUserTile;
char **boardOfGame;
int* sizeOfBoardGame = NULL;
sizeOfBoardGame = &size;

boardOfGame = new char*[row];
for (int i = 0; i < row; i++)
{
boardOfGame[i] = new char[column];
}
initializeBoardGame(boardOfGame, sizeOfBoardGame);


And my func.cpp looks like this.



#include "dtt0055HW4func.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

void initializeBoardGame(char **boardOfGame,int* sizeOfBoardGame)
{
char nameOfFile[30],c;
ifstream inFS;

cout << "Please enter the name of the input file: ";
cin >> nameOfFile;

inFS.open(nameOfFile);
if (inFS.fail())
{
while(inFS.fail())
{
cout << "Unable to open the file, please enter the name of the file again. ";
cin >> nameOfFile;
inFS.open(nameOfFile);
}
}

while (!inFS.eof())
{
for (int i = 0; i < *sizeOfBoardGame; i++)
{
for (int j = 0; j < *sizeOfBoardGame; j++)
{
inFS.get(c);
boardOfGame[i][j] = c;
cout << boardOfGame[i][j];
}
}
}
inFS.close();
}


My program will read data from a user's file, then assign each character to be the value of 2D array, then display it on the terminal. However, after display the data to the terminal, my 2D array becomes blank, it does not cointain any value at all. I try to display it using the for loop but it gives me nothing. Can you explain why?



For example, my file is: * * * * *



Then it will display in the terminal as: * * * * *



If I use the for loop to simply display it, it will give me this: ______



*_ indicates blank, nothing at all.



Another question is do you know how to insert an element in 2D pointer array and push existing element to next element. If an element is pushed out of the array boundaries, we will delete that element. For example, I have a 2D array like char **board = (5,6,7,8,9). Now I want to insert a char 'c' into the element, and my array will look like (c,5,6,7,8).



Another question is, is there any way to compare a text color in c++? I try to research this but found nothing. For example, i want to compare a value in my 2D array that is a cross '+' in red color to see if it match.



if (boardOfGame[i][j] == '+' in Red) something like this.



Here is my new code for handling the read stream.



while (row < *sizeOfBoardGame && inFS.get(c))
{
if (!isspace(c))
{
boardOfGame[row][column++] = c;
if (column == *sizeOfBoardGame)
{
column = 0;
row++;
}
}
}


Then I print the array using for loop as normal.










share|improve this question
























  • Why !.eof() inside a loop condition is always wrong. You will want to review Why is iostream::eof inside a loop condition considered wrong?
    – David C. Rankin
    Nov 21 at 0:42










  • Thank you sir, I try to fix and now my array has value in its elements. I just still dont understand the part that If i can display my array to the terminal by assigning c to the element, why cant my array keep that value to element?
    – Dat To
    Nov 21 at 0:55










  • What happens is EOF isn't set until you attempt to read after reading the final character in the file. Your read of the final character does Not set EOF (as it was a good read). However, on your next read, you encounter EOF -- but in your loop, it's to late, you hit EOF with inFS.get(c);, then you attempt to assign an unknown value for c to boardOfGame[i][j] = c; invoking Undefined Behavior - so all bets are off at that point.
    – David C. Rankin
    Nov 21 at 0:59












  • Instead, control your entire read loop with while ((inFS.get(c))) { /* now use c */ }
    – David C. Rankin
    Nov 21 at 1:02












  • I have tried three different ways to control the read loop like this: while (inFS >> c); while (inFS.get(c)); while(!(inFS >> c).eof()); These three works properly, which i means it does read a character from my file then assign that character to boardOfGame[i][j]. However, it displays terribly with a weird pattern in the terminal as one character will be displayed 49 times (my 2D array is 7 * 7). I do not know what causes this?
    – Dat To
    Nov 21 at 1:15


















0














My main.cpp looks like this.



int row = 7, column = 7, size = 7, userChoice;
char typeOfUserTile;
char **boardOfGame;
int* sizeOfBoardGame = NULL;
sizeOfBoardGame = &size;

boardOfGame = new char*[row];
for (int i = 0; i < row; i++)
{
boardOfGame[i] = new char[column];
}
initializeBoardGame(boardOfGame, sizeOfBoardGame);


And my func.cpp looks like this.



#include "dtt0055HW4func.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

void initializeBoardGame(char **boardOfGame,int* sizeOfBoardGame)
{
char nameOfFile[30],c;
ifstream inFS;

cout << "Please enter the name of the input file: ";
cin >> nameOfFile;

inFS.open(nameOfFile);
if (inFS.fail())
{
while(inFS.fail())
{
cout << "Unable to open the file, please enter the name of the file again. ";
cin >> nameOfFile;
inFS.open(nameOfFile);
}
}

while (!inFS.eof())
{
for (int i = 0; i < *sizeOfBoardGame; i++)
{
for (int j = 0; j < *sizeOfBoardGame; j++)
{
inFS.get(c);
boardOfGame[i][j] = c;
cout << boardOfGame[i][j];
}
}
}
inFS.close();
}


My program will read data from a user's file, then assign each character to be the value of 2D array, then display it on the terminal. However, after display the data to the terminal, my 2D array becomes blank, it does not cointain any value at all. I try to display it using the for loop but it gives me nothing. Can you explain why?



For example, my file is: * * * * *



Then it will display in the terminal as: * * * * *



If I use the for loop to simply display it, it will give me this: ______



*_ indicates blank, nothing at all.



Another question is do you know how to insert an element in 2D pointer array and push existing element to next element. If an element is pushed out of the array boundaries, we will delete that element. For example, I have a 2D array like char **board = (5,6,7,8,9). Now I want to insert a char 'c' into the element, and my array will look like (c,5,6,7,8).



Another question is, is there any way to compare a text color in c++? I try to research this but found nothing. For example, i want to compare a value in my 2D array that is a cross '+' in red color to see if it match.



if (boardOfGame[i][j] == '+' in Red) something like this.



Here is my new code for handling the read stream.



while (row < *sizeOfBoardGame && inFS.get(c))
{
if (!isspace(c))
{
boardOfGame[row][column++] = c;
if (column == *sizeOfBoardGame)
{
column = 0;
row++;
}
}
}


Then I print the array using for loop as normal.










share|improve this question
























  • Why !.eof() inside a loop condition is always wrong. You will want to review Why is iostream::eof inside a loop condition considered wrong?
    – David C. Rankin
    Nov 21 at 0:42










  • Thank you sir, I try to fix and now my array has value in its elements. I just still dont understand the part that If i can display my array to the terminal by assigning c to the element, why cant my array keep that value to element?
    – Dat To
    Nov 21 at 0:55










  • What happens is EOF isn't set until you attempt to read after reading the final character in the file. Your read of the final character does Not set EOF (as it was a good read). However, on your next read, you encounter EOF -- but in your loop, it's to late, you hit EOF with inFS.get(c);, then you attempt to assign an unknown value for c to boardOfGame[i][j] = c; invoking Undefined Behavior - so all bets are off at that point.
    – David C. Rankin
    Nov 21 at 0:59












  • Instead, control your entire read loop with while ((inFS.get(c))) { /* now use c */ }
    – David C. Rankin
    Nov 21 at 1:02












  • I have tried three different ways to control the read loop like this: while (inFS >> c); while (inFS.get(c)); while(!(inFS >> c).eof()); These three works properly, which i means it does read a character from my file then assign that character to boardOfGame[i][j]. However, it displays terribly with a weird pattern in the terminal as one character will be displayed 49 times (my 2D array is 7 * 7). I do not know what causes this?
    – Dat To
    Nov 21 at 1:15
















0












0








0







My main.cpp looks like this.



int row = 7, column = 7, size = 7, userChoice;
char typeOfUserTile;
char **boardOfGame;
int* sizeOfBoardGame = NULL;
sizeOfBoardGame = &size;

boardOfGame = new char*[row];
for (int i = 0; i < row; i++)
{
boardOfGame[i] = new char[column];
}
initializeBoardGame(boardOfGame, sizeOfBoardGame);


And my func.cpp looks like this.



#include "dtt0055HW4func.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

void initializeBoardGame(char **boardOfGame,int* sizeOfBoardGame)
{
char nameOfFile[30],c;
ifstream inFS;

cout << "Please enter the name of the input file: ";
cin >> nameOfFile;

inFS.open(nameOfFile);
if (inFS.fail())
{
while(inFS.fail())
{
cout << "Unable to open the file, please enter the name of the file again. ";
cin >> nameOfFile;
inFS.open(nameOfFile);
}
}

while (!inFS.eof())
{
for (int i = 0; i < *sizeOfBoardGame; i++)
{
for (int j = 0; j < *sizeOfBoardGame; j++)
{
inFS.get(c);
boardOfGame[i][j] = c;
cout << boardOfGame[i][j];
}
}
}
inFS.close();
}


My program will read data from a user's file, then assign each character to be the value of 2D array, then display it on the terminal. However, after display the data to the terminal, my 2D array becomes blank, it does not cointain any value at all. I try to display it using the for loop but it gives me nothing. Can you explain why?



For example, my file is: * * * * *



Then it will display in the terminal as: * * * * *



If I use the for loop to simply display it, it will give me this: ______



*_ indicates blank, nothing at all.



Another question is do you know how to insert an element in 2D pointer array and push existing element to next element. If an element is pushed out of the array boundaries, we will delete that element. For example, I have a 2D array like char **board = (5,6,7,8,9). Now I want to insert a char 'c' into the element, and my array will look like (c,5,6,7,8).



Another question is, is there any way to compare a text color in c++? I try to research this but found nothing. For example, i want to compare a value in my 2D array that is a cross '+' in red color to see if it match.



if (boardOfGame[i][j] == '+' in Red) something like this.



Here is my new code for handling the read stream.



while (row < *sizeOfBoardGame && inFS.get(c))
{
if (!isspace(c))
{
boardOfGame[row][column++] = c;
if (column == *sizeOfBoardGame)
{
column = 0;
row++;
}
}
}


Then I print the array using for loop as normal.










share|improve this question















My main.cpp looks like this.



int row = 7, column = 7, size = 7, userChoice;
char typeOfUserTile;
char **boardOfGame;
int* sizeOfBoardGame = NULL;
sizeOfBoardGame = &size;

boardOfGame = new char*[row];
for (int i = 0; i < row; i++)
{
boardOfGame[i] = new char[column];
}
initializeBoardGame(boardOfGame, sizeOfBoardGame);


And my func.cpp looks like this.



#include "dtt0055HW4func.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

void initializeBoardGame(char **boardOfGame,int* sizeOfBoardGame)
{
char nameOfFile[30],c;
ifstream inFS;

cout << "Please enter the name of the input file: ";
cin >> nameOfFile;

inFS.open(nameOfFile);
if (inFS.fail())
{
while(inFS.fail())
{
cout << "Unable to open the file, please enter the name of the file again. ";
cin >> nameOfFile;
inFS.open(nameOfFile);
}
}

while (!inFS.eof())
{
for (int i = 0; i < *sizeOfBoardGame; i++)
{
for (int j = 0; j < *sizeOfBoardGame; j++)
{
inFS.get(c);
boardOfGame[i][j] = c;
cout << boardOfGame[i][j];
}
}
}
inFS.close();
}


My program will read data from a user's file, then assign each character to be the value of 2D array, then display it on the terminal. However, after display the data to the terminal, my 2D array becomes blank, it does not cointain any value at all. I try to display it using the for loop but it gives me nothing. Can you explain why?



For example, my file is: * * * * *



Then it will display in the terminal as: * * * * *



If I use the for loop to simply display it, it will give me this: ______



*_ indicates blank, nothing at all.



Another question is do you know how to insert an element in 2D pointer array and push existing element to next element. If an element is pushed out of the array boundaries, we will delete that element. For example, I have a 2D array like char **board = (5,6,7,8,9). Now I want to insert a char 'c' into the element, and my array will look like (c,5,6,7,8).



Another question is, is there any way to compare a text color in c++? I try to research this but found nothing. For example, i want to compare a value in my 2D array that is a cross '+' in red color to see if it match.



if (boardOfGame[i][j] == '+' in Red) something like this.



Here is my new code for handling the read stream.



while (row < *sizeOfBoardGame && inFS.get(c))
{
if (!isspace(c))
{
boardOfGame[row][column++] = c;
if (column == *sizeOfBoardGame)
{
column = 0;
row++;
}
}
}


Then I print the array using for loop as normal.







c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 at 4:15

























asked Nov 21 at 0:39









Dat To

184




184












  • Why !.eof() inside a loop condition is always wrong. You will want to review Why is iostream::eof inside a loop condition considered wrong?
    – David C. Rankin
    Nov 21 at 0:42










  • Thank you sir, I try to fix and now my array has value in its elements. I just still dont understand the part that If i can display my array to the terminal by assigning c to the element, why cant my array keep that value to element?
    – Dat To
    Nov 21 at 0:55










  • What happens is EOF isn't set until you attempt to read after reading the final character in the file. Your read of the final character does Not set EOF (as it was a good read). However, on your next read, you encounter EOF -- but in your loop, it's to late, you hit EOF with inFS.get(c);, then you attempt to assign an unknown value for c to boardOfGame[i][j] = c; invoking Undefined Behavior - so all bets are off at that point.
    – David C. Rankin
    Nov 21 at 0:59












  • Instead, control your entire read loop with while ((inFS.get(c))) { /* now use c */ }
    – David C. Rankin
    Nov 21 at 1:02












  • I have tried three different ways to control the read loop like this: while (inFS >> c); while (inFS.get(c)); while(!(inFS >> c).eof()); These three works properly, which i means it does read a character from my file then assign that character to boardOfGame[i][j]. However, it displays terribly with a weird pattern in the terminal as one character will be displayed 49 times (my 2D array is 7 * 7). I do not know what causes this?
    – Dat To
    Nov 21 at 1:15




















  • Why !.eof() inside a loop condition is always wrong. You will want to review Why is iostream::eof inside a loop condition considered wrong?
    – David C. Rankin
    Nov 21 at 0:42










  • Thank you sir, I try to fix and now my array has value in its elements. I just still dont understand the part that If i can display my array to the terminal by assigning c to the element, why cant my array keep that value to element?
    – Dat To
    Nov 21 at 0:55










  • What happens is EOF isn't set until you attempt to read after reading the final character in the file. Your read of the final character does Not set EOF (as it was a good read). However, on your next read, you encounter EOF -- but in your loop, it's to late, you hit EOF with inFS.get(c);, then you attempt to assign an unknown value for c to boardOfGame[i][j] = c; invoking Undefined Behavior - so all bets are off at that point.
    – David C. Rankin
    Nov 21 at 0:59












  • Instead, control your entire read loop with while ((inFS.get(c))) { /* now use c */ }
    – David C. Rankin
    Nov 21 at 1:02












  • I have tried three different ways to control the read loop like this: while (inFS >> c); while (inFS.get(c)); while(!(inFS >> c).eof()); These three works properly, which i means it does read a character from my file then assign that character to boardOfGame[i][j]. However, it displays terribly with a weird pattern in the terminal as one character will be displayed 49 times (my 2D array is 7 * 7). I do not know what causes this?
    – Dat To
    Nov 21 at 1:15


















Why !.eof() inside a loop condition is always wrong. You will want to review Why is iostream::eof inside a loop condition considered wrong?
– David C. Rankin
Nov 21 at 0:42




Why !.eof() inside a loop condition is always wrong. You will want to review Why is iostream::eof inside a loop condition considered wrong?
– David C. Rankin
Nov 21 at 0:42












Thank you sir, I try to fix and now my array has value in its elements. I just still dont understand the part that If i can display my array to the terminal by assigning c to the element, why cant my array keep that value to element?
– Dat To
Nov 21 at 0:55




Thank you sir, I try to fix and now my array has value in its elements. I just still dont understand the part that If i can display my array to the terminal by assigning c to the element, why cant my array keep that value to element?
– Dat To
Nov 21 at 0:55












What happens is EOF isn't set until you attempt to read after reading the final character in the file. Your read of the final character does Not set EOF (as it was a good read). However, on your next read, you encounter EOF -- but in your loop, it's to late, you hit EOF with inFS.get(c);, then you attempt to assign an unknown value for c to boardOfGame[i][j] = c; invoking Undefined Behavior - so all bets are off at that point.
– David C. Rankin
Nov 21 at 0:59






What happens is EOF isn't set until you attempt to read after reading the final character in the file. Your read of the final character does Not set EOF (as it was a good read). However, on your next read, you encounter EOF -- but in your loop, it's to late, you hit EOF with inFS.get(c);, then you attempt to assign an unknown value for c to boardOfGame[i][j] = c; invoking Undefined Behavior - so all bets are off at that point.
– David C. Rankin
Nov 21 at 0:59














Instead, control your entire read loop with while ((inFS.get(c))) { /* now use c */ }
– David C. Rankin
Nov 21 at 1:02






Instead, control your entire read loop with while ((inFS.get(c))) { /* now use c */ }
– David C. Rankin
Nov 21 at 1:02














I have tried three different ways to control the read loop like this: while (inFS >> c); while (inFS.get(c)); while(!(inFS >> c).eof()); These three works properly, which i means it does read a character from my file then assign that character to boardOfGame[i][j]. However, it displays terribly with a weird pattern in the terminal as one character will be displayed 49 times (my 2D array is 7 * 7). I do not know what causes this?
– Dat To
Nov 21 at 1:15






I have tried three different ways to control the read loop like this: while (inFS >> c); while (inFS.get(c)); while(!(inFS >> c).eof()); These three works properly, which i means it does read a character from my file then assign that character to boardOfGame[i][j]. However, it displays terribly with a weird pattern in the terminal as one character will be displayed 49 times (my 2D array is 7 * 7). I do not know what causes this?
– Dat To
Nov 21 at 1:15














1 Answer
1






active

oldest

votes


















0














There are a number of ways to control the read loop -- however, the control must be based upon a successful read from the file. You can either use your nested loops and read, e.g.



    for (int i = 0; i < *sizeOfBoardGame; i++) {
for (int j = 0; j < *sizeOfBoardGame; j++) {
if (!(inFS.get(c)))
goto readdone;
boardOfGame[i][j] = c;
}
}
readdone:;


(note: using fixed for loops -- you cannot account for additional characters like spaces or the terminating 'n'. for loops will only execute that specific number of times regardless what the character read is. Better to use while loops and counter-variables to ensure you fill each row and column with a valid character)



Or, preferably, just control the read itself, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();


Putting it into a short example you could do:



#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) {
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Example Use/Output



$ ./bin/readboard
Please enter the name of the input file: dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Look things over and let me know if you need further help.



Update To Read X,X,X,X



Now that I understand you want to read 4 values and replace the ',' in the input file with an actual ' ' (space character) in your array, you can tweak the read loop to read each character, if the character is !isspace(c) then store the character, if c == ',' then store a space, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}


Since you are storing a space between each X (or character value) in your array, when you want to insert a character and move the existing column values to the right, you must move the column values by 2 instead of just shifting by 1 to account for the space that is stored before the value, e.g. (to insert the letter 'c' as the new first value in the array at boardOfGame[0][0], you could do:



    memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';


Putting that altogether in an example (and printing with an additional space between columns), you could do:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < BRDSZ; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7-2.txt
5,9,3,7
2,6,2,1
1,9,0,9
2,1,7,3
6,1,6,3
1,7,3,8
3,0,6,4


Example Use/Output



$ ./bin/readboard2
Please enter the name of the input file: dat/board_7x7-2.txt
5 9 3 7
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4

c 5 9 3
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4


Reading from File with Unequal Rows



If I understand now and your data file looks similar to:



Example Input File



$ cat dat/board_7x7-3.txt
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X


And, your job is to read the X values storing them in a 2D array with spaces stored between the X values, then you will need to pass a pointer to either int or size_t as a parameter to your function so that it can be updated with the number of rows actually stored (since the rows containing all commas contain no values). The approach to reading is essentially the same, accept this time you will determine when valid data is read and if it is not the 1st column, you will add a space before it in your array, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}


The complete example with the additional pointer parameter added and the number of rows filled updated within the function is:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};
int nrows = BRDSZ;

initializeBoardGame (boardOfGame, &nrows);

for (int i = 0; i < nrows; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < nrows; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows)
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ)
*nrows = row;
}


Example Use/Output



$ ./bin/readboard3
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X
X X X X
X X X X
X X X X

c X X X
X X X X
X X X X
X X X X


If this is not what you intend, the post the exact output you expect so I will know what your intent is regarding input lines that are all commas.



Last But Not Least



What this all boils down to is that your separators change between odd and even rows. This is a fairly ridiculous case, but it has educational value in helping you think through reading data with varying states of input.



When your rows are odd, your file is a comma-separated file. When you rows are even your file is a space-separated file. The simplest and most efficient test of whether an integer value (like row in the code) is odd or even is simply to test if the 1-bit is set (e.g. row & 1 == 0 is row is even and row & 1 == 1 row is odd)



So you simply swap which separator you are looking for based on whether your row is odd or even, e.g.



    while (row < BRDSZ && inFS.get(c)) {    /* protect row bounds, read c */
if (col < BRDSZ) { /* protect col bounds */
if ((row & 1) == 0) { /* even no. row */
if (c != ',' && c != 'n') /* separator is ',' */
boardOfGame[row][col++] = c; /* assign c */
}
else { /* odd no. row */
if (!isspace(c) && c != 'n') { /* seperator is ' ' */
if (c == ',') /* if c ',' save ' ' */
boardOfGame[row][col++] = ' ';
else /* otherwise, use c */
boardOfGame[row][col++] = c;
}
}
}
if (c == 'n') { /* when newline reached */
col = 0; /* reset values, increment row */
row++;
}
}
inFS.close();


When you substitute this read into the last example, you end up with:



Example Use/Output



$ ./bin/readboard4
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X

X X X X

X X X X

X X X X


c X X X

X X X X

X X X X

X X X X


Now having gone though this multiple ways, you should be picking up on the fact that reading data character by character is a simple matter of:




  1. testing the character "What do I have?";

  2. handling the character based on your needs, e.g. "What do I do with it?"; and


  3. never forget to account for your line-ending characters (e.g. 'n') also being read as part of your read loop.



    If you think of it that way, you should be able to sort it all out.








share|improve this answer























  • Thank you so much for your help! I'm be able to control the array right now. However, it will not display the same in the terminal as in the original file. It will print 7 rows, but only 5 columns for each row instead of 7, it not display like your example. Do you perhaps know how to fix it ? What does it mean when you use the if(!isspace(c)) to check whether it is a space or not? In my case, I must include the space. For example my file is: X, ,X, ,X, ,X - It prints: X, ,X, ,X
    – Dat To
    Nov 21 at 2:09










  • You don't read the space into your array. You only store characters. You handle the space in the output by including one in the output, e.g. as in cout << " " << boardOfGame[i][j];. I suspect that is where your column problem is partially coming from. Edit your question and add (but do not delete your original code) your new code to your question and I'll take a look.
    – David C. Rankin
    Nov 21 at 2:20












  • Dear David, I just add my new code in the original post, can you please take a look again? Thanks.
    – Dat To
    Nov 21 at 4:43










  • Your new code looks fine, but using the pointer sizeOfBoardGame is a bit "weird". For inserting 'c' in your array and pushing the other values one to the right in a row, since you are effectively using a 2D array, you will simply want to memmove the values to the right. Example to insert 'c' at boardOfGame[0][0] you would memmove (&boardOfGame[0][1], &boardOfGame[0][0], 6); boardOfGame[0][0] = 'c'; (you can also do the same thing with a simple for loop beginning at col = 1 and setting current column = column - 1)
    – David C. Rankin
    Nov 21 at 4:52












  • Dear David, If i change the condition of if(isspace) to if(c != ',') then it will print only X X X X with proper space. However, it stop at the fourth row first column. For example, I will have a total of 7 row, in each row there will be an X for each column with space between each X for a total of 4 X and 3 spaces. Then if I run the code, it only display until reach boardOfGame[6][0] and stop, missing total 6 elements for the last row.
    – Dat To
    Nov 21 at 5:28











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403718%2f2d-pointer-array-does-not-cointain-value-in-element-after-initialization%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














There are a number of ways to control the read loop -- however, the control must be based upon a successful read from the file. You can either use your nested loops and read, e.g.



    for (int i = 0; i < *sizeOfBoardGame; i++) {
for (int j = 0; j < *sizeOfBoardGame; j++) {
if (!(inFS.get(c)))
goto readdone;
boardOfGame[i][j] = c;
}
}
readdone:;


(note: using fixed for loops -- you cannot account for additional characters like spaces or the terminating 'n'. for loops will only execute that specific number of times regardless what the character read is. Better to use while loops and counter-variables to ensure you fill each row and column with a valid character)



Or, preferably, just control the read itself, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();


Putting it into a short example you could do:



#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) {
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Example Use/Output



$ ./bin/readboard
Please enter the name of the input file: dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Look things over and let me know if you need further help.



Update To Read X,X,X,X



Now that I understand you want to read 4 values and replace the ',' in the input file with an actual ' ' (space character) in your array, you can tweak the read loop to read each character, if the character is !isspace(c) then store the character, if c == ',' then store a space, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}


Since you are storing a space between each X (or character value) in your array, when you want to insert a character and move the existing column values to the right, you must move the column values by 2 instead of just shifting by 1 to account for the space that is stored before the value, e.g. (to insert the letter 'c' as the new first value in the array at boardOfGame[0][0], you could do:



    memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';


Putting that altogether in an example (and printing with an additional space between columns), you could do:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < BRDSZ; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7-2.txt
5,9,3,7
2,6,2,1
1,9,0,9
2,1,7,3
6,1,6,3
1,7,3,8
3,0,6,4


Example Use/Output



$ ./bin/readboard2
Please enter the name of the input file: dat/board_7x7-2.txt
5 9 3 7
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4

c 5 9 3
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4


Reading from File with Unequal Rows



If I understand now and your data file looks similar to:



Example Input File



$ cat dat/board_7x7-3.txt
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X


And, your job is to read the X values storing them in a 2D array with spaces stored between the X values, then you will need to pass a pointer to either int or size_t as a parameter to your function so that it can be updated with the number of rows actually stored (since the rows containing all commas contain no values). The approach to reading is essentially the same, accept this time you will determine when valid data is read and if it is not the 1st column, you will add a space before it in your array, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}


The complete example with the additional pointer parameter added and the number of rows filled updated within the function is:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};
int nrows = BRDSZ;

initializeBoardGame (boardOfGame, &nrows);

for (int i = 0; i < nrows; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < nrows; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows)
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ)
*nrows = row;
}


Example Use/Output



$ ./bin/readboard3
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X
X X X X
X X X X
X X X X

c X X X
X X X X
X X X X
X X X X


If this is not what you intend, the post the exact output you expect so I will know what your intent is regarding input lines that are all commas.



Last But Not Least



What this all boils down to is that your separators change between odd and even rows. This is a fairly ridiculous case, but it has educational value in helping you think through reading data with varying states of input.



When your rows are odd, your file is a comma-separated file. When you rows are even your file is a space-separated file. The simplest and most efficient test of whether an integer value (like row in the code) is odd or even is simply to test if the 1-bit is set (e.g. row & 1 == 0 is row is even and row & 1 == 1 row is odd)



So you simply swap which separator you are looking for based on whether your row is odd or even, e.g.



    while (row < BRDSZ && inFS.get(c)) {    /* protect row bounds, read c */
if (col < BRDSZ) { /* protect col bounds */
if ((row & 1) == 0) { /* even no. row */
if (c != ',' && c != 'n') /* separator is ',' */
boardOfGame[row][col++] = c; /* assign c */
}
else { /* odd no. row */
if (!isspace(c) && c != 'n') { /* seperator is ' ' */
if (c == ',') /* if c ',' save ' ' */
boardOfGame[row][col++] = ' ';
else /* otherwise, use c */
boardOfGame[row][col++] = c;
}
}
}
if (c == 'n') { /* when newline reached */
col = 0; /* reset values, increment row */
row++;
}
}
inFS.close();


When you substitute this read into the last example, you end up with:



Example Use/Output



$ ./bin/readboard4
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X

X X X X

X X X X

X X X X


c X X X

X X X X

X X X X

X X X X


Now having gone though this multiple ways, you should be picking up on the fact that reading data character by character is a simple matter of:




  1. testing the character "What do I have?";

  2. handling the character based on your needs, e.g. "What do I do with it?"; and


  3. never forget to account for your line-ending characters (e.g. 'n') also being read as part of your read loop.



    If you think of it that way, you should be able to sort it all out.








share|improve this answer























  • Thank you so much for your help! I'm be able to control the array right now. However, it will not display the same in the terminal as in the original file. It will print 7 rows, but only 5 columns for each row instead of 7, it not display like your example. Do you perhaps know how to fix it ? What does it mean when you use the if(!isspace(c)) to check whether it is a space or not? In my case, I must include the space. For example my file is: X, ,X, ,X, ,X - It prints: X, ,X, ,X
    – Dat To
    Nov 21 at 2:09










  • You don't read the space into your array. You only store characters. You handle the space in the output by including one in the output, e.g. as in cout << " " << boardOfGame[i][j];. I suspect that is where your column problem is partially coming from. Edit your question and add (but do not delete your original code) your new code to your question and I'll take a look.
    – David C. Rankin
    Nov 21 at 2:20












  • Dear David, I just add my new code in the original post, can you please take a look again? Thanks.
    – Dat To
    Nov 21 at 4:43










  • Your new code looks fine, but using the pointer sizeOfBoardGame is a bit "weird". For inserting 'c' in your array and pushing the other values one to the right in a row, since you are effectively using a 2D array, you will simply want to memmove the values to the right. Example to insert 'c' at boardOfGame[0][0] you would memmove (&boardOfGame[0][1], &boardOfGame[0][0], 6); boardOfGame[0][0] = 'c'; (you can also do the same thing with a simple for loop beginning at col = 1 and setting current column = column - 1)
    – David C. Rankin
    Nov 21 at 4:52












  • Dear David, If i change the condition of if(isspace) to if(c != ',') then it will print only X X X X with proper space. However, it stop at the fourth row first column. For example, I will have a total of 7 row, in each row there will be an X for each column with space between each X for a total of 4 X and 3 spaces. Then if I run the code, it only display until reach boardOfGame[6][0] and stop, missing total 6 elements for the last row.
    – Dat To
    Nov 21 at 5:28
















0














There are a number of ways to control the read loop -- however, the control must be based upon a successful read from the file. You can either use your nested loops and read, e.g.



    for (int i = 0; i < *sizeOfBoardGame; i++) {
for (int j = 0; j < *sizeOfBoardGame; j++) {
if (!(inFS.get(c)))
goto readdone;
boardOfGame[i][j] = c;
}
}
readdone:;


(note: using fixed for loops -- you cannot account for additional characters like spaces or the terminating 'n'. for loops will only execute that specific number of times regardless what the character read is. Better to use while loops and counter-variables to ensure you fill each row and column with a valid character)



Or, preferably, just control the read itself, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();


Putting it into a short example you could do:



#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) {
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Example Use/Output



$ ./bin/readboard
Please enter the name of the input file: dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Look things over and let me know if you need further help.



Update To Read X,X,X,X



Now that I understand you want to read 4 values and replace the ',' in the input file with an actual ' ' (space character) in your array, you can tweak the read loop to read each character, if the character is !isspace(c) then store the character, if c == ',' then store a space, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}


Since you are storing a space between each X (or character value) in your array, when you want to insert a character and move the existing column values to the right, you must move the column values by 2 instead of just shifting by 1 to account for the space that is stored before the value, e.g. (to insert the letter 'c' as the new first value in the array at boardOfGame[0][0], you could do:



    memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';


Putting that altogether in an example (and printing with an additional space between columns), you could do:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < BRDSZ; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7-2.txt
5,9,3,7
2,6,2,1
1,9,0,9
2,1,7,3
6,1,6,3
1,7,3,8
3,0,6,4


Example Use/Output



$ ./bin/readboard2
Please enter the name of the input file: dat/board_7x7-2.txt
5 9 3 7
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4

c 5 9 3
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4


Reading from File with Unequal Rows



If I understand now and your data file looks similar to:



Example Input File



$ cat dat/board_7x7-3.txt
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X


And, your job is to read the X values storing them in a 2D array with spaces stored between the X values, then you will need to pass a pointer to either int or size_t as a parameter to your function so that it can be updated with the number of rows actually stored (since the rows containing all commas contain no values). The approach to reading is essentially the same, accept this time you will determine when valid data is read and if it is not the 1st column, you will add a space before it in your array, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}


The complete example with the additional pointer parameter added and the number of rows filled updated within the function is:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};
int nrows = BRDSZ;

initializeBoardGame (boardOfGame, &nrows);

for (int i = 0; i < nrows; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < nrows; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows)
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ)
*nrows = row;
}


Example Use/Output



$ ./bin/readboard3
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X
X X X X
X X X X
X X X X

c X X X
X X X X
X X X X
X X X X


If this is not what you intend, the post the exact output you expect so I will know what your intent is regarding input lines that are all commas.



Last But Not Least



What this all boils down to is that your separators change between odd and even rows. This is a fairly ridiculous case, but it has educational value in helping you think through reading data with varying states of input.



When your rows are odd, your file is a comma-separated file. When you rows are even your file is a space-separated file. The simplest and most efficient test of whether an integer value (like row in the code) is odd or even is simply to test if the 1-bit is set (e.g. row & 1 == 0 is row is even and row & 1 == 1 row is odd)



So you simply swap which separator you are looking for based on whether your row is odd or even, e.g.



    while (row < BRDSZ && inFS.get(c)) {    /* protect row bounds, read c */
if (col < BRDSZ) { /* protect col bounds */
if ((row & 1) == 0) { /* even no. row */
if (c != ',' && c != 'n') /* separator is ',' */
boardOfGame[row][col++] = c; /* assign c */
}
else { /* odd no. row */
if (!isspace(c) && c != 'n') { /* seperator is ' ' */
if (c == ',') /* if c ',' save ' ' */
boardOfGame[row][col++] = ' ';
else /* otherwise, use c */
boardOfGame[row][col++] = c;
}
}
}
if (c == 'n') { /* when newline reached */
col = 0; /* reset values, increment row */
row++;
}
}
inFS.close();


When you substitute this read into the last example, you end up with:



Example Use/Output



$ ./bin/readboard4
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X

X X X X

X X X X

X X X X


c X X X

X X X X

X X X X

X X X X


Now having gone though this multiple ways, you should be picking up on the fact that reading data character by character is a simple matter of:




  1. testing the character "What do I have?";

  2. handling the character based on your needs, e.g. "What do I do with it?"; and


  3. never forget to account for your line-ending characters (e.g. 'n') also being read as part of your read loop.



    If you think of it that way, you should be able to sort it all out.








share|improve this answer























  • Thank you so much for your help! I'm be able to control the array right now. However, it will not display the same in the terminal as in the original file. It will print 7 rows, but only 5 columns for each row instead of 7, it not display like your example. Do you perhaps know how to fix it ? What does it mean when you use the if(!isspace(c)) to check whether it is a space or not? In my case, I must include the space. For example my file is: X, ,X, ,X, ,X - It prints: X, ,X, ,X
    – Dat To
    Nov 21 at 2:09










  • You don't read the space into your array. You only store characters. You handle the space in the output by including one in the output, e.g. as in cout << " " << boardOfGame[i][j];. I suspect that is where your column problem is partially coming from. Edit your question and add (but do not delete your original code) your new code to your question and I'll take a look.
    – David C. Rankin
    Nov 21 at 2:20












  • Dear David, I just add my new code in the original post, can you please take a look again? Thanks.
    – Dat To
    Nov 21 at 4:43










  • Your new code looks fine, but using the pointer sizeOfBoardGame is a bit "weird". For inserting 'c' in your array and pushing the other values one to the right in a row, since you are effectively using a 2D array, you will simply want to memmove the values to the right. Example to insert 'c' at boardOfGame[0][0] you would memmove (&boardOfGame[0][1], &boardOfGame[0][0], 6); boardOfGame[0][0] = 'c'; (you can also do the same thing with a simple for loop beginning at col = 1 and setting current column = column - 1)
    – David C. Rankin
    Nov 21 at 4:52












  • Dear David, If i change the condition of if(isspace) to if(c != ',') then it will print only X X X X with proper space. However, it stop at the fourth row first column. For example, I will have a total of 7 row, in each row there will be an X for each column with space between each X for a total of 4 X and 3 spaces. Then if I run the code, it only display until reach boardOfGame[6][0] and stop, missing total 6 elements for the last row.
    – Dat To
    Nov 21 at 5:28














0












0








0






There are a number of ways to control the read loop -- however, the control must be based upon a successful read from the file. You can either use your nested loops and read, e.g.



    for (int i = 0; i < *sizeOfBoardGame; i++) {
for (int j = 0; j < *sizeOfBoardGame; j++) {
if (!(inFS.get(c)))
goto readdone;
boardOfGame[i][j] = c;
}
}
readdone:;


(note: using fixed for loops -- you cannot account for additional characters like spaces or the terminating 'n'. for loops will only execute that specific number of times regardless what the character read is. Better to use while loops and counter-variables to ensure you fill each row and column with a valid character)



Or, preferably, just control the read itself, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();


Putting it into a short example you could do:



#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) {
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Example Use/Output



$ ./bin/readboard
Please enter the name of the input file: dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Look things over and let me know if you need further help.



Update To Read X,X,X,X



Now that I understand you want to read 4 values and replace the ',' in the input file with an actual ' ' (space character) in your array, you can tweak the read loop to read each character, if the character is !isspace(c) then store the character, if c == ',' then store a space, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}


Since you are storing a space between each X (or character value) in your array, when you want to insert a character and move the existing column values to the right, you must move the column values by 2 instead of just shifting by 1 to account for the space that is stored before the value, e.g. (to insert the letter 'c' as the new first value in the array at boardOfGame[0][0], you could do:



    memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';


Putting that altogether in an example (and printing with an additional space between columns), you could do:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < BRDSZ; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7-2.txt
5,9,3,7
2,6,2,1
1,9,0,9
2,1,7,3
6,1,6,3
1,7,3,8
3,0,6,4


Example Use/Output



$ ./bin/readboard2
Please enter the name of the input file: dat/board_7x7-2.txt
5 9 3 7
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4

c 5 9 3
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4


Reading from File with Unequal Rows



If I understand now and your data file looks similar to:



Example Input File



$ cat dat/board_7x7-3.txt
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X


And, your job is to read the X values storing them in a 2D array with spaces stored between the X values, then you will need to pass a pointer to either int or size_t as a parameter to your function so that it can be updated with the number of rows actually stored (since the rows containing all commas contain no values). The approach to reading is essentially the same, accept this time you will determine when valid data is read and if it is not the 1st column, you will add a space before it in your array, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}


The complete example with the additional pointer parameter added and the number of rows filled updated within the function is:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};
int nrows = BRDSZ;

initializeBoardGame (boardOfGame, &nrows);

for (int i = 0; i < nrows; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < nrows; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows)
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ)
*nrows = row;
}


Example Use/Output



$ ./bin/readboard3
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X
X X X X
X X X X
X X X X

c X X X
X X X X
X X X X
X X X X


If this is not what you intend, the post the exact output you expect so I will know what your intent is regarding input lines that are all commas.



Last But Not Least



What this all boils down to is that your separators change between odd and even rows. This is a fairly ridiculous case, but it has educational value in helping you think through reading data with varying states of input.



When your rows are odd, your file is a comma-separated file. When you rows are even your file is a space-separated file. The simplest and most efficient test of whether an integer value (like row in the code) is odd or even is simply to test if the 1-bit is set (e.g. row & 1 == 0 is row is even and row & 1 == 1 row is odd)



So you simply swap which separator you are looking for based on whether your row is odd or even, e.g.



    while (row < BRDSZ && inFS.get(c)) {    /* protect row bounds, read c */
if (col < BRDSZ) { /* protect col bounds */
if ((row & 1) == 0) { /* even no. row */
if (c != ',' && c != 'n') /* separator is ',' */
boardOfGame[row][col++] = c; /* assign c */
}
else { /* odd no. row */
if (!isspace(c) && c != 'n') { /* seperator is ' ' */
if (c == ',') /* if c ',' save ' ' */
boardOfGame[row][col++] = ' ';
else /* otherwise, use c */
boardOfGame[row][col++] = c;
}
}
}
if (c == 'n') { /* when newline reached */
col = 0; /* reset values, increment row */
row++;
}
}
inFS.close();


When you substitute this read into the last example, you end up with:



Example Use/Output



$ ./bin/readboard4
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X

X X X X

X X X X

X X X X


c X X X

X X X X

X X X X

X X X X


Now having gone though this multiple ways, you should be picking up on the fact that reading data character by character is a simple matter of:




  1. testing the character "What do I have?";

  2. handling the character based on your needs, e.g. "What do I do with it?"; and


  3. never forget to account for your line-ending characters (e.g. 'n') also being read as part of your read loop.



    If you think of it that way, you should be able to sort it all out.








share|improve this answer














There are a number of ways to control the read loop -- however, the control must be based upon a successful read from the file. You can either use your nested loops and read, e.g.



    for (int i = 0; i < *sizeOfBoardGame; i++) {
for (int j = 0; j < *sizeOfBoardGame; j++) {
if (!(inFS.get(c)))
goto readdone;
boardOfGame[i][j] = c;
}
}
readdone:;


(note: using fixed for loops -- you cannot account for additional characters like spaces or the terminating 'n'. for loops will only execute that specific number of times regardless what the character read is. Better to use while loops and counter-variables to ensure you fill each row and column with a valid character)



Or, preferably, just control the read itself, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();


Putting it into a short example you could do:



#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) {
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (!isspace (c)) {
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Example Use/Output



$ ./bin/readboard
Please enter the name of the input file: dat/board_7x7.txt
1 6 7 0 4 2 1
2 1 1 2 4 4 9
5 7 9 4 1 5 1
1 6 8 1 1 4 4
2 7 0 7 0 2 9
6 5 8 3 0 0 1
2 5 6 7 4 1 3


Look things over and let me know if you need further help.



Update To Read X,X,X,X



Now that I understand you want to read 4 values and replace the ',' in the input file with an actual ' ' (space character) in your array, you can tweak the read loop to read each character, if the character is !isspace(c) then store the character, if c == ',' then store a space, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}


Since you are storing a space between each X (or character value) in your array, when you want to insert a character and move the existing column values to the right, you must move the column values by 2 instead of just shifting by 1 to account for the space that is stored before the value, e.g. (to insert the letter 'c' as the new first value in the array at boardOfGame[0][0], you could do:



    memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';


Putting that altogether in an example (and printing with an additional space between columns), you could do:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ]);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};

initializeBoardGame (boardOfGame);

for (int i = 0; i < BRDSZ; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < BRDSZ; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << " " << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ])
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if (c == ',')
boardOfGame[row][col++] = ' ';
else if (!isspace(c))
boardOfGame[row][col++] = c;
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ) {
cerr << "error: insufficient values read from file.n";
exit (EXIT_FAILURE);
}
}


Example Input File



$ cat dat/board_7x7-2.txt
5,9,3,7
2,6,2,1
1,9,0,9
2,1,7,3
6,1,6,3
1,7,3,8
3,0,6,4


Example Use/Output



$ ./bin/readboard2
Please enter the name of the input file: dat/board_7x7-2.txt
5 9 3 7
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4

c 5 9 3
2 6 2 1
1 9 0 9
2 1 7 3
6 1 6 3
1 7 3 8
3 0 6 4


Reading from File with Unequal Rows



If I understand now and your data file looks similar to:



Example Input File



$ cat dat/board_7x7-3.txt
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X
, , , , , , ,
X, ,X, ,X, ,X


And, your job is to read the X values storing them in a 2D array with spaces stored between the X values, then you will need to pass a pointer to either int or size_t as a parameter to your function so that it can be updated with the number of rows actually stored (since the rows containing all commas contain no values). The approach to reading is essentially the same, accept this time you will determine when valid data is read and if it is not the 1st column, you will add a space before it in your array, e.g.



    while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}


The complete example with the additional pointer parameter added and the number of rows filled updated within the function is:



#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using namespace std;

#define BRDSZ 7 /* if you need constants, #define them */
#define MAXFN 1024

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows);

int main (void) {
char boardOfGame[BRDSZ][BRDSZ] = {{0}};
int nrows = BRDSZ;

initializeBoardGame (boardOfGame, &nrows);

for (int i = 0; i < nrows; i++) { /* output original values */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}
cout << 'n';

/* insert 'c' at boardOfGame[0][0] - shif existing right */
memmove (&boardOfGame[0][2], &boardOfGame[0][0], BRDSZ - 2);
boardOfGame[0][0] = 'c';
boardOfGame[0][1] = ' ';

for (int i = 0; i < nrows; i++) { /* output with new value */
for (int j = 0; j < BRDSZ; j++)
cout << boardOfGame[i][j];
cout << 'n';
}

}

void initializeBoardGame (char (*boardOfGame)[BRDSZ], int *nrows)
{
char nameOfFile[MAXFN],
c;
int row = 0,
col = 0;
ifstream inFS;

cout << "Please enter the name of the input file: ";
if (!(cin >> nameOfFile)) {
cerr << "error: invalid filename entryn";
exit (EXIT_FAILURE);
}

inFS.open (nameOfFile);
if (!(inFS.is_open())) {
cerr << "error: file open failed '" << nameOfFile << "'.n";
exit (EXIT_FAILURE);
}

while (row < BRDSZ && inFS.get(c)) {
if ((!isspace(c) && c != ',')) { /* read store only values */
if (col) /* if not 1st, store ' ' */
boardOfGame[row][col++] = ' ';
boardOfGame[row][col++] = c;
}
if (col == BRDSZ) {
col = 0;
row++;
}
}
inFS.close();

if (row != BRDSZ)
*nrows = row;
}


Example Use/Output



$ ./bin/readboard3
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X
X X X X
X X X X
X X X X

c X X X
X X X X
X X X X
X X X X


If this is not what you intend, the post the exact output you expect so I will know what your intent is regarding input lines that are all commas.



Last But Not Least



What this all boils down to is that your separators change between odd and even rows. This is a fairly ridiculous case, but it has educational value in helping you think through reading data with varying states of input.



When your rows are odd, your file is a comma-separated file. When you rows are even your file is a space-separated file. The simplest and most efficient test of whether an integer value (like row in the code) is odd or even is simply to test if the 1-bit is set (e.g. row & 1 == 0 is row is even and row & 1 == 1 row is odd)



So you simply swap which separator you are looking for based on whether your row is odd or even, e.g.



    while (row < BRDSZ && inFS.get(c)) {    /* protect row bounds, read c */
if (col < BRDSZ) { /* protect col bounds */
if ((row & 1) == 0) { /* even no. row */
if (c != ',' && c != 'n') /* separator is ',' */
boardOfGame[row][col++] = c; /* assign c */
}
else { /* odd no. row */
if (!isspace(c) && c != 'n') { /* seperator is ' ' */
if (c == ',') /* if c ',' save ' ' */
boardOfGame[row][col++] = ' ';
else /* otherwise, use c */
boardOfGame[row][col++] = c;
}
}
}
if (c == 'n') { /* when newline reached */
col = 0; /* reset values, increment row */
row++;
}
}
inFS.close();


When you substitute this read into the last example, you end up with:



Example Use/Output



$ ./bin/readboard4
Please enter the name of the input file: dat/board_7x7-3.txt
X X X X

X X X X

X X X X

X X X X


c X X X

X X X X

X X X X

X X X X


Now having gone though this multiple ways, you should be picking up on the fact that reading data character by character is a simple matter of:




  1. testing the character "What do I have?";

  2. handling the character based on your needs, e.g. "What do I do with it?"; and


  3. never forget to account for your line-ending characters (e.g. 'n') also being read as part of your read loop.



    If you think of it that way, you should be able to sort it all out.









share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 at 1:53

























answered Nov 21 at 1:44









David C. Rankin

40.1k32647




40.1k32647












  • Thank you so much for your help! I'm be able to control the array right now. However, it will not display the same in the terminal as in the original file. It will print 7 rows, but only 5 columns for each row instead of 7, it not display like your example. Do you perhaps know how to fix it ? What does it mean when you use the if(!isspace(c)) to check whether it is a space or not? In my case, I must include the space. For example my file is: X, ,X, ,X, ,X - It prints: X, ,X, ,X
    – Dat To
    Nov 21 at 2:09










  • You don't read the space into your array. You only store characters. You handle the space in the output by including one in the output, e.g. as in cout << " " << boardOfGame[i][j];. I suspect that is where your column problem is partially coming from. Edit your question and add (but do not delete your original code) your new code to your question and I'll take a look.
    – David C. Rankin
    Nov 21 at 2:20












  • Dear David, I just add my new code in the original post, can you please take a look again? Thanks.
    – Dat To
    Nov 21 at 4:43










  • Your new code looks fine, but using the pointer sizeOfBoardGame is a bit "weird". For inserting 'c' in your array and pushing the other values one to the right in a row, since you are effectively using a 2D array, you will simply want to memmove the values to the right. Example to insert 'c' at boardOfGame[0][0] you would memmove (&boardOfGame[0][1], &boardOfGame[0][0], 6); boardOfGame[0][0] = 'c'; (you can also do the same thing with a simple for loop beginning at col = 1 and setting current column = column - 1)
    – David C. Rankin
    Nov 21 at 4:52












  • Dear David, If i change the condition of if(isspace) to if(c != ',') then it will print only X X X X with proper space. However, it stop at the fourth row first column. For example, I will have a total of 7 row, in each row there will be an X for each column with space between each X for a total of 4 X and 3 spaces. Then if I run the code, it only display until reach boardOfGame[6][0] and stop, missing total 6 elements for the last row.
    – Dat To
    Nov 21 at 5:28


















  • Thank you so much for your help! I'm be able to control the array right now. However, it will not display the same in the terminal as in the original file. It will print 7 rows, but only 5 columns for each row instead of 7, it not display like your example. Do you perhaps know how to fix it ? What does it mean when you use the if(!isspace(c)) to check whether it is a space or not? In my case, I must include the space. For example my file is: X, ,X, ,X, ,X - It prints: X, ,X, ,X
    – Dat To
    Nov 21 at 2:09










  • You don't read the space into your array. You only store characters. You handle the space in the output by including one in the output, e.g. as in cout << " " << boardOfGame[i][j];. I suspect that is where your column problem is partially coming from. Edit your question and add (but do not delete your original code) your new code to your question and I'll take a look.
    – David C. Rankin
    Nov 21 at 2:20












  • Dear David, I just add my new code in the original post, can you please take a look again? Thanks.
    – Dat To
    Nov 21 at 4:43










  • Your new code looks fine, but using the pointer sizeOfBoardGame is a bit "weird". For inserting 'c' in your array and pushing the other values one to the right in a row, since you are effectively using a 2D array, you will simply want to memmove the values to the right. Example to insert 'c' at boardOfGame[0][0] you would memmove (&boardOfGame[0][1], &boardOfGame[0][0], 6); boardOfGame[0][0] = 'c'; (you can also do the same thing with a simple for loop beginning at col = 1 and setting current column = column - 1)
    – David C. Rankin
    Nov 21 at 4:52












  • Dear David, If i change the condition of if(isspace) to if(c != ',') then it will print only X X X X with proper space. However, it stop at the fourth row first column. For example, I will have a total of 7 row, in each row there will be an X for each column with space between each X for a total of 4 X and 3 spaces. Then if I run the code, it only display until reach boardOfGame[6][0] and stop, missing total 6 elements for the last row.
    – Dat To
    Nov 21 at 5:28
















Thank you so much for your help! I'm be able to control the array right now. However, it will not display the same in the terminal as in the original file. It will print 7 rows, but only 5 columns for each row instead of 7, it not display like your example. Do you perhaps know how to fix it ? What does it mean when you use the if(!isspace(c)) to check whether it is a space or not? In my case, I must include the space. For example my file is: X, ,X, ,X, ,X - It prints: X, ,X, ,X
– Dat To
Nov 21 at 2:09




Thank you so much for your help! I'm be able to control the array right now. However, it will not display the same in the terminal as in the original file. It will print 7 rows, but only 5 columns for each row instead of 7, it not display like your example. Do you perhaps know how to fix it ? What does it mean when you use the if(!isspace(c)) to check whether it is a space or not? In my case, I must include the space. For example my file is: X, ,X, ,X, ,X - It prints: X, ,X, ,X
– Dat To
Nov 21 at 2:09












You don't read the space into your array. You only store characters. You handle the space in the output by including one in the output, e.g. as in cout << " " << boardOfGame[i][j];. I suspect that is where your column problem is partially coming from. Edit your question and add (but do not delete your original code) your new code to your question and I'll take a look.
– David C. Rankin
Nov 21 at 2:20






You don't read the space into your array. You only store characters. You handle the space in the output by including one in the output, e.g. as in cout << " " << boardOfGame[i][j];. I suspect that is where your column problem is partially coming from. Edit your question and add (but do not delete your original code) your new code to your question and I'll take a look.
– David C. Rankin
Nov 21 at 2:20














Dear David, I just add my new code in the original post, can you please take a look again? Thanks.
– Dat To
Nov 21 at 4:43




Dear David, I just add my new code in the original post, can you please take a look again? Thanks.
– Dat To
Nov 21 at 4:43












Your new code looks fine, but using the pointer sizeOfBoardGame is a bit "weird". For inserting 'c' in your array and pushing the other values one to the right in a row, since you are effectively using a 2D array, you will simply want to memmove the values to the right. Example to insert 'c' at boardOfGame[0][0] you would memmove (&boardOfGame[0][1], &boardOfGame[0][0], 6); boardOfGame[0][0] = 'c'; (you can also do the same thing with a simple for loop beginning at col = 1 and setting current column = column - 1)
– David C. Rankin
Nov 21 at 4:52






Your new code looks fine, but using the pointer sizeOfBoardGame is a bit "weird". For inserting 'c' in your array and pushing the other values one to the right in a row, since you are effectively using a 2D array, you will simply want to memmove the values to the right. Example to insert 'c' at boardOfGame[0][0] you would memmove (&boardOfGame[0][1], &boardOfGame[0][0], 6); boardOfGame[0][0] = 'c'; (you can also do the same thing with a simple for loop beginning at col = 1 and setting current column = column - 1)
– David C. Rankin
Nov 21 at 4:52














Dear David, If i change the condition of if(isspace) to if(c != ',') then it will print only X X X X with proper space. However, it stop at the fourth row first column. For example, I will have a total of 7 row, in each row there will be an X for each column with space between each X for a total of 4 X and 3 spaces. Then if I run the code, it only display until reach boardOfGame[6][0] and stop, missing total 6 elements for the last row.
– Dat To
Nov 21 at 5:28




Dear David, If i change the condition of if(isspace) to if(c != ',') then it will print only X X X X with proper space. However, it stop at the fourth row first column. For example, I will have a total of 7 row, in each row there will be an X for each column with space between each X for a total of 4 X and 3 spaces. Then if I run the code, it only display until reach boardOfGame[6][0] and stop, missing total 6 elements for the last row.
– Dat To
Nov 21 at 5:28


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403718%2f2d-pointer-array-does-not-cointain-value-in-element-after-initialization%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

TypeError: fit_transform() missing 1 required positional argument: 'X'