Hi,

I need to read unsigned integer and I want to read it number by number. I did this function. But it has "one bug". It can't read number like 4 294 967 295. Max what it reads is like 4 294 967 29. It's because I multiplied it by ten and then divided by 10 at end of function.

I didn't figured any other way of programming this function.

I don't want to use scanf or any other function. I need to scan it number by number because if it's bigger than ULONG_MAX it will stop getting another number. Than it will calculate some my other things.

All I want is some hint how to read number like 4 294 967 295 (32-bit ULONG_MAX) number by number using getchar(). Eventually some hint how to recognize "overflow" or how it's named when using unsigned integer.


This code is pretty lame, I didn't do any test if I am reading numbers from stdin, etc. It's not on my task list at this time.

#include <stdio.h>

unsigned long int readNumbersByGetchar()
{
  unsigned long int thisNumber = 0, i = 0;

  while ((i = getchar()) != '\n')   /*I am reading it until end of line*/
  {
    thisNumber *= 10;             /*At the start I multiply it by 10, at first passage it's 0x10*/
    i = (i - 48);                 /*Because of definition of ASCII code, ASCII 48 == 0*/
    thisNumber += (i*10);         /*I multiply read number by 10 and than I add it to variable thisNumber 
                                   *which was multiplied by 10 before*/
  }
  thisNumber /= 10;               /*At end of reading whole number from stdin I divide it by 10*/
  printf("%lu", thisNumber);      /*Just for my testing*/
  return thisNumber;              /*Return thisNumber to function*/
}

You could try something like below

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

unsigned long int readNumbersByGetchar()
{
  unsigned long int thisNumber = 0, i = 0;	

  while ((i = getchar()) != '\n')  
  {
	if (isdigit(i))
	{
	  thisNumber *= 10;
	  thisNumber += atoi((char*)&i);/*This only works for Intel/AMD type integers*/
	}
  }              
  return thisNumber;              
}

int main(int argc, char**argv)
{
  fprintf(stdout, "ans->%lu\n", readNumbersByGetchar());
  return 0;
}

/*
 18 446 744 073 709 551 615 - 64 bit Max value
 */

You could try something like below

thisNumber += atoi((char*)&i);/*This only works for Intel/AMD type integers*/

atoi() only works on c-strings, not on characters. ZedChu's original code was better: i = (i - 48); , though his loop is incorrect.

while ((i = getchar()) != '\n') 
{
    thisNumber *= 10;      // this is good
    i = (i - 48);          // this is OK.  Instead of 48, use '0'
    thisNumber += (i*10);  // why are you multiplying the digit by 10?
}
thisNumber /= 10;          // why are you dividing the value by 10?

If you aren't sure, desk check your loop to see if it's processing your input properly.

atoi() only works on c-strings, not on characters.

Actually if you think about this, it is a c-string for an Itel/AMD type integer.

int i = getchar();
thisNumber += atoi((char*)&i);

If the user types a number say 5 then i(the int i) will be 0x35,0x0,0x0,0x0. So if you take the address of i you'll have a c-string...Yeah I know its a terrible hack but I did mention it in the remarks.

Edited 5 Years Ago by gerard4143: n/a

Yeah I know its a terrible hack but I did mention it in the remarks.

Umm, yeah. It's so terrible let's not use it anymore. OK? :icon_wink:

atoi() only works on c-strings, not on characters. ZedChu's original code was better: i = (i - 48); , though his loop is incorrect.

while ((i = getchar()) != '\n') 
{
    thisNumber *= 10;      // this is good
    i = (i - 48);          // this is OK.  Instead of 48, use '0'
    thisNumber += (i*10);  // why are you multiplying the digit by 10?
}
thisNumber /= 10;          // why are you dividing the value by 10?

If you aren't sure, desk check your loop to see if it's processing your input properly.

Let me explain it. Shhh...I can't explain it :) I am lame, sorry. I was probably tired that night when I did that code. Because I don't know how could I do something that stupid - multiplying and then dividing. Thanks for helping.

Now it reads whole ULONG_MAX 32Bit number - 4 294 967 295. And when I put number 4 294 967 296 (+1 from ULONG_MAX) it reads it like 0. How can I make protection for overflow?

I though about something like if read number is bigger than ULONG_MAX -> stop reading and use number before. So for number 4 294 967 296 it would use just 4 294 967 29. Can you give me hint how can I make something like that? Or something that would just write some message when it's bigger than ULONG_MAX. Thanks anyway

This article has been dead for over six months. Start a new discussion instead.