Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I am working with vectors and I wanna know how I can print the empty spaces in between until the line ends.
void print_vector(const std::vector < int > & v, int print_cols, int col_width) {
//dash
cout << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
//printing the vector in formated output
cout << "|";
for (size_t x = 0; x < v.size(); x++) {
cout << right << setw(col_width) << v[x] << " |";
//prints new line if it reaches limit of numbers per line
if ((x + 1) % print_cols == 0) cout << endl << "|";
}
//dash
cout << endl << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
}
this is my current output: my output so far and sorry I can't embed images yet it wont let me.
But this is the output that I want output needed
void print_vector(const std::vector < int > & v, int print_cols, int col_width) {
//dash
cout << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
//printing the vector in formated output
cout << "|";
size_t x = 0;
for (x = 0; x < v.size(); x++) {
cout << right << setw(col_width) << v[x] << " |";
//prints new line if it reaches limit of numbers per line
if (x < v.size() - 1) {
if ((x + 1) % print_cols == 0) {
cout << endl << "|";
}
}
}
size_t remain = print_cols - (x % print_cols);
for (size_t i = 0; (remain != print_cols) && i < remain; ++i) {
cout << right << setw(col_width) << " " << " |";
}
//dash
cout << endl << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
}
Sample outputs:
-------------------------------------------------
| 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 |
| 9 | | | |
-------------------------------------------------
-------------------------------------
| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |
-------------------------------------
You can add an extra loop after the one you have and before the bottom row of dashes:
The loop would print a given number of blank columns.
The number of blank columns can be computed as print_cols - v.size() % print_cols.
The loop should not be executed if the number of blank columns is equal to the total number of columns. That would print a full row of empty columns. That case happens when the vector you want to print has a number of elements that is an exact multiple of the number of columns.
Every iteration of the loop should print col_width + 1 blanks and a '|' (or if you prefer it, to make it more consistent with your other code, col_width blanks plus a " |").
Yet you should fix another issue with your code:
The check for reaching the end of the row (enabling the print of a new line and a '|') should be instead a check for starting a row.
If you do it at the end, for the case when the last element of the vector goes in the last column, you will unnecessarily add a new row.
Doing it at the beginning, since you know you have at least one more number to show, you can print "\n|" and then the number.
The check x % print_cols == 0 will tell you if x is the index of the first element of a row.
[Demo]
#include <iomanip> // setw
#include <iostream> // cout
#include <numeric> // iota
#include <string>
#include <vector>
void print_vector(const std::vector<int>& v, int print_cols, int col_width) {
// dash
std::cout << std::string(print_cols * (col_width + 2) + 1, '-');
// printing the vector in formated output
for (size_t x = 0; x < v.size(); x++) {
// prints new line if it is the first element of the line
if (x % print_cols == 0) {
std::cout << "\n|";
}
std::cout << std::right << std::setw(col_width) << v[x] << " |";
}
// prints last empty columns
if (int number_of_blank_columns = print_cols - v.size() % print_cols;
number_of_blank_columns != print_cols) {
for (int x = 0; x < number_of_blank_columns; x++) {
std::cout << std::string(col_width + 1, ' ') << "|";
}
}
// dash
std::cout << "\n" << std::string(print_cols * (col_width + 2) + 1, '-') << "\n";
}
int main() {
{
std::vector<int> v(8);
std::iota(std::begin(v), std::end(v), 100);
print_vector(v, 5, 4);
}
std::cout << "\n";
{
std::vector<int> v(10);
std::iota(std::begin(v), std::end(v), 100);
print_vector(v, 5, 4);
}
}
// Outputs:
//
// -------------------------------
// | 100 | 101 | 102 | 103 | 104 |
// | 105 | 106 | 107 | | |
// -------------------------------
//
// -------------------------------
// | 100 | 101 | 102 | 103 | 104 |
// | 105 | 106 | 107 | 108 | 109 |
// -------------------------------
Very sorry if this is too long-- I posted a question yesterday about a game program I am trying to write and with the help of some people, I managed to figure everything out pretty quickly.
The very large majority of the program is complete, but I have one last weird task to complete. I have a function written, printGrid, that prints one random element from each 16 bundles of characters from within a char array. For example (It's very ugly-- please excuse my beginner code):
char gameZero[outer_size][inner_size] = {
{'A','A','C','I','O','T'}, {'A','H','M','O','R','S'},
{'E','G','K','L','U','Y'}, {'A','B','I','L','T','Y'}, {'A','C','D','E','M','P'},
{'E','G','I','N','T','V'}, {'G','I','L','R','U','W'}, {'E','L','P','S','T','U'},
{'D','E','N','O','S','W'}, {'A','C','E','L','R','S'}, {'A','B','J','M','O','Q'},
{'E','E','F','H','I','Y'}, {'E','H','I','N','P','S'}, {'D','K','N','O','T','U'},
{'A','D','E','N','V','Z'}, {'B','I','F','O','R','X'}
};
void printGrid() {
mt19937 gen(time(nullptr));
uniform_int_distribution<int> random_inner(0, inner_size - 1);
int n = random_inner(gen);
cout << "+---+---+---+---+\n";
for (int i = 0; i < 4; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 4; i < 8; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 8; i < 12; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 12; i < 16; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
}
This will print a 4x4 game board for the user to see. I am now trying to write a sort of toString function, which takes the random numbers generated in printGrid and prints them out into a single line string with no spaces. The issue I am trying to wrap my head around is, I have this assortment of characters that changes each time the player begins a new game. These 16 characters are coming from a set array of 16 die, holding 6 characters each. Is the only way to make this possible to store these new randomly chosen characters into an empty array so the user can simply print them with the toString function when desired? Another obstacle I would have to then tackle is deleting the array every time the user wants to begin again. If this is the case, could I store them in a vector and use something like vector::clear to solve that?
Current output of printGrid function:
+---+---+---+---+
| T | M | E | L |
+---+---+---+---+
| A | V | L | S |
+---+---+---+---+
| E | A | Qu| F |
+---+---+---+---+
| E | D | N | O |
+---+---+---+---+
Desired output of toString function I would like to create:
TMELAVLSEAQuFEDNO
Very sorry if this is too much to read or too confusing- I've been working on this almost all day and my brain is a bit fried at the moment. Any tips are greatly appreciated!
You have the logic to select the characters, example:
for (int i = 0; i < 4; i++)
cout << "| " << gameZero[i][n] << " ";
You could use std::string and operator += to append the characters to a string:
std::string all_letters;
for (int i = 0; i < 4; ++i)
{
all_letters += gameZero[i][n];
}
Edit 1: Expanding the loop
Since you don't need to print by row, you can iterate through the entire array:
std::string all_letters;
for (int i = 0; i < 16; ++i)
{
all_letters += gameZero[i][n];
}
I want to print a game board grid which will vary in size depending on what the user inputs. I also wanted to know would it be best or even be possible to make this same grid using an array or would I need some type of 2d array of some sort?
void printGrid(int &userRows, int &userColumns){
cout << "Enter the number of rows -> ";
cin >> userRows;
cout << "Enter the number of columns -> ";
cin >> userColumns;
for(int i = 0; i < userColumns; i++){
cout << "|";
for(int y = 0; y < userRows; y++){
cout << "-";
}
}
}
I got the nested loop part down pat. Just having an issue telling it to print a new line and to spawn one after the other. Thank you
Here is the final product I am going for
I got the nested loop part down pat. Just having an issue telling it to print a new line and to spawn one after the other.
Are you sure? That doesn't seem to produce anything close to the final product I am going for?
While that may produce "|" and "-" output, it ignores the column headings, the header separator, the row labels, the footer separator and the column footer.
In answer to the newline part of your question, you have two options, you can either output a newline with the macro endl or you can output a literal newline "\n". If you have declared using namespace std;, you can simply use the cout << endl; or cout << "\n";. otherwise you need to explicitly specify the std namespace, e.g. std::cout << endl; or std::cout << "\n";
To finish building your output with column heading, separators, row labels, footer separator and footer, just take it piece-by-piece. For example for your column headings, you could simply loop over your columns, outputting your loop counter + 1 with appropriate spacings:
for (int i = 0; i < cols; i++) /* output column headings */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n";
(note: the use of the if (!i) (equivalent to if (i == 0)) to handle the first-column spacing separately)
For your heading separator, you could loop over the columns again, in like manner with the same check handling the first column differently.
for (int i = 0; i < cols; i++) /* output header separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
Then the actual grid sections requires row-labels both before, and after, each row of the grid is output. Here you simply add a nested loop to loop over each row, but otherwise use a similar loop over each column with first row check, followed by a final output of the closing row-label for each row:
for (int i = 0; i < rows; i++) { /* output labeled grid rows */
for (int j = 0; j < cols; j++)
if (!j)
std::cout << (char)('A' + i) << " | |";
else
std::cout << " |";
std::cout << " " << (char)('A' + i) << "\n";
}
Finally, you just repeat what you did for the column headers and header separator in reverse order for your footer separator and footer, outputting the separator row first followed by the column footers, e.g.
for (int i = 0; i < cols; i++) /* output footer separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
for (int i = 0; i < cols; i++) /* output column footer */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n"; /* tidy up with new line */
That's pretty much it. You can throw together a short example using a class board to hold the rows and cols values and a constructor and a couple of member functions to update or request input for new row/column values, e.g. the following just outputs your 4x6 grid, then prompts for new rows and cols values, and finally output a 5x7 example:
#include <iostream>
class board {
int rows, cols;
public:
board() {};
board (int x, int y) { rows = x; cols = y; }
void prngrid ();
void setsize (int x, int y) { rows = x; cols = y; }
void setsize ();
};
void board::prngrid ()
{
std::cout << "\n"; /* output new line before grid */
for (int i = 0; i < cols; i++) /* output column headings */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n";
for (int i = 0; i < cols; i++) /* output header separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
for (int i = 0; i < rows; i++) { /* output labeled grid rows */
for (int j = 0; j < cols; j++)
if (!j)
std::cout << (char)('A' + i) << " | |";
else
std::cout << " |";
std::cout << " " << (char)('A' + i) << "\n";
}
for (int i = 0; i < cols; i++) /* output footer separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
for (int i = 0; i < cols; i++) /* output column footer */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n"; /* tidy up with new line */
}
void board::setsize ()
{
std::cout << "\nenter the number of rows -> ";
std::cin >> rows;
std::cout << "enter the number of cols -> ";
std::cin >> cols;
}
int main (void) {
board board1 (4, 6);
board1.prngrid();
board1.setsize();
board1.prngrid();
board1.setsize (5,7);
board1.prngrid();
return 0;
}
(note: you should add validation checks that rows and cols values are non-negative (or choose an unsigned type), and also check that they are reasonable for your screen output (e.g. less than 20 or so and at least 26 or less or you will run out of upper-case letters). Those checks, and adjustments for multi-digit headings, are left to you)
Example Use/Output
$ ./bin/board_grid
1 2 3 4 5 6
--- --- --- --- --- ---
A | | | | | | | A
B | | | | | | | B
C | | | | | | | C
D | | | | | | | D
--- --- --- --- --- ---
1 2 3 4 5 6
enter the number of rows -> 5
enter the number of cols -> 5
1 2 3 4 5
--- --- --- --- ---
A | | | | | | A
B | | | | | | B
C | | | | | | C
D | | | | | | D
E | | | | | | E
--- --- --- --- ---
1 2 3 4 5
1 2 3 4 5 6 7
--- --- --- --- --- --- ---
A | | | | | | | | A
B | | | | | | | | B
C | | | | | | | | C
D | | | | | | | | D
E | | | | | | | | E
--- --- --- --- --- --- ---
1 2 3 4 5 6 7
Look things over and let me know if you have further questions.
The problem is fairly easy, just understand the pattern! Here's the working code with live example.
#include <iostream>
using namespace std;
void printGrid(int &userRows, int &userColumns){
cout<<endl;
cout<<" ";
int i=1,j;
for(j = 0; j <= 4*userColumns; j++){
if(j%4==2)
cout<<i++;
else cout<<" ";
}
cout<<endl;
for(i = 0; i <= 2*userRows; i++){
if(i%2!=0)
cout<<(char)(i/2 +'A');
for(j = 0; j <= 2*userColumns; j++){
if(i%2==0)
{
if(j==0)
cout<<" ";
if(j%2==0)
cout<<" ";
else cout<<"---";
}
else{
if(j%2==0)
cout<<"|";
else cout<<" ";
}
}
if(i%2!=0)
cout<<(char)(i/2 +'A');
cout<<endl;
}
cout<<" ";
for(j = 0, i = 1; j <= 4*userColumns; j++){
if(j%4==2)
cout<<i++;
else cout<<" ";
}
cout<<endl;
}
int main() {
int userRows, userColumns;
cout << "Enter the number of rows -> ";
cin >> userRows;
cout << "Enter the number of columns -> ";
cin >> userColumns;
printGrid(userRows, userColumns);
return 0;
}
Live Code
Output:
Enter the number of rows -> 4
Enter the number of columns -> 6
1 2 3 4 5 6
--- --- --- --- --- ---
A| | | | | | |A
--- --- --- --- --- ---
B| | | | | | |B
--- --- --- --- --- ---
C| | | | | | |C
--- --- --- --- --- ---
D| | | | | | |D
--- --- --- --- --- ---
1 2 3 4 5 6
By adding the cout << endl; after the userRows for-loop has finish the process it will proceed with the next line until i < userColumns
for(int i = 0; i < userColumns; i++){
cout << "|";
for(int y = 0; y < userRows; y++){
cout << "-";
}
cout << endl; //end of every-line
}
When you say:
make this same grid using an array
I'm guessing you are asking how to handle values you can use to populate the grid. There are lots of ways to store a variable number of values. Here are a few (I'm assuming the values are of type char):
One dimensional std::vector
std::vector<char> gridValues;
gridValues.resize(userColumns * userRows);
Then, inside the for loops:
cout << gridValues.at( i + y*userColumns );
Two dimensional std::vector
std::vector<std::vector<char>> gridValues;
gridValues.resize(userRows);
for( int i = 0; i < userRows; ++i )
gridValues.at(i).resize(userColumns);
Then, inside the for loops:
cout << gridValues.at( y ).at( i );
One dimensional array
char* gridValues = new char[ userColumns*userRows ];
Then, inside the for loops:
cout << gridValues[ i + y*userColumns ];
Two dimensional array
char** gridValues = new char[ userRows ];
for( int i = 0; i < userRows; ++i )
gridValues[i] = new char[ userColumns ];
Then, inside the for loops:
cout << gridValues[ y ][ i ];
I would use the one-dimensional std::vector, because it's simple to setup and I don't have to worry about forgetting to delete the pointers at the end.
As a note, you may want to check you for loops. With userColumns = 3 and userRows = 2, the code you gave will print: |--|--|--. The variables are being used backwards.
Once you fix the order of the loops, JaxLee's answer will help you put the newline in the right spot.
I am currently learning C++, and I wanted to manually input values to a vector of strings, processing each character before storing it. This is the code I used:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int i, height = 5, width = 5;
vector<string> lab;
lab.resize(height, "");
string s;
//For input reference
cout << endl << "Input data:" << endl << "01234" << endl;
//Input values
for (i = 0; i < height; i++)
{
getline (cin, s);
for (int j = 0; j < width; j++)
{
//Process char [...]
lab[i][j] = s.at(j);
}
}
//Show Matrix
cout << endl << endl;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
cout << lab[i][j] << " ";
}
cout << endl;
}
//Show Addresses
cout << endl << endl;
for (int i = 0; i < height; i++)
{
cout << "String Addr: " << (void*) &lab[i] << " | Chars Addr: ";
for (int j = 0; j < width; j++)
{
//cout << lab[i][j] << " ";
cout << (void*) &lab[i][j] << " ";
}
cout << endl;
}
cout << endl;
return 0;
}
The problem was that the characters inside the strings have the same address (I don't know why). Here is an example of one execution of the program:
Input data:
01234
aaaaa
bbbbb
ccccc
ddddd
abcde
a b c d e
a b c d e
a b c d e
a b c d e
a b c d e
String Addr: 0x8fe8008 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610
String Addr: 0x8fe800c | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610
String Addr: 0x8fe8010 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610
String Addr: 0x8fe8014 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610
String Addr: 0x8fe8018 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610
At the end you can see that the addresses of the chars are the same, while the ones for the strings are different. The final matrix in the example should have been:
a a a a a
b b b b b
c c c c c
d d d d d
a b c d e
But instead, it is:
a b c d e
a b c d e
a b c d e
a b c d e
a b c d e
While I already solved the problem, using the += operator instead of assigning using [], I still don't know exactly what hapened with the code above. Why does the chars have the same reference?
You are going out of bounds on your assignments:
lab[i][j] = s.at(j);
lab[i] is valid but lab[i][j] for any j is out of bounds, because all the strings in your vector were initialized to "", an empty string.
The problem is that although you've resized the vector you have not resized any of the strings inside it, they are all still zero length. So when you do
lab[i][j] = s.at(j);
you are accessing outside of the bounds of the string at lab[i].
This should work
for (int j = 0; j < width; j++)
{
//Process char [...]
lab[i].push_back(s.at(j));
}
This version adds each char to the string as it's processed.
This code is invalid
//Input values
for (i = 0; i < height; i++)
{
getline (cin, s);
for (int j = 0; j < width; j++)
{
//Process char [...]
lab[i][j] = s.at(j);
}
}
Each string of the vector is empty so you may not access its elements by the subscript operator.
Avoid working on separater characters in string. You havent event set the size before calling operator[] on your string, it does not even work when I check with g++/mingw.
This line is bad:
lab[i][j] = s.at(j);
lab[i] as not been constructed with a size, so it is not required to be able to contains anything.
Use (without the j for loop):
lab[i] = s;
Or even better:
//Input values
for (i = 0; i < height; i++)
{
getline (cin, lab[i]);
}
This is may code for 2D array. I will using it for Battleship game.
I want to ask, if its necessary to use a dynamic memory because I have two 2D array. Also I want to ask if anyone can tell my how to improve or fix my code
I'm not sure that I used the Class correct, but its my first time
enter code here
#include <iostream>
#include<array>
#include <string>
#include <stdlib.h>
#include <vector>
using namespace std;
class Board {
public:
int grid[15][15];
int initBoard(int A, int B)
{
int grid[A][B];
for(int col=0; col<A; col++) //Outer column loop
{
for(int row=0; row<B; row++) //Inner row loop
{
grid[col][row]=0;
}
}
}
void printBoard(int A, int B)
{
if (B == 10){
cout<<endl;
cout<<" ---{WELCOME TO THE BATTLESHIP}---\n"<<endl;
cout << " 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |" << endl << endl;
}
else if (B == 15){
cout<<endl;
cout<<" ---{WELCOME TO THE BATTLESHIP}---\n"<<endl;
cout << " 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12| 13| 14|" << endl << endl;
}
for(int i=0; i<A; i++) //column loop
{
for(int j=0; j<B; j++) //row loop
{
if(j==0)
{
if(i<=9){
cout << i << " " ; //print row number and spaces before new row
}
else if(i>=10){
cout << i << " " ;
}
}
grid[i][j]=0;
cout << grid[i][j] ;
if(j <= B)
{
cout << " | ";
}
}
cout << endl; //new line at end of column
}
cout << endl;
}
}:
int main(){
system("clear");
cout<<endl;
cout<<"***------GAME MENU------***"<<endl<<endl;
int b;
string name;
string surname;
cout<<" Choose Difficulty\n\n"<<" 1 for Easy\n"<<" 2 for
Hard\n"<<endl;
cout<<"***---------------------***"<<endl<<endl;
cout<<"Enter your name: ";
cin>>name;
cout<<"Enter your surname: ";
cin>>surname;
cout<<"Enter your choice -->";
cin>>b;
system("clear");
if (b==1){
Board easy;
easy.initBoard(10,10);
easy.printBoard(10,10);
cout<<endl;
}
else if(b==2){
Board hard;
hard.initBoard(15,15);
hard.printBoard(15,15);
cout<<endl;
}
return 0;
}
if its necessary to use a dynamic memory because I have two 2D array.
On my system, Ubuntu 17.10, each thread stack size is 8 MB (default). You need to figure out your per thread auto-var size, and if your grid is smaller, and enough size is left for max depth function calls, you will not need to use dynamic memory.
Generally, I would not resist using dynamic memory.
Because I have 2D array
The dimensionality has no impact. The grid (made with std::array) takes a fixed number of bytes, and the elements are back to back.