OSDev.org

The Place to Start for Operating System Developers
It is currently Wed May 08, 2024 4:50 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: printing integers
PostPosted: Fri May 16, 2008 10:58 am 
Offline
User avatar

Joined: Sat Apr 26, 2008 1:19 pm
Posts: 19
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


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 16, 2008 12:15 pm 
Offline
Member
Member
User avatar

Joined: Sun Oct 22, 2006 7:01 am
Posts: 2646
Location: Devon, UK
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


Last edited by AJ on Fri May 16, 2008 12:16 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: printing integers
PostPosted: Fri May 16, 2008 12:15 pm 
Offline
Member
Member
User avatar

Joined: Tue Jul 10, 2007 5:27 am
Posts: 2935
Location: York, United Kingdom
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


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.

_________________
Horizon - a framework and language for SAS-OS development
Project 'Pedigree'
Practical x86 OSDev tutorials


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 16, 2008 1:30 pm 
Offline
User avatar

Joined: Sat Apr 26, 2008 1:19 pm
Posts: 19
wow thanks this link helps me very much
ill write my own algorithm now
thanks ;)


Top
 Profile  
 
 Post subject:
PostPosted: Sat May 17, 2008 5:39 pm 
Offline
User avatar

Joined: Sat Apr 26, 2008 1:19 pm
Posts: 19
ok i have a problem now
i bet its quite easy but i cant fix it

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


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


Top
 Profile  
 
 Post subject:
PostPosted: Sat May 17, 2008 5:45 pm 
Offline
Member
Member
User avatar

Joined: Thu Jan 04, 2007 3:29 pm
Posts: 1466
Location: Noricum and Pannonia
You're returning a char array, but your declaration is only for a char.

Try listening to your warnings. ;)

_________________
C8H10N4O2 | #446691 | Trust the nodes.


Top
 Profile  
 
 Post subject:
PostPosted: Sat May 17, 2008 6:09 pm 
Offline
User avatar

Joined: Sat Apr 26, 2008 1:19 pm
Posts: 19
oh yeah, ure right
i changed the text variable to a pointer and now it works ;)
thank you very much for your help


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 19, 2008 12:32 am 
Offline
Member
Member

Joined: Sat Nov 18, 2006 9:11 am
Posts: 571
That function works, but programmatically, there are simpler ways, for example:

Code:
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
}


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:

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


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)


Last edited by Ready4Dis on Mon May 19, 2008 9:35 pm, edited 4 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon May 19, 2008 8:16 am 
Offline
User avatar

Joined: Sat Apr 26, 2008 1:19 pm
Posts: 19
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:

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

and it works ;)
i understand the multitask/thread issue, thank you for that, ill change that
but is my code still acceptable then?

Quote:
while (loc) //Calculate the size of the string we require

u do a while loop with the variable loc, without initialising it
could u do a correction on that?

thank you


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 19, 2008 10:08 am 
Offline
Member
Member

Joined: Sat Nov 18, 2006 9:11 am
Posts: 571
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.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 19, 2008 12:23 pm 
Offline
User avatar

Joined: Sat Apr 26, 2008 1:19 pm
Posts: 19
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:
Quote:
text[size] = (zahl%10)+'0';

im sure u mean
Quote:
buffer[size] = (zahl%10)+'0';

dont you?


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 19, 2008 9:40 pm 
Offline
Member
Member

Joined: Sat Nov 18, 2006 9:11 am
Posts: 571
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).


Top
 Profile  
 
 Post subject:
PostPosted: Sat May 24, 2008 9:43 pm 
Offline

Joined: Sat May 24, 2008 9:26 pm
Posts: 1
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')

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


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group