Is it possible to store a leading zero in an int? - c++

I have a programming assignment where I need to encrypt a 4 digit int, input by user. I have split the int into four separate values and the encrypt and decrypt functions work. My problem is when I put the four separate ints back together, some numbers encrypt to zero (eg. in:1234 out:0189) and I want to store the output into an int for use with other functions.
Right now I have a half-baked solution that prints 0 first if the first int is 0.
void joinInt(){
if(int1 == 0) {cout << 0;}
joined = int1 * 1000;
joined += int2 * 100;
joined += int3 * 10;
joined += int4;
cout << joined << endl;
}
My goal is to return joined (with the leading zero) rather than just print it within the function.

Do this:
#include <iomanip>
#include <iostream>
std::cout << std::setfill('0') << std::setw(4) << joined << std::endl;

An int contains a number. It does not contain any particular representation information, like whether it was input from text containing one leading zero or two, or whether it was written in hexadecimal, octal, or chicken scratches, or even if it was computed from adding a bunch of numbers. It is just a value.
If you want to display an int with leading zeros, then you have to explicitly convert it that way:
char buf [20];
snprintf (buf, sizeof buf, "%04d", myint); // output base 10, + leading zeros
// for a field width of 4

An int basically stores leading zeros. The problem that you are running into is that you are not printing the leading zeros that are there.
Another, different approach is to create a function that will accept the four int values along with a string and to then return a string with the numbers.
With this approach you have a helper function with very good cohesion, no side effects, reusable where you need something similar to be done.
For instance:
char *joinedIntString (char *pBuff, int int1, int int2, int int3, int int4)
{
pBuff[0] = (int1 % 10) + '0';
pBuff[1] = (int2 % 10) + '0';
pBuff[2] = (int3 % 10) + '0';
pBuff[3] = (int4 % 10) + '0';
pBuff[4] = 0; // end of string needed.
return pBuff;
}
Then in the place where you need to print the value you can just call the function with the arguments and the provided character buffer and then just print the character buffer.
With this approach if you have some unreasonable numbers that end up have more than one leading zero, you will get all of the zeros.
Or you may want to have a function that combines the four ints into a single int and then another function that will print the combined int with leading zeros.
int createJoinedInt (int int1, int int2, int int3, int int4)
{
return (int1 % 10) * 1000 + (int2 % 10) * 100 + (int 3 % 10) * 10 + (int4 % 10);
}
char *joinedIntString (char *pBuff, int joinedInt)
{
pBuff[0] = ((joinedInt / 1000) % 10) + '0';
pBuff[1] = ((joinedInt / 100) % 10) + '0';
pBuff[2] = ((joinedInt / 10) % 10) + '0';
pBuff[3] = (joinedInt % 10) + '0';
pBuff[4] = 0; // end of string needed.
return pBuff;
}

This should do the trick.
cout << setw(4) << setfill('0') << joined << endl;
In order to use these manipulators, you'll need to:
#include <iomanip>

C++ stores int as a binary number. However all IO is as string. So, to display an int there must be a conversion from an int to a string. It's in the conversion process that you can set the with from the displayed number. Use the streams manipulators setw and setfill for this purpose.

Related

Remove trailing zero in C++

I want to ask how to remove trailing zeros after decimal point?
I've read lots of topics about it but I don't understand them clearly. Could you show me any easy understanding ways ?
For example 12.50 to 12.5, but the actual output is 12.50
This is one thing that IMHO is overly complicated in C++. Anyway, you need to specify the desired format by setting properties on the output stream. For convenience a number of manipulators are defined.
In this case, you need to set fixed representation and set precision to 2 to obtain the rounding to 2 decimals after the point using the corresponding manipulators, see below (notice that setprecisioncauses rounding to the desired precision). The tricky part is then to remove trailing zeroes. As far as I know C++ does not support this out of the box, so you have to do some string manipulation.
To be able to do this, we will first "print" the value to a string and then manipulate that string before printing it:
#include <iostream>
#include <iomanip>
int main()
{
double value = 12.498;
// Print value to a string
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << value;
std::string str = ss.str();
// Ensure that there is a decimal point somewhere (there should be)
if(str.find('.') != std::string::npos)
{
// Remove trailing zeroes
str = str.substr(0, str.find_last_not_of('0')+1);
// If the decimal point is now the last character, remove that as well
if(str.find('.') == str.size()-1)
{
str = str.substr(0, str.size()-1);
}
}
std::cout << str << std::endl;
}
For C++ check this How to output float to cout without scientific notation or trailing zeros?
using printf() you may use following method to do this,
int main()
{
double value = 12.500;
printf("%.6g", value ); // 12.5 with 6 digit precision
printf("%.6g", 32.1234); // 32.1234
printf("%.6g", 32.12300000); // 32.123
}
std::string example = std::to_string(10.500f);
while (example[example.size() - 1] == '0' || example[example.size() - 1] == '.')
example.resize(example.size() - 1);
Just use 'printf' function.
printf("%.8g",8.230400); will print '8.2304'
float value =4.5300;
printf ("%.8g",value);
will return 4.53.
Try this code . It is quite simple.
I was stumped by this for a while and didn't want to convert to a string to get the job done, so I came up with this:
float value = 1.00;
char buffer[10];
sprintf(buffer, "%.2f", value);
int lastZero = strlen(buffer);
for (int i = strlen(buffer) - 1; i >= 0; i--)
{
if (buffer[i] == '\0' || buffer[i]=='0' || buffer[i]=='.')
lastZero = i;
else
break;
}
if (lastZero==0)
lastZero++;
char newValue[lastZero + 1];
strncpy(newValue, buffer, lastZero);
newValue[lastZero] = '\0';
newValue = 1
you can round-off the value to 2 digits after decimal,
x = floor((x * 100) + 0.5)/100;
and then print using printf to truncate any trailing zeros..
printf("%g", x);
example:
double x = 25.528;
x = floor((x * 100) + 0.5)/100;
printf("%g", x);
output: 25.53

formatted output for doubles [duplicate]

This question already has answers here:
C++ setprecision(2) printing one decimal?
(2 answers)
Closed 8 years ago.
I want to know how I can, in c++, print for example 10 as 10.0000, or 10.1 as 10.1000.
I want the total number of digits to be the same and pad with '0' the empty spaces on the right.
I read about 'setprecision', but it doesn't add '0'.
'fixed' is the numbers of digits after the floating point, and I want the total number of digits to be fixed.
is there a way to do this, not using printf?
You can do something like this: (considering you want a fixed length of 5)
int precision(double num){
int p;
if (num <1)
p = 5;
else if (num <10)
p = 4;
else if (num <100)
p = 3;
else if (num <1000)
p = 2;
else if (num <10000)
p = 1;
else
p = 0;
return p;
}
int main(){
double num;
std::cin>>num;
std::cout <<std::fixed <<std::setprecision(precision(num)) << num <<std::endl;
return 0;
}
As you required, if the number of digits After decimal is more than 5 it will be truncated.
Now, implement your own logic for what you want to do if number of digits Before decimal point is more than 5. :)
You will ultimately need to find out the length in digits of the double. I'm not entirely sure how to go about that in a safe way but fortunately I can show you an example where we can do this with integers.
Basically I would recommend creating a new facet class that implements the custom formatting inside do_put(). Then imbue this class into your stream. The exact same thing as below can be done for the overload of do_put() that takes a double as its last argument, plus a few changes to the for loop.
#include <iostream>
#include <iomanip>
class num_put : public std::num_put<char>
{
iter_type do_put( iter_type out, std::ios_base& str, char, long v ) const
{
std::streamsize width = str.width();
int digits = num_digits(v);
if (digits > width)
for (std::streamsize i(0); i < digits - width; ++i)
v /= 10;
/* v = static_cast<int>(v * 10) / 10.; // use this instead for
*/ // floating-point
str.flags(std::ios_base::left);
out = std::num_put<char>::do_put(out, str, '0', v);
str.width(width);
return out;
}
private:
template<class T>
static int num_digits(T num) // only works for integral types
{
int length = 1;
while (num /= 10)
++length;
return length;
}
};
int main()
{
std::cout.imbue(std::locale(std::cout.getloc(), new num_put));
std::cout << std::setw(5) << 123; // 12300
std::cout << std::setw(5) << 123456789; // 12345
}

Base encoding impossible with leading 0?

I am trying to encode a string to base36.
static char *decode(unsigned long long value)
{
char base36[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[14];
unsigned int offset = sizeof(buffer);
buffer[--offset] = '\0';
do {
buffer[--offset] = base36[value % 36];
} while (value /= 36);
return _strdup(&buffer[offset]);
}
int main()
{
char original[8] = "0XDX3A1";
unsigned long long encoded = _strtoui64(original, NULL, 36);
char *decoded = decode(encoded);
cout << "Original: " << original << " Decoded: " << decoded << endl;
return 0;
}
The problem here is, while those functions work OK: if the string I am trying to encode has a leading 0 the decoded string is one character (or more) less than the original.
How to deal with this?
If you decode the string "01234" as a base-16 string (for example), you get the integer value 4660 (0x1234) -- exactly the same integer value you get by decoding the string "1234" or "00001234" as a base-16 string. By converting the string to an integer, you've thrown away any information about leading zeros. You've also discarded any information about uppercase vs. lowercase letters, assuming that A and a represent the same value.
Converting that integer value back to a string isn't going to restore that leading 0 unless you add it explicitly. And if you want to add that leading 0 (or multiple 0s) if and only if they were present in the original string, you're going to have to store that information somehow.
Introduce a new variable in your main, called zeroCount in main
Introduce a 2nd argument to function decode, called zeroCount
Count the amount of leading zeroes in the original to the zeroCount in main
Place zeroes to buffer[--offset] until you consume all the zeroCount before the return
Like this:
static char *decode( unsigned long long value, int zeroCount )
{ // introduced zeroCount argument there ^
char base36[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[14];
unsigned int offset = sizeof( buffer );
buffer[--offset] = '\0';
do {
buffer[--offset] = base36[value % 36];
} while ( value /= 36 );
while ( zeroCount-- ) buffer[--offset] = '0'; // <-- added this
return strdup( &buffer[offset] );
}
int main( )
{
char original[8] = "0XDX3A1";
unsigned long long encoded = _strtoui64( original, NULL, 36 );
int zeroCount = 0; // added
for ( int i = 0; i < sizeof original && original[i] == '0'; i++ ) // these
zeroCount++; // three
char *decoded = decode( encoded, zeroCount ); // <-- called along with zeroCount
cout << "Original: " << original << " Decoded: " << decoded << endl;
return 0;
}
Since there isn't any apparent rule for the 0 appending behaviour you desire, I had to assume that you'd like to have exact many leading zeroes that the original had.
You're calling a function tat takes a string containing a representation of a numeric value and converts it to an unsigned long long . The two string representations '00007' and '7' are both converted to numeric 7, and the leading zeroes are lost.
IF you want, eg, 00000036 to covert to 00000010 in base 36, you'll just have to count the zeroes you want and then decide how many of them to replace ( would it depend on the relative lengths of base 10 and base 36 strings? )
But it seems poor practice in the conversion functions. better, in my mind, to add leading zeroes when outputting the value. As many have commented, they have no significance and should not be part of the conversion logic.
I'd suggest you to create a wrapper around your method, and pass it a length parameter.
Eg.
char * wrap_base36enc(int out_len, unsigned long long value){
char pre_str[MAX_VAL]="", *ans = base36enc(value);
len -= strlen(ans);
while(len--){
strcat(pre_str,"0");
}
strcat(pre_str,ans);
return pre_str;
}

Get the number of digits in an int

How do I detect the length of an integer? In case I had le: int test(234567545);
How do I know how long the int is? Like telling me there is 9 numbers inside it???
*I have tried:**
char buffer_length[100];
// assign directly to a string.
sprintf(buffer_length, "%d\n", 234567545);
string sf = buffer_length;
cout <<sf.length()-1 << endl;
But there must be a simpler way of doing it or more clean...
How about division:
int length = 1;
int x = 234567545;
while ( x /= 10 )
length++;
or use the log10 method from <math.h>.
Note that log10 returns a double, so you'll have to adjust the result.
Make a function :
int count_numbers ( int num) {
int count =0;
while (num !=0) {
count++;
num/=10;
}
return count;
}
Nobody seems to have mentioned converting it to a string, and then getting the length. Not the most performant, but it definitely does it in one line of code :)
int num = -123456;
int len = to_string(abs(num)).length();
cout << "LENGTH of " << num << " is " << len << endl;
// prints "LENGTH of 123456 is 6"
You can use stringstream for this as shown below
stringstream ss;
int i = 234567545;
ss << i;
cout << ss.str().size() << endl;
if "i" is the integer, then
int len ;
char buf[33] ;
itoa (i, buf, 10) ; // or maybe 16 if you want base-16 ?
len = strlen(buf) ;
if(i < 0)
len-- ; // maybe if you don't want to include "-" in length ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int i=2384995;
char buf[100];
itoa(i, buf, 10); // 10 is the base decimal
printf("Lenght: %d\n", strlen(buf));
return 0;
}
Beware that itoa is not a standard function, even if it is supported by many compilers.
len=1+floor(log10(n));//c++ code lib (cmath)
looking across the internet it's common to make the mistake of initializing the counter variable to 0 and then entering a pre-condition loop testing for as long as the count does not equal 0. a do-while loop is perfect to avoid this.
unsigned udc(unsigned u) //unsigned digit count
{
unsigned c = 0;
do
++c;
while ((u /= 10) != 0);
return c;
}
it's probably cheaper to test whether u is less than 10 to avoid the uneccessary division, increment, and cmp instructions for cases where u < 10.
but while on that subject, optimization, you could simply test u against constant powers of ten.
unsigned udc(unsigned u) //unsigned digit count
{
if (u < 10) return 1;
if (u < 100) return 2;
if (u < 1000) return 3;
//...
return 0; //number was not supported
}
which saves you 3 instructions per digit, but is less adaptable for different radixes inaddition to being not as attractive, and tedious to write by hand, in which case you'd rather write a routine to write the routine before inserting it into your program. because C only supports very finite numbers, 64bit,32bit,16bit,8bit, you could simply limit yourself to the maximum when generating the routine to benefit all sizes.
to account for negative numbers, you'd simply negate u if u < 0 before counting the number of digits. of course first making the routine support signed numbers.
if you know that u < 1000,
it's probably easier to just write, instead of writing the routine.
if (u > 99) len = 3;
else
if (u > 9) len = 2;
else len = 1;
Here are a few different C++ implementations* of a function named digits() which takes a size_t as argument and returns its number of digits. If your number is negative, you are going to have to pass its absolute value to the function in order for it to work properly:
The While Loop
int digits(size_t i)
{
int count = 1;
while (i /= 10) {
count++;
}
return count;
}
The Exhaustive Optimization Technique
int digits(size_t i) {
if (i > 9999999999999999999ull) return 20;
if (i > 999999999999999999ull) return 19;
if (i > 99999999999999999ull) return 18;
if (i > 9999999999999999ull) return 17;
if (i > 999999999999999ull) return 16;
if (i > 99999999999999ull) return 15;
if (i > 9999999999999ull) return 14;
if (i > 999999999999ull) return 13;
if (i > 99999999999ull) return 12;
if (i > 9999999999ull) return 11;
if (i > 999999999ull) return 10;
if (i > 99999999ull) return 9;
if (i > 9999999ull) return 8;
if (i > 999999ull) return 7;
if (i > 99999ull) return 6;
if (i > 9999ull) return 5;
if (i > 999ull) return 4;
if (i > 99ull) return 3;
if (i > 9ull) return 2;
return 1;
}
The Recursive Way
int digits(size_t i) { return i < 10 ? 1 : 1 + digits(i / 10); }
Using snprintf() as a Character Counter
⚠ Requires #include <stdio.h> and may incur a significant performance penalty compared to other solutions. This method capitalizes on the fact that snprintf() counts the characters it discards when the buffer is full. Therefore, with the right arguments and format specifiers, we can force snprintf() to give us the number of digits of any size_t.
int digits(size_t i) { return snprintf (NULL, 0, "%llu", i); }
The Logarithmic Way
⚠ Requires #include <cmath> and is unreliable for unsigned integers with more than 14 digits.
// WARNING! There is a silent implicit conversion precision loss that happens
// when we pass a large int to log10() which expects a double as argument.
int digits(size_t i) { return !i? 1 : 1 + log10(i); }
Driver Program
You can use this program to test any function that takes a size_t as argument and returns its number of digits. Just replace the definition of the function digits() in the following code:
#include <iostream>
#include <stdio.h>
#include <cmath>
using std::cout;
// REPLACE this function definition with the one you want to test.
int digits(size_t i)
{
int count = 1;
while (i /= 10) {
count++;
}
return count;
}
// driver code
int main ()
{
const int max = digits(-1ull);
size_t i = 0;
int d;
do {
d = digits(i);
cout << i << " has " << d << " digits." << '\n';
i = d < max ? (!i ? 9 : 10 * i - 1) : -1;
cout << i << " has " << digits(i) << " digits." << '\n';
} while (++i);
}
* Everything was tested on a Windows 10 (64-bit) machine using GCC 12.2.0 in Visual Studio Code .
As long as you are mixing C stdio and C++ iostream, you can use the snprintf NULL 0 trick to get the number of digits in the integer representation of the number. Specifically, per man 3 printf If the string exceeds the size parameter provided and is truncated snprintf() will return
... the number of characters (excluding the terminating null byte)
which would have been written to the final string if enough space
had been available.
This allows snprintf() to be called with the str parameter NULL and the size parameter 0, e.g.
int ndigits = snprintf (NULL, 0, "%d", 234567545)
In your case where you simply wish to output the number of digits required for the representation, you can simply output the return, e.g.
#include <iostream>
#include <cstdio>
int main() {
std::cout << "234567545 is " << snprintf (NULL, 0, "%d", 234567545) <<
" characters\n";
}
Example Use/Output
$ ./bin/snprintf_trick
234567545 is 9 characters
note: the downside to using the snprintf() trick is that you must provide the conversion specifier which will limit the number of digits representable. E.g "%d" will limit to int values while "%lld" would allow space for long long values. The C++ approach using std::stringstream while still limited to numeric conversion using the << operator handles the different integer types without manually specifying the conversion. Something to consider.
second note: you shouldn't dangle the "\n" of the end of your sprintf() conversion. Add the new line as part of your output and you don't have to subtract 1 from the length...

How to convert an int to a binary string representation in C++

I have an int that I want to store as a binary string representation. How can this be done?
Try this:
#include <bitset>
#include <iostream>
int main()
{
std::bitset<32> x(23456);
std::cout << x << "\n";
// If you don't want a variable just create a temporary.
std::cout << std::bitset<32>(23456) << "\n";
}
I have an int that I want to first convert to a binary number.
What exactly does that mean? There is no type "binary number". Well, an int is already represented in binary form internally unless you're using a very strange computer, but that's an implementation detail -- conceptually, it is just an integral number.
Each time you print a number to the screen, it must be converted to a string of characters. It just so happens that most I/O systems chose a decimal representation for this process so that humans have an easier time. But there is nothing inherently decimal about int.
Anyway, to generate a base b representation of an integral number x, simply follow this algorithm:
initialize s with the empty string
m = x % b
x = x / b
Convert m into a digit, d.
Append d on s.
If x is not zero, goto step 2.
Reverse s
Step 4 is easy if b <= 10 and your computer uses a character encoding where the digits 0-9 are contiguous, because then it's simply d = '0' + m. Otherwise, you need a lookup table.
Steps 5 and 7 can be simplified to append d on the left of s if you know ahead of time how much space you will need and start from the right end in the string.
In the case of b == 2 (e.g. binary representation), step 2 can be simplified to m = x & 1, and step 3 can be simplified to x = x >> 1.
Solution with reverse:
#include <string>
#include <algorithm>
std::string binary(unsigned x)
{
std::string s;
do
{
s.push_back('0' + (x & 1));
} while (x >>= 1);
std::reverse(s.begin(), s.end());
return s;
}
Solution without reverse:
#include <string>
std::string binary(unsigned x)
{
// Warning: this breaks for numbers with more than 64 bits
char buffer[64];
char* p = buffer + 64;
do
{
*--p = '0' + (x & 1);
} while (x >>= 1);
return std::string(p, buffer + 64);
}
AND the number with 100000..., then 010000..., 0010000..., etc. Each time, if the result is 0, put a '0' in a char array, otherwise put a '1'.
int numberOfBits = sizeof(int) * 8;
char binary[numberOfBits + 1];
int decimal = 29;
for(int i = 0; i < numberOfBits; ++i) {
if ((decimal & (0x80000000 >> i)) == 0) {
binary[i] = '0';
} else {
binary[i] = '1';
}
}
binary[numberOfBits] = '\0';
string binaryString(binary);
http://www.phanderson.com/printer/bin_disp.html is a good example.
The basic principle of a simple approach:
Loop until the # is 0
& (bitwise and) the # with 1. Print the result (1 or 0) to the end of string buffer.
Shift the # by 1 bit using >>=.
Repeat loop
Print reversed string buffer
To avoid reversing the string or needing to limit yourself to #s fitting the buffer string length, you can:
Compute ceiling(log2(N)) - say L
Compute mask = 2^L
Loop until mask == 0:
& (bitwise and) the mask with the #. Print the result (1 or 0).
number &= (mask-1)
mask >>= 1 (divide by 2)
I assume this is related to your other question on extensible hashing.
First define some mnemonics for your bits:
const int FIRST_BIT = 0x1;
const int SECOND_BIT = 0x2;
const int THIRD_BIT = 0x4;
Then you have your number you want to convert to a bit string:
int x = someValue;
You can check if a bit is set by using the logical & operator.
if(x & FIRST_BIT)
{
// The first bit is set.
}
And you can keep an std::string and you add 1 to that string if a bit is set, and you add 0 if the bit is not set. Depending on what order you want the string in you can start with the last bit and move to the first or just first to last.
You can refactor this into a loop and using it for arbitrarily sized numbers by calculating the mnemonic bits above using current_bit_value<<=1 after each iteration.
There isn't a direct function, you can just walk along the bits of the int (hint see >> ) and insert a '1' or '0' in the string.
Sounds like a standard interview / homework type question
Use sprintf function to store the formatted output in the string variable, instead of printf for directly printing. Note, however, that these functions only work with C strings, and not C++ strings.
There's a small header only library you can use for this here.
Example:
std::cout << ConvertInteger<Uint32>::ToBinaryString(21);
// Displays "10101"
auto x = ConvertInteger<Int8>::ToBinaryString(21, true);
std::cout << x << "\n"; // displays "00010101"
auto x = ConvertInteger<Uint8>::ToBinaryString(21, true, "0b");
std::cout << x << "\n"; // displays "0b00010101"
Solution without reverse, no additional copy, and with 0-padding:
#include <iostream>
#include <string>
template <short WIDTH>
std::string binary( unsigned x )
{
std::string buffer( WIDTH, '0' );
char *p = &buffer[ WIDTH ];
do {
--p;
if (x & 1) *p = '1';
}
while (x >>= 1);
return buffer;
}
int main()
{
std::cout << "'" << binary<32>(0xf0f0f0f0) << "'" << std::endl;
return 0;
}
This is my best implementation of converting integers(any type) to a std::string. You can remove the template if you are only going to use it for a single integer type. To the best of my knowledge , I think there is a good balance between safety of C++ and cryptic nature of C. Make sure to include the needed headers.
template<typename T>
std::string bstring(T n){
std::string s;
for(int m = sizeof(n) * 8;m--;){
s.push_back('0'+((n >> m) & 1));
}
return s;
}
Use it like so,
std::cout << bstring<size_t>(371) << '\n';
This is the output in my computer(it differs on every computer),
0000000000000000000000000000000000000000000000000000000101110011
Note that the entire binary string is copied and thus the padded zeros which helps to represent the bit size. So the length of the string is the size of size_t in bits.
Lets try a signed integer(negative number),
std::cout << bstring<signed int>(-1) << '\n';
This is the output in my computer(as stated , it differs on every computer),
11111111111111111111111111111111
Note that now the string is smaller , this proves that signed int consumes less space than size_t. As you can see my computer uses the 2's complement method to represent signed integers (negative numbers). You can now see why unsigned short(-1) > signed int(1)
Here is a version made just for signed integers to make this function without templates , i.e use this if you only intend to convert signed integers to string.
std::string bstring(int n){
std::string s;
for(int m = sizeof(n) * 8;m--;){
s.push_back('0'+((n >> m) & 1));
}
return s;
}