4

I am new to Stack overflow and I am wondering if I can get help regarding my C++ code.

I want to fill my 2D array with the users input, for example:

  • Please Enter 16 characters: (abcdabcdabcdabcd)

Outputs a 4x4 grid that is filled with user's input in this case its (abcdabcdabcdabcd).

a b c d
a b c d 
a b c d
a b c d

Here is my progress up till now:

#include <iostream>
#include <stdlib.h>

using namespace std;

//Constants
const int SM_GRID = 3;
const int LG_GRID = 4;
const char FILL_1 = 'X';
const char FILL_2 = 'O';
const int FORWARD = 1;
const int REVERSE = 2;
const int MAXLEN = 128;

//displays an overview of the program
void displayOverview();

//fills a small array with x's and o's
void fillSmallArray(char grid[][SM_GRID]);

//prompts the user for characters, and fills a 4x4 array with them
//either fills it from top to bottom, left to right (if direction is 1)
//or bottom to top, right to left (if direction is 2)
void fillLgArray(char grid[][LG_GRID], int direction);

//outputs the small array
void outputSmallArray(char grid[][SM_GRID]);

//outputs the large array
void outputLgArray(char grid[][LG_GRID]);

//prompts for a command, and calls the appropriate function based on it
//returns true if command was valid
bool doCommand(char grid[][LG_GRID]);


int main(){

  //Overview of the program
  displayOverview();

  //set up arrays
  char myGrid[SM_GRID][SM_GRID];
  fillSmallArray (myGrid);
  outputSmallArray(myGrid);

  //declare a large array
  //declare variable: Play or Not?
  //As long as user wants to play
  //call doCommand
  char myGrid1[LG_GRID][LG_GRID];
  doCommand (myGrid1);

    //fill the small array and output it

    //fill the large array and output it, as many times as the user wants
    //1 for forward, 2 for reverse, any other character ends the game

return 0;
}


//displays an overview of the program
void displayOverview(){
  cout << "Welcome to my grid-o-matic game !! :)\n"
  << "Here is your small grid: \n";

}


//fills a small array with x's and o's
void fillSmallArray(char grid[][SM_GRID]){
  //logic: if both row and col are even, or both odd, put in a X
  //otherwise put in a O
  //loop through the grid put in a X or O as above
  for (int row = 0; row < SM_GRID; row++){
    for(int col = 0; col < SM_GRID; col++){
      if((row %2) == (col%2)){
grid [row][col] = FILL_1;
      }else{
grid [row][col] = FILL_2;
      }//if else
    }//inner for
  }//outer for
}//function



//prompts the user for characters, and fills a 4x4 array with them
//either fills it from top to bottom, left to right (if direction is 1)
//or bottom to top, right to left (if direction is 2)

void fillLgArray(char grid[][LG_GRID], int direction){


    string userInput;

    cout << "Please enter 16 characters!\n";
    cin >> userInput;

    if(userInput.length() > 16){

        userInput = userInput.substr(0, 16);
    }

    cout << "You entered " << userInput << endl;

    for (int row = 0; row < LG_GRID; row++){
        for (int col = 0; col < LG_GRID; row++){
                grid [row][col] = userInput.at(col+row*LG_GRID);
        }
    }
}//Function


//outputs the small array
void outputSmallArray(char grid[][SM_GRID]){

  for (int row=0;row <SM_GRID;row++){
    for(int col=0;col <SM_GRID;col++){
      cout << grid[row][col]<<" ";
    }
    cout << endl;
  }
}


//outputs the large array
void outputLgArray(char grid[][LG_GRID]){

    for (int row=0;row <LG_GRID;row++){
    for(int col=0;col <LG_GRID;col++){
      cout << grid[row][col]<<" ";
    }
    cout << endl;
  }
}


//prompts for a command, and calls the appropriate function based on it
//returns true if command was valid
bool doCommand(char grid[][LG_GRID]){

  bool valid = true;

  char input [MAXLEN];
  int command;

  cout << "Please enter 1 for FORWARDS or 2 for reverse!\n";
  cin.getline(input,MAXLEN);

  command = atoi(input);
  switch (command){
  case FORWARD:
    cout << "Going Forwards !!!\n";
    fillLgArray(grid,command);

    outputLgArray(grid);
    break;

  case REVERSE:
    cout << "Going backwards !!\n";
    fillLgArray(grid, command);

    outputLgArray(grid);
    break;

  default:
    return false;
  }
 return valid;
}
  • 2
    I assume you are having a problem or you wouldn't be asking a question here. I recommend adding details describing the problem. – user4581301 Nov 12 '18 at 04:25
  • 2
    It looks like you have a typo at `if (direction = 1)`. You probably mean `if (direction == 1)` to get a comparison rather than an assignment. – user4581301 Nov 12 '18 at 04:28
  • 1
    It looks like their question is regarding `grid [row][col] = userInput[IDK what to put here];` – Tas Nov 12 '18 at 04:31
  • Good eyes, Tas. `row * LG_GRID + col`. – user4581301 Nov 12 '18 at 04:33
  • Yes, sorry, should have mentioned it yes – Epic Dehaan Nov 12 '18 at 04:34
  • Please provide a Minimal, Complete and Verifiable example: for help on that please use this link: https://stackoverflow.com/help/mcve. What is `doCommand()`? Where is it declared and defined, and what is calling your two functions in question? Where and how is `LG_GRID` declared - defined? – Francis Cugler Nov 12 '18 at 04:53

3 Answers3

1

In your fillLgArray function where you stated: You didn't know what to put for indexing into the user input string, there is a formula for indexing a 1D array to treat it as a 2D array. There are two variations for this formula one is for Row - Colum major and the other is for Col - Row major. In your particular situation if the user enters this from the console:

abcdabcdabcdabcd

You can count on the fact that std::string is very much like std::vector only that std::string stores its contents as char_type and has special member functions for working with string manipulation other than that std::string at the core is basically a specialized version of std::vector. Both of these containers from the stl are wrappers around a contiguous block of memory that it allocates into dynamic memory. These containers wrap around a type [size] array and they grow dynamically.

So knowing this we can treat the text from the console "abcdabcdabcdabcd" as an 1D array of characters like this:

 0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
[a] [b] [c] [d] [a] [b] [c] [d] [a] [b] [c] [d] [a] [b] [c] [d]

So when you are traversing a double for loop to index into a 2D array you have to mentally step through the loop on each iteration.

In C languages such as C & C++ the indexing of a flat 1D array to represent a 2D array is Row-Major so the formula is as follows:

for ( row = 0; row < 4; row++ ) {
    for ( col = 0; col < 4; col ++ ) {
        2darray[row][col] = 1darray[(row * row_size or width) + col];
    }
}

This has already been asked and answered here! Map a 2D array onto a 1D

Here is a working example of your code in a minimal, complete verifiable example:

#include <string>
#include <iostream>
#include <exception>

#define LG_GRID = 4;

void fillArray( char grid[][LG_GRID] ) {
    std::string userInput;
    std::cout << "Please enter 16 characters\n";
    std::cin >> userInput;

    if( userInput.length() < 16 )
        throw std::runtime_error( "Not enough characters" );
    if( userInput.length() > 16 )
        userInput = userInput.substr( 0, 16 );

    std::cout << "You entered " << userInput << '\n';

    for( int row = 0; row < LG_GRID; row++ ) {
        for( int col = 0; col < LG_GRID; col++ ) {
            // grid[row][col] = userInput[row * LG_GRID + col];
            grid[row][col] = userInput.at( row * LG_GRID + col );
            // both lines above will work however `string.at()` will throw an out of range exception.
        }
    }
}

void displayArray( char grid[][LG_GRID] ) {
    for( int row = 0; row < LG_GRID; row++ ) {
        for( int col = 0; col < LG_GRID; col++ ) {
            std::cout << grid[row][col] << " ";
        }
        std::cout << '\n';
    }
}

int main() {
    try {
        char myGrid[LG_GRID][LG_GRID];
        fillArray( myGrid );
        displayArray( myGrid );    

    } catch( const std::runtime_error& e ) {
        std::cerr << e.what() << '\n';
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

And using the input you described: "abcdabcdabcdabcd" The output on the console to this program is:

Please enter 16 characters
abcdabcdabcdabcd
You entered abcdabcdabcabcd
a b c d
a b c d
a b c d
a b c d
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
0

Looking at your "IDK what to put here" line, you should probably use charAt. Something like:

grid [row][col] = userInput.at(col+row*4);

You want the character at user's input, spot 0, 1, 2, 3, 4, 5...etc

  • Looks good, but can I talk you into replacing `4` with `LG_GRID`? [Magic numbers are bad.](https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad) – user4581301 Nov 12 '18 at 04:35
  • Interesting, when I try to run it, it just crashes, any idea why? – Epic Dehaan Nov 12 '18 at 04:39
  • Have you entered 16 characters? Does `userInput.length()>=16`? – Tas Nov 12 '18 at 04:42
  • 1
    @EpicDehaan amazed you're getting that far. `LG_GRID` isn't defined and neither is `doCommand ` – user4581301 Nov 12 '18 at 04:50
  • I did not put my full code because I want to be specific, but doCommand is to prompt the user to go forward or backward, show I put my full code up? – Epic Dehaan Nov 12 '18 at 04:57
  • I have entered 16 characters yes, but now I am getting terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::at: __n (which is 8) >= this->size() (which is 8) – Epic Dehaan Nov 12 '18 at 04:57
  • @user4581301 Good call. You're probably not getting a 16 char String when you substring it. Set userInput to some 16-char long test value to verify this is the issue. – AardvarkBlue Nov 12 '18 at 05:43
-1
     String inputString = "abcdabcdabcdabcd";
     inputString = inputString.substring(0, 16);
     char[] inputChar = inputString.toCharArray();
     for (int i = 0; i < 4; i++) {
         String printRow = "";
        for (int j = 0; j < 4; j++) {
            printRow = printRow + inputChar[j];
        }
        System.out.println(printRow);
    }
  • 1
    Problems with this answer: Code only answers have an annoying tendency to produce [Cargo Cult Programmers](https://en.wikipedia.org/wiki/Cargo_cult_programming). Please add some explanation of what you've done and why it will solve the asker's problem. This answer looks like it will print out the first four characters over and over again. I will not load the grid, nor will it print what needs to go into the grid correctly. On the minor front, the language used looks like C++/CLI, not Standard C++. – user4581301 Nov 12 '18 at 06:43