How to store random number in usigned char variable in c++? - c++

I am wanting to fill a unsigned char 2d array with random 8 bit hex numbers using rand(). But I am getting weird results(seen below) when I try to save them in my array. It works fine if I change the 2d array to an int array, but I really wanna keep unsigned char so I know only numbers that are 8 bit can be saved into each index. Here is the code I was testing on:
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
unsigned char key[4][4];
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
key[x][y] = (rand() % 256);
cout << hex << setfill('0') << setw(2) << key[x][y] << " | ";
}
cout << endl;
}
}
Is there any solution to this? Or is there a better way to fill my 2d array with random 8bit numbers?
To clarify weird results, this is what I get:
0┘ | 0☻ | 0| | 0┌ |
0L | 0ä | 0⌐ | 0ä |
0☺ | 0î | 0X | 0Y |
0▬ | 0╧ | 0# | 0╩ |

Need to cast key[x][y] as int or unsigned, for example:
cout << hex << setfill('0') << setw(2) << (unsigned)key[x][y] << " | ";
or
cout << hex << setfill('0') << setw(2) << int(key[x][y]) << " | ";
As answered by John and Tadman

Related

How can I print the empty spaces with " | | " until the line ends [closed]

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 |
// -------------------------------

toString function from 2D array

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];
}

Most efficient possible code for printing a specific board C++

So I am trying to print a board exactly like this with the multidimensional array
char score[10][10] = {' '};
a b c d e f g h i j
+-------------------+
0| |
1| |
2| |
3| |
4| |
5| |
6| |
7| |
8| |
9| |
+-------------------+
Currently this is my code:
#include <iostream>
using namespace std;
#include <vector>
#include <string.h>
int main() {
char score[10][10] = {' '};
cout << " a b c d e f g h i j" << endl;
cout << " +-------------------+" << endl;
for (int i = 0; i < 10; i++) {
cout << " " << i << "|";
for (int j = 0; j < 10; j++) {
cout << score[i][j];
}
if(i == 0) {
cout << " |";
} else {
cout << " |";
}
cout << endl;
}
cout << " +-------------------+" << endl;
}
As you can see my code is inefficient and lengthy.
What would be the most efficient possible way ( or a more efficient way) of printing the board as exactly shown above with the multidimensional score array?
As the comments have pointed out, your code is almost efficient as possible. Making it shorter would do little to its run-time and instead obscure its meaning. There are however a few things you can do to speed it up.
Avoid an extra call to operator<<, evaluation of std::end, and unnecessary buffer flushes by using \n and including it in your existing string literals (evaluated at compile time).
Use printf instead of cout. See "performance" section of this article.
As already pointed out by others, there are not many ways to make this more efficient, particularly if constrained to use the cout stream.
But for the "lengthy" part, this is a few lines and characters shorter, albeit C++11:
cout << " a b c d e f g h i j\n"
" +-------------------+\n";
for (int i = 0; i < 10; i++) {
cout << ' ' << i << '|';
for (char s : score[i])
cout << s;
cout << " |\n";
}
cout << " +-------------------+\n";
I don't understand why the spaces should be printed at the end instead of aligning the inner columns nicely, but I followed what you did in your code.
I have also got rid of the unnecessary endl which triggers stream flush and changed single letter strings to character constants, but I'm a bit doubtful of the resulting efficiency gain there. After all, it's just printing some output, not a time-critical computation task.
I'm going to assume that when you said you wanted to make it efficient and not lengthy what you really meant was that you wanted it to be correct and readable.
I don't believe what you currently have is "correct". I assume that char score[10][10] will contain a single printable character for each square of the board and perhaps a null character for cells where you don't want to print anything. And you want to print the contents of score into the template shown. As it stands, if you put anything other than a single space into char score[10][10] you will mess up your template.
As for readability, I think what you currently have is reasonably readable, perhaps it would benefit by having some functions extracted with meaningful names but that is just my personal preference. Based on my assumptions about what you were trying to do here is my corrected and refactored version:
#include <iostream>
#include <vector>
#include <string>
void printHeader() {
std::cout << " a b c d e f g h i j\n";
std::cout << " +-------------------+\n";
}
void printFooter() {
std::cout << " +-------------------+\n";
}
void printRowStart(int i) {
std::cout << " " << i << "|";
}
void printRowEnd() {
std::cout << "|\n";
}
void printSquare(char score) {
char printable_score = (score != '\0') ? score : ' ';
std::cout << printable_score;
}
void printRowScore(char (&row_score)[10]) {
printSquare(row_score[0]);
for (int i = 1; i != 10; ++i) {
std::cout << " ";
printSquare(row_score[i]);
}
}
void printScore(char (&score)[10][10]) {
printHeader();
for (int i = 0; i != 10; ++i) {
printRowStart(i);
printRowScore(score[i]);
printRowEnd();
}
printFooter();
}
int main(){
char score[10][10] = { { 0 } };
// Added to test assumed usage
score[4][5] = 'x';
score[4][6] = 'x';
printScore(score);
}
You might also want to consider making the code print to a generic ostream to make it more testable.

How to convert ASCII value into char in C++?

How do I convert 5 random ascii values into chars?
Prompt:
Randomly generate 5 ascii values from 97 to 122 (the ascii values for all of the alphabet). As you go, determine the letter that corresponds to each ascii value and output the word formed by the 5 letters.
My Code:
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main ()
{
srand (time(NULL));
int val1= rand()%122+97;
int val2= rand()%122+97;
int val3= rand()%122+97;
int val4= rand()%122+97;
int val5= rand()%122+97
cout<<val1<<" and "<<val2<<" and "<<val3<<" and "<<val4<<" and "<<val15<<". "<<
return 0;
}
To convert an int ASCII value to character you can also use:
int asciiValue = 65;
char character = char(asciiValue);
cout << character; // output: A
cout << char(90); // output: Z
for (int i = 0; i < 5; i++){
int asciiVal = rand()%26 + 97;
char asciiChar = asciiVal;
cout << asciiChar << " and ";
}
int main()
{
int v1, v2, v3, v4, v5,v6,v7;
cout << "Enter 7 vals ";
cin >> v1 >> v2 >> v3 >> v4 >> v5 >> v6 >> v7;
cout << "The phrase is "
<< char(v1)
<< char(v2) << " "
<< char(v3) << " "
<< char(v4)
<< char(v5)
<< char(v6)
<< char(v7);
system("pause>0");
}

Bit Operations, mainly ~

I am currently converting decimal to binary, making sure it is 8 bits. All bit operations work except the ~ (NOT) operations. They come out as a huge integer value. I am not sure why, since the other bit operations work. Here is my code: (The commented out lines are what is not working)
Edit: If I want to get 8 bit binary strings, what do I do? Use unsigned chars? If I change all unsigned ints to unsigned chars then my BinaryToDecimal function produces incorrect binary conversion.
#include <iostream>
#include <string>
using namespace std;
string BinaryToDecimal(unsigned int dec)
{
string binary = "";
float remainder = 0.0f;
while( dec != 0 )
{
remainder = dec % 2;
dec /= 2;
if( remainder == 0 )
binary.append("0");
else
binary.append("1");
}
// Reverse binary string
string ret = string(binary.rbegin(), binary.rend());
return ret;
}
int main()
{
unsigned int a = 0;
unsigned int b = 0;
cout << "Enter a number to convert to binary: ";
cin >> a;
cout << "Enter a number to convert to binary: ";
cin >> b;
cout << "A = " << BinaryToDecimal(a) << endl;
cout << "B = " << BinaryToDecimal(b) << endl;
unsigned int c = a & b;
unsigned int d = a | b;
//unsigned int e = ~a;
//unsigned int f = ~b;
unsigned int g = a ^ b;
unsigned int h = a << 2;
unsigned int i = b >> 3;
cout << "A & B = " << BinaryToDecimal(c) << endl;
cout << "A | B = " << BinaryToDecimal(d) << endl;
//cout << "~A = " << BinaryToDecimal(e) << endl;
//cout << "~B = " << BinaryToDecimal(f) << endl;
cout << "A ^ B = " << BinaryToDecimal(g) << endl;
cout << "A << 2 = " << BinaryToDecimal(h) << endl;
cout << "B >> 3 = " << BinaryToDecimal(i) << endl;
}
If you perform a binary NOT on a small unsigned integer, you will get a large number as a result, seeing as most of the most significant bits will be set to 1 (the inverse of what they were in the operand).
In this case you're doing ~ 0 which will certainly give you a large number, in fact the largest possible unsigned int, since all bits will be set to 1.
(What result were you expecting?)
You are using an unsigned int for the operations, such that the inversion of small number becomes a large number because of leading 1 starting from the MSB. If you only want the representation is 8 bit only, you should use unsigned char for its storage.
But you cannot change a or b to unsigned char. Otherwise, cin >> a will put the number's ASCII code to a, not a number. For example, your input is 5, it puts 0x35 ('5'), not number 5.
If you don't want to change unsigned int of your code, you can do some minor enhancements
string BinaryToDecimal(unsigned int dec)
{
string binary = "";
float remainder = 0.0f;
dec &= 0xff; // only 8 bits you care about
while( dec != 0 )
{
....
But you are using while( dec !=0 ), which is buggy. If the result is already 0, then the function returns an empty string, not "0000". Instead, you should use a counter to count only for 8 bit.
for (int i = 0; i < 8; i++ ) {
if ((dec & 1) != 0)
binary.append("1");
else
binary.append("0");
dec >>= 1;
}
Also, using bit wise AND to test the bit is 0 or 1, and shift operation, is better than / and % operators.
Finally, for 8 bit 5 (0000_0101), its inversion is 250 (1111_1010), not 1010.