Truncate C++ string fields generated by ostringstream, iomanip:setw - c++

In C++ I need string representations of integers with leading zeroes, where the representation has 8 digits and no more than 8 digits, truncating digits on the right side if necessary. I thought I could do this using just ostringstream and iomanip.setw(), like this:
int num_1 = 3000;
ostringstream out_target;
out_target << setw(8) << setfill('0') << num_1;
cout << "field: " << out_target.str() << " vs input: " << num_1 << endl;
The output here is:
field: 00003000 vs input: 3000
Very nice! However if I try a bigger number, setw lets the output grow beyond 8 characters:
int num_2 = 2000000000;
ostringstream out_target;
out_target << setw(8) << setfill('0') << num_2;
cout << "field: " << out_target.str() << " vs input: " << num_2 << endl;
out_target.str("");
output:
field: 2000000000 vs input: 2000000000
The desired output is "20000000". There's nothing stopping me from using a second operation to take only the first 8 characters, but is field truncation truly missing from iomanip? Would the Boost formatting do what I need in one step?

I can't think of any way to truncate a numeric field like that. Perhaps it has not been implemented because it would change the value.
ostream::write() allows you to truncate a string buffer simply enough, as in this example...
int num_2 = 2000000000;
ostringstream out_target;
out_target << setw(8) << setfill('0') << num_2;
cout << "field: ";
cout.write(out_target.str().c_str(), 8);
cout << " vs input: " << num_2 << endl;

If you assume that snprintf() will write as many chars at it can (I don't think this is guaranteed),
char buf[9];
snprintf(buf, 10, "%08d", num);
buf[8] = 0;
cout << std::string(buf) << endl;
I am not sure why you want 2 billion to be the same as 20 million. It may make more sense to signal an error on truncation, like this:
if (snprintf(buf, 10, "%08d", num) > 8) {
throw std::exception("oops")
}

Related

How to get non scientific output while still not outputing zeros in std::cout?

Here's is an example:
std::cout << 1000000.0 << "\n";
std::cout << std::fixed << 1000000.0 << "\n";
std::cout << std::fixed << std::noshowpoint << 1000000.0 << "\n";
It will print me this:
1e+06
1000000.000000
1000000.000000
But I want this:
1000000
How I can do it with IO manipulators without setprecision()?
Why without?
Because I want to print:
std::cout << 1000000.0 << " " << 1111111.1 << " " << 1234567.89;
and get:
1000000 1111111.1 1234567.89
without calculating precision for every number
The scientific output is used when the digits count of the number is higher than precision.
For example, the default precision is equal to 6, but the number 1234567 has 7 digits, so it will be printed as 1.23457+e06, cutting off the last digit.
So to get 1234567 printed normally we need at least precision = 7.
The highest precision that is not adding the "wrong" numbers is 15, so you need to use std::setprecision(15).
code:
std::cout << std::setprecision(15) << 1000000.0 << " " << 1111111.1 << " " << 1234567.89;
out:
1000000 1111111.1 1234567.89

How can you use std::setw() with array output?

I am making a blackjack game in C++, and I am trying to print out the players and dealers cards in addition to their sums, capital and so on. However I'm running into an issue with std::setw() when printing out the vector of cards. Here is a code snippet:
int width = 18;
std::cout << std::left << std::setw(width) << "Your cards:";
std::cout << std::left << std::setw(width * 2) << "arr";
std::cout << std::left << std::setw(width) << "Dealers cards:";
std::cout << "arr2" << std::endl;
std::cout << std::left << std::setw(width) << "Your sum:";
std::cout << std::left << std::setw(width*2) << player.sum();
std::cout << std::left << std::setw(width) << "Dealers sum:";
std::cout << dealer.sum() << std::endl;
Where arr and arr2 is there should be number values like 5 2 6 1, but if I print each element separately the with alignment will break. I think for setw() to work it needs to be one block or string, or else the vertical alignment will mess up once the values change. I tried myString.push_back() for each vector value and then printing that, with no luck. I assume I need to find a way to print the string into one element.
This is what it should look like:
Your cards: 5 7 1 2 Dealers cards: 2 1 7 5
Your sum: 21 Dealers sum: 21
Your capital: 100 Dealers capital: 100
I have found a solution. You can use stringstream to add int values to a string with no errors in conversion, this is how I fixed my code:
#include <sstream>
std::stringstream playerCards{};
for (int i{}; i < player.cards.size(); i++) {
playerCards << player.cards[i] << " ";
}
int width = 18;
std::cout << std::left << std::setw(width) << "Your cards:";
std::cout << std::left << std::setw(width * 2) << playerCards.str();
This way the array will get put into a string and will count as one block, which is what I was looking for.

Addition and Subtraction giving incorrect results

I made a simple program to add and subtract the given numbers. Let's say the 2 numbers give were 5 and 5. It would print 5 + 5 = 10 and 5 - 5 = 0. Right now I'm not sure what's wrong. I might need a temporary variable, but something with the input isn't right. If you test the numbers with 5 and 5 it prints:
Addition / Subtraction Program
*------------------------------*
Press Enter to begin!
What is the number you'd like to add / sub to?5
5
What is the next number?5
55 + 5 = 105 - 5 = 0
Here's the code I'm using:
#include <iostream>
using namespace std;
int main() {
int num_1;
int num_2;
cout << "Addition / Subtraction Program" << endl << "*------------------------------*\n\nPress Enter to begin!";
cin.get();
cout << "What is the number you'd like to add / sub to?";
cin >> num_1;
cout << num_1 << endl << "What is the next number?";
cin >> num_2;
cout << num_2;
cout << num_1 << " + " << num_2 << " = " << num_1 + num_2;
cout << num_1 << " - " << num_2 << " = " << num_1 - num_2;
return 0;
}
The output is correct, it's just missing spaces.
After the user enters their number, you echo it back to them; without any whitespace. This "turns" 5 into 55, and 10 5 into 105.
The addition and subtraction are fine, you just need to format your output. End your cout lines with a << endl; or << "\n"; to see the difference.
The outputs are not incorrect. You only need to fix the formatting. In between the following two cout's, there is no clear demarcation:
cout << num_1 << " + " << num_2 << " = " << num_1 + num_2;//cout 1
cout << num_1 << " - " << num_2 << " = " << num_1 - num_2;//cout 2
Hence you get the output as:
55 + 5 = 105 - 5 = 0
|-cout 1 -||-cout 2-|
You can either use a newline (by cout<<endl; or cout<<"\n"; between the two) or a space(cout<<" ";) to clearly demarcate between the two outputs.
Actually there is no problem with addition and subtraction. You didn't print the new line ('\n') character at the end of this line -
cout << num_1 << " + " << num_2 << " = " << num_1 + num_2;
It's good practice to add newline ('\n') character one endl manipulator at the end of each line.
In your current code, you have only formatting problem.

setw of a specific integer with set precision in C++

I'm learning the setw and setprecision functions, so here is what I've been trying so far and I have a few questions.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
float y = 1.25;
cout << fixed << setw(10) << setprecision(2) << y << endl;
cout << "\n\n\nx\n";
float x = 213565544.4826;
cout << fixed << setw(13) << setprecision(3) << x << endl;
cout << fixed << setw(14) << setprecision(3) << x << endl;
cout << fixed << setw(15) << setprecision(3) << x << endl;
cout << fixed << setprecision(3) << x;
cout << "\n\n\nz\n";
float z = 213565544.4826;
cout << setw(11) << setprecision(1) << x << endl;
cout << fixed << setw(12) << setprecision(1) << x << endl;
cout << fixed << setw(11) << setprecision(1) << x << endl;
cout << setw(12) << setprecision(1) << x << endl;
cout << "\n\n\nm\n";
float m = -344.275;
cout << fixed << setprecision(1) << x << endl;
cout << fixed << setw(8) << setprecision(1) << x << endl;
cout << fixed << setw(7) << setprecision(1) << x << endl;
cout << fixed << setw(6) << setprecision(1) << x << endl;
return 0;
}
And the input is :
1.25
x
213565552.000
213565552.000
213565552.000
213565552.000
z
213565552.0
213565552.0
213565552.0
213565552.0
m
213565552.0
213565552.0
213565552.0
213565552.0
So, now my questions are :
1) Why do we use "fixed" in first place?
If we look at this example:
cout << setw(11) << setprecision(1) << x << endl;
cout << fixed << setw(11) << setprecision(1) << x << endl;
They output the same value, so what does fixed really change?
2) How does setw work for negative numbers?
In the last example of m. The result is the same for all examples, what does the - sign change in the setw ?
213565552.0
213565552.0
213565552.0
213565552.0
Where do these numbers come from? The value of m is totally different from the ones outputted.
3) Does the . in the number counts as 1 place?
For example, we have number 1.23 and setw(10)
There would be 6 spaces before and then 1.23 (because the dot is counted as 1). Is that true?
4) Why does setprecision is used along with setw? Why does 0000s appear if it's not used? Does it appear as many 0s as the float can handle?
5) Why is the value for x
213565552.000
213565552.000
213565552.000
213565552.000
If x = 213565544.4826.
Where does the numbers 44.4826 get lost?
These seem to be 5 questions rather than one. Anyway:
std::fixed is used to indicate that you always want to have a fixed point format rather than using scientific notation where this notation is more appropriate. When there are many digits needed to represent the value reasonably, the format will switch use x.yyyyyyEee (you can ask to always use scientific format using std::scientific).
std::setw() doesn't care what value is formatted! When a value is formatted and there is a positive out.width() set, the output will be padded with out.fill() character to be at least out.width() characters wide. If the output is bigger than out.width() anyway, no padding will occur. After each output operation [which takes out.width() into account] the out.width() is reset to 0 (all other formatting options are not automatically reset).
Any character counts towards the width, including the sign, thousands separators, decimal points, etc. The decimal point does not count towards the precision: out.precision() is the number of fractional digits (for std::fixed formatting) or the number of non-exponent digits (for std::scientific formatting).
The width is how many characters will be filled by the output, the precision specifies how many [fractional] digits are to be produced.
Binary floating point values can represent very few decimal digits (for float it is normally 6; you can find out how many digits can be safely used by using std::numeric_limits<float>::digits10). Trying to use any more digits than that will probably result in unexpected output when processing decimal values (when processing binary values you may be interested in up to std:numeric_limits<float>::digits places). You might want to have a look at What Every Computer Scientist Should Know About Floating-Point Arithmetic.

How do I show the actual values in hex instead of the ASCII symbols

int main()
{
char B[76]={0};
ifstream infile;
infile.open("tworecords.dat", ios::binary);
infile.read(reinterpret_cast<char*>(B), sizeof (B));
cout << "Array B in hex" << endl;
for (int i = 0; i < 76; i++)
{
cout << hex << B[i] << " " << endl;;
}
return 0;
}
right now it reads the data correctly, but prints out the values as ASCII symbols. I would like to output the actual hex values in the file.
example:
01
3D
76
D6
etc.
Cast it to integer:
cout << hex << static_cast<int>(B[i]) << " " << endl;
Or alternatively, if you don't want to cast, just add 0:
cout << hex << B[i]+0 << " " << endl;
However you probably also want to make sure that for values below 16, a leading 0 is printed (e.g. for the newline character 0A, not just A):
cout << setfill('0') << setw(2) << hex << B[i]+0 << " " << endl;
You simply cast the number to an integer:
cout << hex << (int)B[i] << " " << endl;
the <iostream> library (actually, all stream libraries) output ascii values for char types.