C++ Int with Preceding 0 Changes Entire Value

C++ int with preceding 0 changes entire value

An integer literal that starts from 0 defines an octal integer literal. Now in C++ there are four categories of integer literals

integer-literal:
decimal-literal integer-suffixopt
octal-literal integer-suffixopt
hexadecimal-literal integer-suffixopt
binary-literal integer-suffixopt

And octal-integer literal is defined the following way

octal-literal:
0 octal-literal
opt octal-digit

That is it starts from 0.

Thus this octal integer literal

0110

corresponds to the following decimal number

8^2 + 8^1 

that is equal to 72.

You can be sure that 72 in octal representation is equivalent to 110 by running the following simple program

#include <iostream>
#include <iomanip>

int main()
{
std::cout << std::oct << 72 << std::endl;

return 0;
}

The output is

110

How does C Handle Integer Literals with Leading Zeros, and What About atoi?

Leading zeros indicate that the number is expressed in octal, or base 8; thus, 010 = 8. Adding additional leading zeros has no effect; just as you would expect in math, x + 0*8^n = x; there's no change to the value by making its representation longer.

One place you often see this is in UNIX file modes; 0755 actually means 7*8^2+5*8+5 = 493; or with umasks such as 0022 = 2*8+2 = 10.

atoi(nptr) is defined as equivalent to strtol(nptr, (char **) NULL, 10), except that it does not detect errors - as such, atoi() always uses decimal (and thus ignores leading zeros). strtol(nptr, anything, 0) does the following:

The string may begin with an arbitrary
amount of white space (as determined
by isspace(3)) followed by a single
optional '+' or '-' sign. If base is
zero or 16, the string may then
include a "0x" prefix, and the number
will be read in base 16; otherwise, a
zero base is taken as 10 (decimal)
unless the next character is '0', in
which case it is taken as 8 (octal).

So it uses the same rules as the C compiler.

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

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

How to force a preceding 0 to an int (without actually outputting it)

If I understand correctly your question, you can just use those manipulators with a stringstream, for instance:

std::stringstream str_hour;
str_hour << setfill('0') << setw(2) << int_hour;

String streams are output streams, so I/O manipulators affect them the same way they affect the behavior of std::cout.

A complete example:

#include <sstream>
#include <iostream>
#include <iomanip>

int main()
{
std::stringstream ss;
ss << std::setfill('0') << std::setw(2) << 10; // Prints 10
ss << " - ";
ss << std::setfill('0') << std::setw(2) << 5; // Prints 05

std::cout << ss.str();
}

And the corresponding live example.

preceding 0's in integer value

An integer doesn't have leading zeros. Integers are numeric values, they don't carry display information with them. So if you're storing the value as an integer then you're not storing any display information. In that case you apply the display information when you display the value:

int a = 10;
Console.WriteLine(Convert.ToString(a).PadLeft(5, '0'));

If you want the display information to be retained as part of the value itself, make it a string:

string a = "00010";
Console.WriteLine(a);

If it needs to be stored as an integer and you don't want to re-write the display logic many times, you can encapsulate that logic into a custom type which wraps the integer:

public class PaddedInteger
{
private int Value { get; set; }
private int PaddingSize { get; set; }
private char PaddingCharacter { get; set; }

public PaddedInteger(int value, int paddingSize, char paddingCharacter)
{
Value = value;
PaddingSize = paddingSize;
PaddingCharacter = paddingCharacter;
}

public override string ToString()
{
return Convert.ToString(Value).PadLeft(PaddingSize, PaddingCharacter);
}
}

Then in your code:

PaddedInteger a = new PaddedInteger(10, 5, '0');
Console.WriteLine(a);

Why Integers change their value when zeros are added to the left?

A leading zero mean octal. Just like a leading 0x mean hexadecimal



Related Topics



Leave a reply



Submit