如何用用户的输入填充2D数组?

4
我是新手,想知道我是否可以在 Stack Overflow 上得到有关我的 C++ 代码的帮助。
我想用用户的输入填充我的二维数组,例如:
  • 请输入 16 个字符:(abcdabcdabcdabcd)
输出一个 4x4 的网格,其中填充着用户的输入,在这种情况下是 (abcdabcdabcdabcd)。
a b c d
a b c d 
a b c d
a b c d

到目前为止,我的进展如下:

#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
我猜你遇到了问题,否则你就不会在这里问问题了。我建议添加描述问题的细节。 - user4581301
2
看起来你在 if (direction = 1) 这行代码中打错了字。你可能想要写成 if (direction == 1),这样才能进行比较而不是赋值。 - user4581301
1
看起来他们的问题是关于 grid [row][col] = userInput[IDK what to put here]; 的。 - Tas
好眼力,Tas。row * LG_GRID + col - user4581301
是的,抱歉,应该提到的。 - Epic Dehaan
请提供一个最小、完整和可验证的示例:有关帮助,请使用此链接:https://stackoverflow.com/help/mcve。`doCommand()`是什么?它在哪里声明和定义,以及谁调用了你所问的两个函数?`LG_GRID`在哪里和如何声明-定义? - Francis Cugler
3个回答

1
在您的fillLgArray函数中,您提到了:当索引用户输入字符串时,您不知道该放什么,实际上有一种公式可以将1D数组索引作为2D数组来处理。这个公式有两种变体,一种是行-列主要,另一种是列-行主要。在您的特定情况下,如果用户从控制台输入以下内容:
abcdabcdabcdabcd

你可以相信,std::string 很像 std::vector,只不过 std::string 将其内容存储为 char_type 并具有用于字符串操作的特殊成员函数,除此之外,std::string 在核心上基本上是 std::vector 的一个专业版本。这两个容器都来自于 stl,它们都是包装在动态内存中分配的连续块上的。这些容器围绕着一个 type [size] 数组进行包装,并且它们可以动态增长。

因此,我们可以将控制台文本"abcdabcdabcdabcd"视为字符的一维数组,如下所示:

 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]

当您遍历双重循环以索引2D数组时,每次迭代都必须在脑海中跟随循环。
在C语言(如C和C ++)中,使用一维数组的索引来表示二维数组的行主序,因此公式如下:
for ( row = 0; row < 4; row++ ) {
    for ( col = 0; col < 4; col ++ ) {
        2darray[row][col] = 1darray[(row * row_size or width) + col];
    }
}

这个问题已经在这里得到了回答!将2D数组映射到1D
以下是您代码的工作示例,包括最小化、完整性和可验证性:
#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;
}

使用您描述的输入:"abcdabcdabcdabcd",此程序在控制台上的输出为:

Please enter 16 characters
abcdabcdabcdabcd
You entered abcdabcdabcabcd
a b c d
a b c d
a b c d
a b c d

1
谢谢您的解释,先生,还有感谢您提供的资源 :D - Epic Dehaan
@EpicDehaan 如果这有帮助到您,请不要忘记点赞! - Francis Cugler

0

看到你的“IDK what to put here”这一行,你应该使用charAt。像这样:

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

你想获取用户输入的字符,位置为0、1、2、3、4、5...等等


听起来不错,但我能说服你用LG_GRID代替4吗?[魔术数字是不好的。](https://dev59.com/7XVD5IYBdhLWcg3wOo5h) - user4581301
有趣的是,当我尝试运行它时,它就会崩溃,你有什么想法为什么会这样吗? - Epic Dehaan
你输入了16个字符吗?userInput.length()>=16 - Tas
1
@EpicDehaan 惊讶于你能够做到这一步。LG_GRIDdoCommand都没有被定义。 - user4581301
我没有放上完整的代码,因为我想要更具体的指示,但是doCommand是用来提示用户向前或向后的,我应该把完整的代码放上去吗? - Epic Dehaan
显示剩余2条评论

-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
这个答案存在的问题:仅有代码的答案往往会产生空洞编程。请添加一些解释说明你做了什么以及为什么它会解决提问者的问题。这个答案看起来会一遍又一遍地打印出前四个字符。它不会加载网格,也不会正确地打印需要放入网格中的内容。在次要方面,所使用的语言看起来更像是C++/CLI,而不是标准C++。 - user4581301

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接