printing integers
printing integers
i have a little problem..
i have a function which prints strings on the screen(puts()) but i want it to print an integer on the screen
but the problem is, that i have to convert the integer first
i dont know how to do so
ive already tried to use a cast like: (char) integer_variable but it doesnt seem to work
i hope u have an answer to that
thanks
i have a function which prints strings on the screen(puts()) but i want it to print an integer on the screen
but the problem is, that i have to convert the integer first
i dont know how to do so
ive already tried to use a cast like: (char) integer_variable but it doesnt seem to work
i hope u have an answer to that
thanks
Hi,
Have a look at this link which has a decent section on number conversion (despite being an AVR rather than x86 site).
The basic rule for decimal is that you divide by decreasing factors of 10, appending ASCII numbers to the string you are creating. For hex you do the same, but you can use bit shifting because you deal with a whole nibble at a time.
You cannot use a cast in the way you mention. Supposing yout integer_variable = 0x12345678, cast it and pass it to a putchar function, the function will try to print the ASCII value of 0x78, which is the character 'N'.
Cheers,
Adam
Have a look at this link which has a decent section on number conversion (despite being an AVR rather than x86 site).
The basic rule for decimal is that you divide by decreasing factors of 10, appending ASCII numbers to the string you are creating. For hex you do the same, but you can use bit shifting because you deal with a whole nibble at a time.
You cannot use a cast in the way you mention. Supposing yout integer_variable = 0x12345678, cast it and pass it to a putchar function, the function will try to print the ASCII value of 0x78, which is the character 'N'.
Cheers,
Adam
Last edited by AJ on Fri May 16, 2008 12:16 pm, edited 1 time in total.
Re: printing integers
You have to make an algorithm up yourself to do it (there are several standard ones out there). You can't do it with a cast - there are a number of steps involved.Woellchen wrote:i have a little problem..
i have a function which prints strings on the screen(puts()) but i want it to print an integer on the screen
but the problem is, that i have to convert the integer first
i dont know how to do so
ive already tried to use a cast like: (char) integer_variable but it doesnt seem to work
i hope u have an answer to that
thanks
ok i have a problem now
i bet its quite easy but i cant fix it
at the moment the code can only handle numbers to 999 but thats not the problem
the code is working actually but the problem is the returning
when i print the text variable in the function itself the number is displayed but when i print the returning theres nothing but some special chars or so
whats wrong with my code, hope you can help me
thanks
i bet its quite easy but i cant fix it
Code: Select all
char longtostr( long zahl )
{
char text[20];
int i = 0;
int c = 0;
if( zahl == 0 ) return "0";
while( zahl >= 100 ) zahl -= 100, ++c;
text[i++] = c + 48, c = 0;
while( zahl >= 10 ) zahl -= 10, ++c;
text[i++] = c + 48, text[i] = zahl + 48;
return text;
}
the code is working actually but the problem is the returning
when i print the text variable in the function itself the number is displayed but when i print the returning theres nothing but some special chars or so
whats wrong with my code, hope you can help me
thanks
That function works, but programmatically, there are simpler ways, for example:
Another solution is to take in an argument for an array + length, then try filling that in, this will make it safe for a multi-threaded environment . So, something like this:
This second one isn't perfect, but much better, you can add checks for max == 0, or max==1 and return an error, or if an overflow condition happens, and max is <5, then you can return an error as well.
How this works:
zahl = 173
zahl % 10 = 3 (remainder of 173 / 10)
zahl / 10 = 17 (integer math)
zahl % 10 = 7
zahl / 10 = 1
zahl % 10 = 1
zahl / 10 = 0
While loops see's zahl = 0, and breaks, so when we placed 3,7,1 into our buffer backwards, forwards it is 173 . This works for any sized number, and is much more intuitive than checking each value, and is also multi-threading safe, since it can work on multiple arrays at a time.
--- Edit ---
Oops, fixed code tags... and code bug(s)
Code: Select all
char* longtostr( long zahl )
{
static char text[20]; //Make me static, otherwise it's on the stack and will screw up soon, if it's static, it's allocated always, but is not safe for multi-tasking/threading.
int loc=19;
text[19] = 0; //NULL terminate the string
while (zahl) //While we have something left, lets add a character to the string
{
--loc;
text[loc] = (zahl%10)+'0';
zahl/=10;
}
if (loc==19) //Nothing, lets at least put a 0 in there!
{
--loc;
text[loc] = '0';
}
return &text[loc]; //Start from where loc left off
}
Code: Select all
void longtostr( long zahl , char *buffer, long max)
{
int tmp, size;
if (!zahl) //check for 0 first thing, assumes max>=2
{
buffer[0] = '0';
buffer[1] = 0;
return;
}
tmp= zahl; //Temporary
size = 0;
while (tmp) //Calculate the size of the string we require
{
tmp/=10;
++size;
}
if (size >= max-1) //Error, overflow, we assume max >= 5 :)
{
buffer[0] = 'O';
buffer[1] = 'v';
buffer[2] = 'f';
buffer[3] = 'l';
buffer[4] = 'w';
buffer[5] = 0;
}
buffer[size] = 0; //Set the size
while (zahl) //While we have something left, lets add a character to the string
{
--size;
buffer[size] = (zahl%10)+'0';
zahl/=10;
}
}
How this works:
zahl = 173
zahl % 10 = 3 (remainder of 173 / 10)
zahl / 10 = 17 (integer math)
zahl % 10 = 7
zahl / 10 = 1
zahl % 10 = 1
zahl / 10 = 0
While loops see's zahl = 0, and breaks, so when we placed 3,7,1 into our buffer backwards, forwards it is 173 . This works for any sized number, and is much more intuitive than checking each value, and is also multi-threading safe, since it can work on multiple arrays at a time.
--- Edit ---
Oops, fixed code tags... and code bug(s)
Last edited by Ready4Dis on Mon May 19, 2008 9:35 pm, edited 4 times in total.
wow thanks ready, its cool that u explain how it works but i already got it out of here: http://www.avrbeginners.net/
my current code is this btw:
and it works
i understand the multitask/thread issue, thank you for that, ill change that
but is my code still acceptable then?
could u do a correction on that?
thank you
my current code is this btw:
Code: Select all
char longtostr( long zahl )
{
char *text = 0;
int i = 0;
int j = 0;
int c = 0;
int s = 0;
long *zahlp = &zahl + 4;
while( *zahlp++ ) s++;
if( zahl == 0 )
{
text[0] = '0';
text[1] = '\0';
return text;
}
for( j = 1 ; j < s + 1 ; j++ )
{
while( zahl >= pow( 10, s - j ) ) zahl -= pow( 10, s - j ), c++;
if( c > 0 ) text[i++] = c + 48, c = 0;
}
text[i++] = zahl + 48;
text[i] = '\0';
return text;
}
i understand the multitask/thread issue, thank you for that, ill change that
but is my code still acceptable then?
u do a while loop with the variable loc, without initialising itwhile (loc) //Calculate the size of the string we require
could u do a correction on that?
thank you
Sorry, fixed it, good catch. I typed it all in the window, cut and paste the first to write the second, and forgot to change the variable name there . Anyways, no problem for the explanation, just wanted to mention that your method, while it may work, it is much less efficient due to the while loop and all the pow calls, where my method runs very fast in all cases.
Couple of issues with your code:
What is with the zahlp. I am not sure what you're trying to do, but it's a bad idea, taking the memory address of an argument to the function will give you a pointer to the stack. the problem is, after your parameter in the stack, it will have the address of the function call, so it will increment until it finds a NULL value in your stack (there may never be one until it over-runs your stack and causes a page fault).
Also, you declare char *text = 0; Then you use it directly, which means you're physicall writing to 0x00000000 in memory, which will over-write your real mode interrupt vector table (fi you don't use v86 or real-mode, this is ok, but just realize that it's not typically considered good programming to write to 0x00000000, since it's typically used to check for NULL). I would suggest using a variant of my method, it is probably one of the most used, and most efficient methods (in C anyways, in ASM you can use a div and get the % for free).
Your coding concerns me, using a NULL pointer, referencing the stack like you are, etc. You may want to get a bit more familiar with how function calls are done (what actually happens on the stack), how memory is treated (pointers, vaiables, local variables, etc), the difference between normal and static variables in functions, etc. It will help you in writing code that doesn't have so many potential problems.
Couple of issues with your code:
What is with the zahlp. I am not sure what you're trying to do, but it's a bad idea, taking the memory address of an argument to the function will give you a pointer to the stack. the problem is, after your parameter in the stack, it will have the address of the function call, so it will increment until it finds a NULL value in your stack (there may never be one until it over-runs your stack and causes a page fault).
Also, you declare char *text = 0; Then you use it directly, which means you're physicall writing to 0x00000000 in memory, which will over-write your real mode interrupt vector table (fi you don't use v86 or real-mode, this is ok, but just realize that it's not typically considered good programming to write to 0x00000000, since it's typically used to check for NULL). I would suggest using a variant of my method, it is probably one of the most used, and most efficient methods (in C anyways, in ASM you can use a div and get the % for free).
Your coding concerns me, using a NULL pointer, referencing the stack like you are, etc. You may want to get a bit more familiar with how function calls are done (what actually happens on the stack), how memory is treated (pointers, vaiables, local variables, etc), the difference between normal and static variables in functions, etc. It will help you in writing code that doesn't have so many potential problems.
yea sorry, the *text = 0 declaration is not really good, but i knew that i have written to 0x00000000
later i had changed it to *text = malloc() or so as soon as i had implented memory management
but i think i will use a variant of yours anyway
and thank you for ur corrections in my code, helps me being better in os-dev
EDIT:
later i had changed it to *text = malloc() or so as soon as i had implented memory management
but i think i will use a variant of yours anyway
and thank you for ur corrections in my code, helps me being better in os-dev
EDIT:
im sure u meantext[size] = (zahl%10)+'0';
dont you?buffer[size] = (zahl%10)+'0';
Yes, again remanents of my copy/paste from above and chaning variable's to be more descriptive. That said, using malloc inside of a function as this will be very wasteful (most memory managers are relatively slow, so allocating and deallocating such small memory buffers will waste a lot of time), it's simpler to just say, it's a 4-byte integer, what's the largest value i can store, then make a buffer that large for it. Depending on if it has to be multi-thread safe, you can use a static buffer, or pass a buffer to it (or as you're doing, allocate the buffer, but then who is responsible to deallocate the buffer? You can't deallocate it until it is displayed, so you would have to remember to store the buffer to delete later, not generally a good thing).
Here is my modified version of one of the methods above. This one will correctly handle negative numbers.
If the number is positive, it will convert it to a negative number, as opposed to converting it to a positive number if it is negative. This allows it to correctly handle the minimum integer value -2,147,483,648.
I also changed the char array to only have 12 elements (minus sign, 10 digits, '\0')
If the number is positive, it will convert it to a negative number, as opposed to converting it to a positive number if it is negative. This allows it to correctly handle the minimum integer value -2,147,483,648.
I also changed the char array to only have 12 elements (minus sign, 10 digits, '\0')
Code: Select all
char* itoa(int i)
{
static char text[12];
int loc = 11;
text[11] = 0;
char neg = 1;
if (i >= 0)
{
neg = 0;
i = -i;
}
while (i)
{
text[--loc] = '0' - (i%10);
i/=10;
}
if (loc==11)
text[--loc] = '0';
if (neg)
text[--loc] = '-';
return &text[loc];
}