By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,492 Members | 3,174 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,492 IT Pros & Developers. It's quick & easy.

User Input issue

P: n/a
n3o
Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
...
}

now we know that the int data type uses 4 bytes of memory. Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner. To be more specific,
let's say that the programmer wants a real number meaning that they do
not want floating point numbers. If that is the case, we know that by
just changing the data type of 'num' to double would not solve the
issue for a specific reason which I will explain in a minute. Also, by
changing the data type of, 'num,' to long int would not solve the
issue either. Why? long int uses 4 bytes just like int, and double,
which is not what the programmer wants in this instance, uses 8 bytes.
Therefore, if someone could guide me as to how I can fix this minor
problem, I would really appreciate it greatly. But, now that I think
of it, if I make 'num' a double, is it possible to type cast 'num' to
an int data type so that the 'num' will output as a whole number with
no decimal number? Also, just as a sidenote, I know that I can use
either a C-style string or C++ string and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.

n3o

Oct 2 '07 #1
Share this Question
Share on Google+
14 Replies


P: n/a
n3o wrote:
Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
Unless you terminate the string with a newline the output might not appear
immediately. Alternatively you can also call fflush on the stream.
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
The diagnostic is not required by the Standard, so it a QoI issue. Also as
you can see C++ style comments tend to break when posted to Usenet. Also
some compilers under certain switches cannot compile code containing them.
...
}
Stylistically I prefer a return statement to falling of the end.
now we know that the int data type uses 4 bytes of memory.
No. This is not specified by the Standard. An int has to be at least of 16
bits but could be anything more, 24 bit, 32 bit, 64 bit and other sizes are
common.
Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.
Presumably.
To be more specific,
let's say that the programmer wants a real number meaning that they do
not want floating point numbers.
Huh?
If that is the case, we know that by
just changing the data type of 'num' to double would not solve the
issue for a specific reason which I will explain in a minute. Also, by
changing the data type of, 'num,' to long int would not solve the
issue either. Why? long int uses 4 bytes just like int, and double,
which is not what the programmer wants in this instance, uses 8 bytes.

None of your assumptions regarding the size of types are mandated by the
Standard. A long has to be at least 32 bits while a double could be
anywhere from 32 to 96 or more bits depending on the implementation.
Therefore, if someone could guide me as to how I can fix this minor
problem, I would really appreciate it greatly. But, now that I think
of it, if I make 'num' a double, is it possible to type cast 'num' to
an int data type so that the 'num' will output as a whole number with
no decimal number?
In C the term is cast and you don't need to do that, since casting a
floating type to an integer type might involve undefined behaviour if the
integer type is not big enough to hold the double's value. Just round the
double to the nearest whole number and print it out.
Also, just as a sidenote, I know that I can use
either a C-style string or C++ string
No. If you use anything from C++, then your code becomes C++. Consult on
comp.lang.c++. Interaction between C and C++ is subtle and involved.
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.
The scanf family of functions are your only choice if you cannot use
strings. If the value read by scanf is too big for the object in question
then the behaviour is undefined. Usually you'll get garbage values.

A more robust solution is to read in the value as a string with fgets and
convert it with strtol or strtod. These functions indicate when they are
unable to convert the value. Unfortunately you are apparently prohibited
from using them.

My advice is to use either one of long, unsigned long, long long, unsigned
long long, double or long double, depending on your exact needs and
availability and inform the user of the maximum possible value when
prompting for input. For non-interactive input there is no way, given your
restrictions, against overflow or wrap-around. The ranges of these types
are found in limits.h and float.h

Oct 2 '07 #2

P: n/a
n3o
On Oct 2, 1:06 pm, santosh <santosh....@gmail.comwrote:
n3o wrote:
Hello Comp.Lang.C Members,
I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:
void foo()
{
int num;
printf("Please enter a number: ");

Unless you terminate the string with a newline the output might not appear
immediately. Alternatively you can also call fflush on the stream.
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)

The diagnostic is not required by the Standard, so it a QoI issue. Also as
you can see C++ style comments tend to break when posted to Usenet. Also
some compilers under certain switches cannot compile code containing them.
...
}

Stylistically I prefer a return statement to falling of the end.
now we know that the int data type uses 4 bytes of memory.

No. This is not specified by the Standard. An int has to be at least of 16
bits but could be anything more, 24 bit, 32 bit, 64 bit and other sizes are
common.
Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.

Presumably.
To be more specific,
let's say that the programmer wants a real number meaning that they do
not want floating point numbers.

Huh?
If that is the case, we know that by
just changing the data type of 'num' to double would not solve the
issue for a specific reason which I will explain in a minute. Also, by
changing the data type of, 'num,' to long int would not solve the
issue either. Why? long int uses 4 bytes just like int, and double,
which is not what the programmer wants in this instance, uses 8 bytes.

None of your assumptions regarding the size of types are mandated by the
Standard. A long has to be at least 32 bits while a double could be
anywhere from 32 to 96 or more bits depending on the implementation.
Therefore, if someone could guide me as to how I can fix this minor
problem, I would really appreciate it greatly. But, now that I think
of it, if I make 'num' a double, is it possible to type cast 'num' to
an int data type so that the 'num' will output as a whole number with
no decimal number?

In C the term is cast and you don't need to do that, since casting a
floating type to an integer type might involve undefined behaviour if the
integer type is not big enough to hold the double's value. Just round the
double to the nearest whole number and print it out.
Also, just as a sidenote, I know that I can use
either a C-style string or C++ string

No. If you use anything from C++, then your code becomes C++. Consult on
comp.lang.c++. Interaction between C and C++ is subtle and involved.
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.

The scanf family of functions are your only choice if you cannot use
strings. If the value read by scanf is too big for the object in question
then the behaviour is undefined. Usually you'll get garbage values.

A more robust solution is to read in the value as a string with fgets and
convert it with strtol or strtod. These functions indicate when they are
unable to convert the value. Unfortunately you are apparently prohibited
from using them.

My advice is to use either one of long, unsigned long, long long, unsigned
long long, double or long double, depending on your exact needs and
availability and inform the user of the maximum possible value when
prompting for input. For non-interactive input there is no way, given your
restrictions, against overflow or wrap-around. The ranges of these types
are found in limits.h and float.h
Ok I really appreciate this. I will go ahead and include what you have
said. Although these programs are very basic, I believe that when I do
something, I do it to my full potential. And that's another topic
within itself that is outside the parameters of this community.

n3o
"You can't consider the problem of defense without first understanding
the problem of attack."

Oct 2 '07 #3

P: n/a
n3o wrote On 10/02/07 13:35,:
Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
...
}

now we know that the int data type uses 4 bytes of memory.
On your machine, perhaps, but not on all.
Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.
It produces "undefined behavior." That is, the C
language does not specify what scanf() will do if the
input is out of range, and different implementations of
C will behave differently.
To be more specific,
let's say that the programmer wants a real number meaning that they do
not want floating point numbers.
I'm not sure what you mean. If you mean that you
want the user to be able to enter arbitrary real numbers
like pi or e or even phi, you are out of luck: C has no
built-in support for such values.
If that is the case, we know that by
just changing the data type of 'num' to double would not solve the
issue for a specific reason which I will explain in a minute.
You wrote a moment ago that the programmer does not
want floating-point numbers. In C, `double' is a floating-
point number, so why are you even considering it?
Also, by
changing the data type of, 'num,' to long int would not solve the
issue either. Why? long int uses 4 bytes just like int,
Again, this may be true of your machine but is not
true of all.
and double,
which is not what the programmer wants in this instance, uses 8 bytes.
Tru of your machine, but not necessarily of all.
Therefore, if someone could guide me as to how I can fix this minor
problem, I would really appreciate it greatly.
What is the "problem" you want fixed? Adding the
ability to handle arbitrary real numbers is probably
not possible: computers are finite machines and thus
can only deal with a finite number of distinct values.

If the "problem" is to read numbers that are too
large or small for "%d" there may be ways to improve a
bit. But moving the boundaries does not eliminate them;
there will still be numbers too large or too small for
whatever conversion scheme you use, and the behavior of
scanf() when it encounters such numbers will still be
undefined.
But, now that I think
of it, if I make 'num' a double, is it possible to type cast 'num' to
an int data type so that the 'num' will output as a whole number with
no decimal number?
If all you need to do is print the `double' value
rounded to an integer, just leave it as a `double' and
use "%.0f" instead of just "%f".
Also, just as a sidenote, I know that I can use
either a C-style string or C++ string
Not in C, you can't.
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.
You could, I suppose, read characters one at a time
with getc() or one of its relatives, and develop the value
of the number as you go. That would avoid the ban on not
using strings, because by handling just one character at
a time, in isolation from others, you would form no strings.
Seems a pretty silly exercise, though.

--
Er*********@sun.com
Oct 2 '07 #4

P: n/a
"Eric Sosman" <Er*********@sun.coma crit dans le message de news:
1191351673.631251@news1nwk...
n3o wrote On 10/02/07 13:35,:
>Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
...
}

now we know that the int data type uses 4 bytes of memory.

On your machine, perhaps, but not on all.
>Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.

It produces "undefined behavior." That is, the C
language does not specify what scanf() will do if the
input is out of range, and different implementations of
C will behave differently.
<snip>
>Also, just as a sidenote, I know that I can use
either a C-style string or C++ string
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.

You could, I suppose, read characters one at a time
with getc() or one of its relatives, and develop the value
of the number as you go. That would avoid the ban on not
using strings, because by handling just one character at
a time, in isolation from others, you would form no strings.
Seems a pretty silly exercise, though.
Actually, it seems like a pretty interesting exercice for the OP.
Write a function that takes a FILE * and a pointer to an integer type, make
it read the steam and parse it as an decimal integer as per strtol, detect
and return an error code upon overflow, leave extra characters in the
stream, do not use a char array. The hard part will be "detect overflow"
portably without causing it ;-)

--
Chqrlie.
Oct 2 '07 #5

P: n/a
n3o wrote:
>
I have an issue with user input that I have been trying to figure
out for the longest. For instance, let's say you have something
like this:

void foo() {
int num;
printf("Please enter a number: ");
scanf("%d", &num);
...
}

now we know that the int data type uses 4 bytes of memory. Let's
say the user enters a number that exceeds the minimum/maximum size
the int data type can hold.
No we don't know about '4 bytes'. The number will be "sizeof int",
and the number of bits will be that multiplied by CHAR_BIT (found
in limits.h). foo() is not completely specified either - specify
the parameters, either by type or by void (if none).

Ignoring the above, scanf is a generally terrible way to handle
interactive input. It is just barely usable if you check its error
code. Something like:

if (1 != scanf("%d", &num) {
/* whatever is needed to recover from an input failure */
}
else {
/* correct input, now handle the line ending or whatever */
}
/* by now you probably have a valid value to work with */

I prefer to use my own input routines that interact correctly with
streams, need no extra buffers (like scanf) and have clearly
defined error actions (as does scanf, but try to discover those
actions when needed).

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Oct 2 '07 #6

P: n/a
Charlie Gordon wrote:
>
.... snip ...
>
Actually, it seems like a pretty interesting exercice for the OP.
Write a function that takes a FILE * and a pointer to an integer
type, make it read the steam and parse it as an decimal integer
as per strtol, detect and return an error code upon overflow,
leave extra characters in the stream, do not use a char array.
The hard part will be "detect overflow" portably without causing
it ;-)
Here they are. Slightly later version than on my webpage.

/* ------------------------------------------------- *
* File txtinput.c *
* ------------------------------------------------- */

#include <limits.h /* xxxx_MAX, xxxx_MIN */
#include <ctype.h /* isdigit, isblank, isspace */
#include <stdio.h /* FILE, getc, ungetc */
#include "txtinput.h"

/* For licensing restrictions (GPL) see readme.txt in:
* <http://cbfalconer.home.att.net/download/txtio.zip>
*
* These stream input routines are written so that simple
* conditionals can be used:
*
* if (readxint(&myint, stdin)) {
* do_error_recovery; normally_abort_to_somewhere;
* }
* else {
* do_normal_things; usually_much_longer_than_bad_case;
* }
*
* They allow overflow detection, and permit other routines to
* detect the character that terminated a numerical field. No
* string storage is required, thus there is no limitation on
* the length of input fields. For example, a number entered
* with a string of 1000 leading zeroes will not annoy these.
*
* The numerical input routines *NEVER* absorb a terminating
* char (including '\n'). Thus a sequence such as:
*
* err = readxint(&myint, stdin);
* flushln(stdin);
*
* will always consume complete lines, and after execution of
* readxint a further getc (or fgetc) will return the character
* that terminated the numeric field.
*
* They are also re-entrant, subject to the limitations of file
* systems. e.g interrupting readxint(v, stdin) operation with
* a call to readxwd(wd, stdin) would not be well defined, if
* the same stdin is being used for both calls. If ungetc is
* interruptible the run-time system is broken.
*
* Originally issued 2002-10-07
*
* Revised 2006-01-15 so that unsigned entry overflow (readxwd)
uses the normal C modulo (UINT_MAX + 1) operation. readxwd
still rejects an initial sign as an error.
*/

/* -------------------------------------------------------------
* Skip to non-blank on f, and return that char. or EOF The next
* char that getc(f) will return is unknown. Local use only.
*/
static int ignoreblks(FILE *f)
{
int ch;

do {
ch = getc(f);
} while ((' ' == ch) || ('\t' == ch));
/* while (isblank(ch)); */ /* for C99 */
return ch;
} /* ignoreblks */

/*--------------------------------------------------------------
* Skip all blanks on f. At completion getc(f) will return
* a non-blank character, which may be \n or EOF
*
* Skipblks returns the char that getc will next return, or EOF.
*/
int skipblks(FILE *f)
{
return ungetc(ignoreblks(f), f);
} /* skipblks */

/*--------------------------------------------------------------
* Skip all whitespace on f, including \n, \f, \v, \r. At
* completion getc(f) will return a non-blank character, which
* may be EOF
*
* Skipwhite returns the char that getc will next return, or EOF.
*/
int skipwhite(FILE *f)
{
int ch;

do {
ch = getc(f);
} while (isspace(ch));
return ungetc(ch, f);
} /* skipwhite */

/*--------------------------------------------------------------
* Read an unsigned value. Signal error for overflow or no
* valid number found. Returns 1 for error, 0 for noerror, EOF
* for EOF encountered before parsing a value.
*
* Skip all leading blanks on f. At completion getc(f) will
* return the character terminating the number, which may be \n
* or EOF among others. Barring EOF it will NOT be a digit. The
* combination of error, 0 result, and the next getc returning
* \n indicates that no numerical value was found on the line.
*
* If the user wants to skip all leading white space including
* \n, \f, \v, \r, he should first call "skipwhite(f);"
*
* Peculiarity: This specifically forbids a leading '+' or '-'.
*/
int readxwd(unsigned int *wd, FILE *f)
{
unsigned int value, digit;
int status;
int ch;

#define UWARNLVL (UINT_MAX / 10U)
#define UWARNDIG (UINT_MAX - UWARNLVL * 10U)

value = 0; /* default */
status = 1; /* default error */

ch = ignoreblks(f);

if (EOF == ch) status = EOF;
else if (isdigit(ch)) status = 0; /* digit, no error */

while (isdigit(ch)) {
digit = ch - '0';
if ((value UWARNLVL) ||
((UWARNLVL == value) && (digit UWARNDIG))) {
status = 1; /* overflow */
value -= UWARNLVL;
}
value = 10 * value + digit;
ch = getc(f);
} /* while (ch is a digit) */

*wd = value;
ungetc(ch, f);
return status;
} /* readxwd */

/*--------------------------------------------------------------
* Read a signed value. Signal error for overflow or no valid
* number found. Returns true for error, false for noerror. On
* overflow either INT_MAX or INT_MIN is returned in *val.
*
* Skip all leading blanks on f. At completion getc(f) will
* return the character terminating the number, which may be \n
* or EOF among others. Barring EOF it will NOT be a digit. The
* combination of error, 0 result, and the next getc returning
* \n indicates that no numerical value was found on the line.
*
* If the user wants to skip all leading white space including
* \n, \f, \v, \r, he should first call "skipwhite(f);"
*
* Peculiarity: an isolated leading '+' or '-' NOT immediately
* followed by a digit will return error and a value of 0, when
* the next getc will return that following non-digit. This is
* caused by the single level ungetc available.
*/
int readxint(int *val, FILE *f)
{
unsigned int value;
int status, negative;
int ch;

*val = value = 0; /* default */
status = 1; /* default error */
negative = 0;

ch = ignoreblks(f);

if (EOF != ch) {
if (('+' == ch) || ('-' == ch)) {
negative = ('-' == ch);
ch = ignoreblks(f); /* absorb any sign */
}

if (isdigit(ch)) { /* digit, no error */
ungetc(ch, f);
status = readxwd(&value, f);
ch = getc(f); /* This terminated readxwd */
}

if (0 == status) {
/* got initial digit and no readxwd overflow */
if (!negative && (value <= INT_MAX))
*val = value;
else if (negative && (value < UINT_MAX) &&
((value - 1) <= -(1 + INT_MIN)))
*val = -value;
else { /* overflow */
status = 1; /* do whatever the native system does */
if (negative) *val = -value;
else *val = value;
}
}
else if (negative) *val = -value;
else *val = value;
}
ungetc(ch, f);
return status;
} /* readxint */

/*-----------------------------------------------------
* Flush input through an end-of-line marker inclusive.
*/
void flushln(FILE *f)
{
int ch;

do {
ch = getc(f);
} while (('\n' != ch) && (EOF != ch));
} /* flushln */

/* End of txtinput.c */

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Oct 3 '07 #7

P: n/a
CBFalconer said:
n3o wrote:
>>
I have an issue with user input that I have been trying to figure
out for the longest. For instance, let's say you have something
like this:

void foo() {
int num;
printf("Please enter a number: ");
scanf("%d", &num);
...
}

now we know that the int data type uses 4 bytes of memory. Let's
say the user enters a number that exceeds the minimum/maximum size
the int data type can hold.

No we don't know about '4 bytes'. The number will be "sizeof int",
Close. It'll be

sizeof num

or

sizeof(int)

- the sizeof keyword takes /either/ an expression /or/ a parenthesised
type.

and the number of bits will be that multiplied by CHAR_BIT (found
in limits.h).
....and if that product turns out to be greater than 16, the object might
contain padding bits.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 3 '07 #8

P: n/a
In data Tue, 2 Oct 2007 23:14:56 +0200, Charlie Gordon scrisse:
>"Eric Sosman" <Er*********@sun.coma crit dans le message de news:
1191351673.631251@news1nwk...
>n3o wrote On 10/02/07 13:35,:
>>Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
...
}

now we know that the int data type uses 4 bytes of memory.

On your machine, perhaps, but not on all.
>>Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.

It produces "undefined behavior." That is, the C
language does not specify what scanf() will do if the
input is out of range, and different implementations of
C will behave differently.
<snip>
>>Also, just as a sidenote, I know that I can use
either a C-style string or C++ string
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.

You could, I suppose, read characters one at a time
with getc() or one of its relatives, and develop the value
of the number as you go. That would avoid the ban on not
using strings, because by handling just one character at
a time, in isolation from others, you would form no strings.
Seems a pretty silly exercise, though.

Actually, it seems like a pretty interesting exercice for the OP.
Write a function that takes a FILE * and a pointer to an integer type, make
it read the steam and parse it as an decimal integer as per strtol, detect
and return an error code upon overflow, leave extra characters in the
stream, do not use a char array. The hard part will be "detect overflow"
portably without causing it ;-)
i'm not agree with you and CBF

why the behaviour not has to be this:

if the number not fit in the data object than push back all digits of
the last number in the FILE for conserve the stream not in error

Oct 3 '07 #9

P: n/a
a\/b wrote:
In data Tue, 2 Oct 2007 23:14:56 +0200, Charlie Gordon scrisse:
<snip>
>>Actually, it seems like a pretty interesting exercice for the OP.
Write a function that takes a FILE * and a pointer to an integer type,
make it read the steam and parse it as an decimal integer as per strtol,
detect and return an error code upon overflow, leave extra characters in
the stream, do not use a char array. The hard part will be "detect
overflow" portably without causing it ;-)

i'm not agree with you and CBF

why the behaviour not has to be this:

if the number not fit in the data object than push back all digits of
the last number in the FILE for conserve the stream not in error
Only one character of pushback is guaranteed by the C Standard.

Oct 3 '07 #10

P: n/a
In data Wed, 03 Oct 2007 10:00:04 +0200, a\/b scrisse:
>In data Tue, 2 Oct 2007 23:14:56 +0200, Charlie Gordon scrisse:
>>"Eric Sosman" <Er*********@sun.coma crit dans le message de news:
1191351673.631251@news1nwk...
>>n3o wrote On 10/02/07 13:35,:
Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
...
}

now we know that the int data type uses 4 bytes of memory.

On your machine, perhaps, but not on all.

Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.

It produces "undefined behavior." That is, the C
language does not specify what scanf() will do if the
input is out of range, and different implementations of
C will behave differently.
<snip>
>>>Also, just as a sidenote, I know that I can use
either a C-style string or C++ string
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.

You could, I suppose, read characters one at a time
with getc() or one of its relatives, and develop the value
of the number as you go. That would avoid the ban on not
using strings, because by handling just one character at
a time, in isolation from others, you would form no strings.
Seems a pretty silly exercise, though.

Actually, it seems like a pretty interesting exercice for the OP.
Write a function that takes a FILE * and a pointer to an integer type, make
it read the steam and parse it as an decimal integer as per strtol, detect
and return an error code upon overflow, leave extra characters in the
stream, do not use a char array. The hard part will be "detect overflow"
portably without causing it ;-)

i'm not agree with you and CBF

why the behaviour not has to be this:

if the number not fit in the data object than push back all digits of
the last number in the FILE for conserve the stream not in error
i not remember well, it seems only the last char is ungetted,

if there is some error for get that number from the stream than the
stream flag for _FAIL is on
where goto==G and return==R

istream& operator>>(istream& istr, int& b)
{int ch, i;
uns state, base;

if( istr.f->flag & _FAIL ) G li;
base=10;
if(istr.flag & is_m::hex) base=16;
else if(istr.flag & is_m::oct) base= 8;
i=fgeti_m(istr.f, &ch, &state, base);
if(state!=0) istr.f->flag|=_FAIL;
else b=i;
li:;
R istr;
}

; uns __stdcall fgeti_m(FILE_m* pf, int* ch, uns* state, uns basen)
; legge un numero da "pf" e lo ritorna con formato
; |spaces||+ or -|<digits>
; *ch il prossimo carattere che si trovera' a leggere
; *ch==EOF <=errore o EOF nello stream
; nello stream tranne nel caso "bit_3" "bit_2" set
; di "*state"
; *state == bit_0 1 numero non preso, se altri flag non settati
; significa errore di parametro e lo stream
; non toccato
; *state == bit_1 2 overflow; overflow+ ritorna 0x7FFFFFFF=int_max
; overflow- ritorna 0x80000000=int_min
; *state == bit_2 4 impossibile riallocazione stream
; non sanabile
; *state == bit_3 8 impossibile riallocazione stream
; sanabile con ch
; 0k, 4k, 8i, 12r, 16c, 20b, 24Ra,
; 28P_pf, 32P_ch, 36P_state, 40P_basen
fgeti_m:
push ebx
push ecx
push edx
push esi
push ebp
push ebp
%define @pf [esp+28]
%define @ch [esp+32]
%define @state [esp+36]
%define @basen [esp+40]
%define @cnt 0
%define @ptr 4
%define @base 8
%define @flag 12
%define @fd 16
xor edx, edx
mov ebx, @state
mov ecx, @basen
cmp dword @state, 0
je .e1
mov dword[ebx], 0
mov esi, @pf
cmp dword @ch, 0
je .e0
cmp ecx, 36
ja .e0
cmp ecx, 1
jbe .e0
cmp esi, 0
je .e0
..c0:
push esi
call _fgetc_m
add esp, 4
cmp eax, -1
je .ce
mov ebp, eax
and eax, 0xFF
cmp dword[is+4*eax], 3
je .c0

mov dword[esp], 0
jmp short .b0
..ce:
mov ebx, @ch
mov [ebx], eax
..e0:
mov eax, @state
or dword[eax], 1
..e1:
mov eax, 0
jmp .cf
..b0:
mov eax, ebp
and eax, 0xFF
cmp al, '+'
jne .c1
..b1:
push esi
call _fgetc_m
add esp, 4
mov dl, al
cmp [tab+4*edx], ecx
jb .a3
push esi
push edx
call ungetc_m
jnc .a0
or dword[ebx], 4
mov eax, edx
jmp short .ce
..a0:
jmp short .a4
..a3:
mov ebp, edx
jmp short .c2
..c1:
cmp al, '-'
jne .b2
mov dword[esp], 1
jmp short .b1
..b2:
cmp [tab+4*eax], ecx
jb .c2
..a4:
push esi
push ebp
call ungetc_m
jnc .a5
or dword[ebx], 8
mov eax, ebp
..a5:
jmp .ce
..c2:
mov eax, ebp
..c4:
xor ebx, ebx
mov bl, al
xor eax, eax
jmp short .a6
..c5:
push eax
push esi
call _fgetc_m
add esp, 4
mov ebp, eax
mov bl, al
pop eax
..a6:
mov edx, [tab+4*ebx]
cmp edx, ecx
jae .c8
mov ebx, edx
mul ecx
cmp edx, 0
jne .ci
add eax, ebx
jc .ci
test eax, 0x80000000
jnz .ci
jmp short .c5
..ci: ;/ stato overflow
mov eax, 0x7FFFFFFF
mov edx, @state
or dword[edx], 2
..c6:
push eax
push esi
call _fgetc_m
add esp, 4
mov ebp, eax
mov bl, al
pop eax
cmp [tab+4*ebx], ecx
jb .c6
..c8:
mov ebx, eax
mov edx, @state
push esi
push ebp
call ungetc_m
jnc .c9
or dword[edx], 8
..c9:
cmp dword[esp], 1
jne .ca
neg ebx
test dword[edx], 2
jz .ca
dec ebx
..ca:
mov edx, @ch
mov [edx], ebp
mov eax, ebx
..cf:
%undef @cnt
%undef @ptr
%undef @base
%undef @flag
%undef @fd
%undef @pf
%undef @ch
%undef @state
%undef @basen
pop ebp
pop ebp
pop esi
pop edx
pop ecx
pop ebx
ret 16
/* uns __stdcall fgeti_m(FILE_m* pf, int* ch, uns* state, uns basen)
/* legge un numero da "pf" e lo ritorna con formato
/* |spaces||+ or -|<digits>
/* *ch il prossimo carattere che si trovera' a leggere
/* *ch==EOF <=errore o EOF nello stream
/* nello stream tranne nel caso "bit_3" "bit_2" set
/* di "*state"
/* *state == bit_0 1 numero non preso, se altri flag non settati
/* significa errore di parametro e lo stream
/* non toccato
/* *state == bit_1 2 overflow; overflow+ ritorna 0x7FFFFFFF=int_max
/* overflow- ritorna 0x80000000=int_min
/* *state == bit_2 4 impossibile riallocazione stream
/* non sanabile
/* *state == bit_3 8 impossibile riallocazione stream
/* sanabile con ch
/* 0k, 4k, 8i, 12r, 16c, 20b, 24Ra,
/* 28P_pf, 32P_ch, 36P_state, 40P_basen
fgeti_m:
< b, c, r, i, k, k
<< @pf=[s+28], @ch=[s+32], @state=[s+36], @basen=[s+40]
<< @cnt=0, @ptr=4, @base=8, @flag=12, @fd=16
r^=r; b=@state; c=@basen; D @state==0#.e1;
D*b=0; i=@pf; D @ch==0#.e0; c>36#.e0;
c<=1#.e0; i==0#.e0;
..c0: { _fgetc_m<(i); a==-1#.ce; k=a;
a&=0xFF; D[is+4*a]==3#.c0;
}
D*s=0; #.b0;
..ce: b=@ch; *b =a;
..e0: a=@state; D*a|=1;
..e1: a=0; ##.cf;
..b0: a=k; a&=0xFF; al=='+'!#.c1
..b1: _fgetc_m<(i);
rl=al;
[tab+4*r]<c#.a3;
ungetc_m(r, i);
jnc .a0| D*b|=4; a=r; #.ce;
..a0: #.a4;
..a3: k=r; #.c2;
..c1: al=='-'!#.b2| D*s=1; #.b1;
..b2: [tab+4*a]>=c!#.c2;
..a4: ungetc_m(k, i);
jnc .a5| D*b|=8; a=k;
..a5: ##.ce
..c2: a=k;
..c4: b^=b; bl=al; a^=a; #.a6;
..c5: < a | _fgetc_m<(i); k=a; bl=al | a;
..a6: r=[tab+4*b]; r>=c#.c8;
b= r;
mul c; r#.ci;
a+=b; jc .ci;
a&0x80000000| jnz .ci;
#.c5;
..ci: a=0x7FFFFFFF; r=@state; D*r|=2; // stato overflow
..c6: {< a| _fgetc_m<(i); k=a; bl=al | a; [tab+4*b]<c#.c6}
..c8: b=a; r=@state;
ungetc_m(k, i); jnc .c9 | D*r|=8;
..c9: D*s==1!#.ca| neg b; D*r&2!#.ca; --b;
..ca: r=@ch; *r=k; a=b;
..cf:
> @cnt, @ptr, @base, @flag, @fd
@pf, @ch, @state, @basen
b, c, r, i, k, k
ret 16
Oct 4 '07 #11

P: n/a
In data Wed, 03 Oct 2007 10:00:04 +0200, a\/b scrisse:
>In data Tue, 2 Oct 2007 23:14:56 +0200, Charlie Gordon scrisse:
>>"Eric Sosman" <Er*********@sun.coma crit dans le message de news:
1191351673.631251@news1nwk...
>>n3o wrote On 10/02/07 13:35,:
Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
...
}

now we know that the int data type uses 4 bytes of memory.

On your machine, perhaps, but not on all.

Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.

It produces "undefined behavior." That is, the C
language does not specify what scanf() will do if the
input is out of range, and different implementations of
C will behave differently.
<snip>
>>>Also, just as a sidenote, I know that I can use
either a C-style string or C++ string
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.

You could, I suppose, read characters one at a time
with getc() or one of its relatives, and develop the value
of the number as you go. That would avoid the ban on not
using strings, because by handling just one character at
a time, in isolation from others, you would form no strings.
Seems a pretty silly exercise, though.

Actually, it seems like a pretty interesting exercice for the OP.
Write a function that takes a FILE * and a pointer to an integer type, make
it read the steam and parse it as an decimal integer as per strtol, detect
and return an error code upon overflow, leave extra characters in the
stream, do not use a char array. The hard part will be "detect overflow"
portably without causing it ;-)

i'm not agree with you and CBF

why the behaviour not has to be this:

if the number not fit in the data object than push back all digits of
the last number in the FILE for conserve the stream not in error
i not remember well, it seems only the last char is ungetted,

if there is some error for get that number from the stream than the
stream flag for _FAIL is on
where goto==G and return==R

istream& operator>>(istream& istr, int& b)
{int ch, i;
uns state, base;

if( istr.f->flag & _FAIL ) G li;
base=10;
if(istr.flag & is_m::hex) base=16;
else if(istr.flag & is_m::oct) base= 8;
i=fgeti_m(istr.f, &ch, &state, base);
if(state!=0) istr.f->flag|=_FAIL;
else b=i;
li:;
R istr;
}

; uns __stdcall fgeti_m(FILE_m* pf, int* ch, uns* state, uns basen)
; legge un numero da "pf" e lo ritorna con formato
; |spaces||+ or -|<digits>
; *ch il prossimo carattere che si trovera' a leggere
; *ch==EOF <=errore o EOF nello stream
; nello stream tranne nel caso "bit_3" "bit_2" set
; di "*state"
; *state == bit_0 1 numero non preso, se altri flag non settati
; significa errore di parametro e lo stream
; non toccato
; *state == bit_1 2 overflow; overflow+ ritorna 0x7FFFFFFF=int_max
; overflow- ritorna 0x80000000=int_min
; *state == bit_2 4 impossibile riallocazione stream
; non sanabile
; *state == bit_3 8 impossibile riallocazione stream
; sanabile con ch
; 0k, 4k, 8i, 12r, 16c, 20b, 24Ra,
; 28P_pf, 32P_ch, 36P_state, 40P_basen
fgeti_m:
push ebx
push ecx
push edx
push esi
push ebp
push ebp
%define @pf [esp+28]
%define @ch [esp+32]
%define @state [esp+36]
%define @basen [esp+40]
%define @cnt 0
%define @ptr 4
%define @base 8
%define @flag 12
%define @fd 16
xor edx, edx
mov ebx, @state
mov ecx, @basen
cmp dword @state, 0
je .e1
mov dword[ebx], 0
mov esi, @pf
cmp dword @ch, 0
je .e0
cmp ecx, 36
ja .e0
cmp ecx, 1
jbe .e0
cmp esi, 0
je .e0
..c0:
push esi
call _fgetc_m
add esp, 4
cmp eax, -1
je .ce
mov ebp, eax
and eax, 0xFF
cmp dword[is+4*eax], 3
je .c0

mov dword[esp], 0
jmp short .b0
..ce:
mov ebx, @ch
mov [ebx], eax
..e0:
mov eax, @state
or dword[eax], 1
..e1:
mov eax, 0
jmp .cf
..b0:
mov eax, ebp
and eax, 0xFF
cmp al, '+'
jne .c1
..b1:
push esi
call _fgetc_m
add esp, 4
mov dl, al
cmp [tab+4*edx], ecx
jb .a3
push esi
push edx
call ungetc_m
jnc .a0
or dword[ebx], 4
mov eax, edx
jmp short .ce
..a0:
jmp short .a4
..a3:
mov ebp, edx
jmp short .c2
..c1:
cmp al, '-'
jne .b2
mov dword[esp], 1
jmp short .b1
..b2:
cmp [tab+4*eax], ecx
jb .c2
..a4:
push esi
push ebp
call ungetc_m
jnc .a5
or dword[ebx], 8
mov eax, ebp
..a5:
jmp .ce
..c2:
mov eax, ebp
..c4:
xor ebx, ebx
mov bl, al
xor eax, eax
jmp short .a6
..c5:
push eax
push esi
call _fgetc_m
add esp, 4
mov ebp, eax
mov bl, al
pop eax
..a6:
mov edx, [tab+4*ebx]
cmp edx, ecx
jae .c8
mov ebx, edx
mul ecx
cmp edx, 0
jne .ci
add eax, ebx
jc .ci
test eax, 0x80000000
jnz .ci
jmp short .c5
..ci: ;/ stato overflow
mov eax, 0x7FFFFFFF
mov edx, @state
or dword[edx], 2
..c6:
push eax
push esi
call _fgetc_m
add esp, 4
mov ebp, eax
mov bl, al
pop eax
cmp [tab+4*ebx], ecx
jb .c6
..c8:
mov ebx, eax
mov edx, @state
push esi
push ebp
call ungetc_m
jnc .c9
or dword[edx], 8
..c9:
cmp dword[esp], 1
jne .ca
neg ebx
test dword[edx], 2
jz .ca
dec ebx
..ca:
mov edx, @ch
mov [edx], ebp
mov eax, ebx
..cf:
%undef @cnt
%undef @ptr
%undef @base
%undef @flag
%undef @fd
%undef @pf
%undef @ch
%undef @state
%undef @basen
pop ebp
pop ebp
pop esi
pop edx
pop ecx
pop ebx
ret 16
/* uns __stdcall fgeti_m(FILE_m* pf, int* ch, uns* state, uns basen)
/* legge un numero da "pf" e lo ritorna con formato
/* |spaces||+ or -|<digits>
/* *ch il prossimo carattere che si trovera' a leggere
/* *ch==EOF <=errore o EOF nello stream
/* nello stream tranne nel caso "bit_3" "bit_2" set
/* di "*state"
/* *state == bit_0 1 numero non preso, se altri flag non settati
/* significa errore di parametro e lo stream
/* non toccato
/* *state == bit_1 2 overflow; overflow+ ritorna 0x7FFFFFFF=int_max
/* overflow- ritorna 0x80000000=int_min
/* *state == bit_2 4 impossibile riallocazione stream
/* non sanabile
/* *state == bit_3 8 impossibile riallocazione stream
/* sanabile con ch
/* 0k, 4k, 8i, 12r, 16c, 20b, 24Ra,
/* 28P_pf, 32P_ch, 36P_state, 40P_basen
fgeti_m:
< b, c, r, i, k, k
<< @pf=[s+28], @ch=[s+32], @state=[s+36], @basen=[s+40]
<< @cnt=0, @ptr=4, @base=8, @flag=12, @fd=16
r^=r; b=@state; c=@basen; D @state==0#.e1;
D*b=0; i=@pf; D @ch==0#.e0; c>36#.e0;
c<=1#.e0; i==0#.e0;
..c0: { _fgetc_m<(i); a==-1#.ce; k=a;
a&=0xFF; D[is+4*a]==3#.c0;
}
D*s=0; #.b0;
..ce: b=@ch; *b =a;
..e0: a=@state; D*a|=1;
..e1: a=0; ##.cf;
..b0: a=k; a&=0xFF; al=='+'!#.c1
..b1: _fgetc_m<(i);
rl=al;
[tab+4*r]<c#.a3;
ungetc_m(r, i);
jnc .a0| D*b|=4; a=r; #.ce;
..a0: #.a4;
..a3: k=r; #.c2;
..c1: al=='-'!#.b2| D*s=1; #.b1;
..b2: [tab+4*a]>=c!#.c2;
..a4: ungetc_m(k, i);
jnc .a5| D*b|=8; a=k;
..a5: ##.ce
..c2: a=k;
..c4: b^=b; bl=al; a^=a; #.a6;
..c5: < a | _fgetc_m<(i); k=a; bl=al | a;
..a6: r=[tab+4*b]; r>=c#.c8;
b= r;
mul c; r#.ci;
a+=b; jc .ci;
a&0x80000000| jnz .ci;
#.c5;
..ci: a=0x7FFFFFFF; r=@state; D*r|=2; // stato overflow
..c6: {< a| _fgetc_m<(i); k=a; bl=al | a; [tab+4*b]<c#.c6}
..c8: b=a; r=@state;
ungetc_m(k, i); jnc .c9 | D*r|=8;
..c9: D*s==1!#.ca| neg b; D*r&2!#.ca; --b;
..ca: r=@ch; *r=k; a=b;
..cf:
> @cnt, @ptr, @base, @flag, @fd
@pf, @ch, @state, @basen
b, c, r, i, k, k
ret 16

don't this post appear good :) ?

Oct 5 '07 #12

P: n/a
On 2007-10-02 18:06, santosh <sa*********@gmail.comwrote:
n3o wrote:
>long int uses 4 bytes just like int, and double, which is not what
the programmer wants in this instance, uses 8 bytes.

None of your assumptions regarding the size of types are mandated by the
Standard. A long has to be at least 32 bits while a double could be
anywhere from 32 to 96 or more bits depending on the implementation.
A double needs to be able to hold at least 10 decimal digits in the
mantissa, which takes at least 33 bits. Add the exponent, and you get
about 42 bits as the minimum for a double.

hp
--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Oct 6 '07 #13

P: n/a
In data Wed, 03 Oct 2007 10:00:04 +0200, a\/b scrisse:
>In data Tue, 2 Oct 2007 23:14:56 +0200, Charlie Gordon scrisse:
>>"Eric Sosman" <Er*********@sun.coma crit dans le message de news:
1191351673.631251@news1nwk...
>>n3o wrote On 10/02/07 13:35,:
Hello Comp.Lang.C Members,

I have an issue with user input that I have been trying to figure out
for the longest. For instance, let's say you have something like this:

void foo()
{
int num;
printf("Please enter a number: ");
scanf("%d", &num); // yes I know this function may throw a
warning with some compilers (MSVC++ 8.0)
...
}

now we know that the int data type uses 4 bytes of memory.

On your machine, perhaps, but not on all.

Let's say
the user enters a number that exceeds the minimum/maximum size the int
data type can hold. This would be considered a bug and would cause the
program to function in an innappropriate manner.

It produces "undefined behavior." That is, the C
language does not specify what scanf() will do if the
input is out of range, and different implementations of
C will behave differently.
<snip>
>>>Also, just as a sidenote, I know that I can use
either a C-style string or C++ string
and then use the stdlib header
to convert the string to an integer which would solve this little
problem that I have been having with user input, however, I am not
allowed to use such a technique because my Computer Science
programming instructor told me not to use strings since we have not
covered strings yet (I'm a college freshman in a Programming I/Novice
Programming course, although I should be in a higher level CS course
but that's irrelavent at this moment in time.) Therefore, I would like
some guidance as to what functions/implementations I could use that
DOES NOT use strings, that would control the use of oversizing a data-
type; exceeding the maximum/minimum size that a data type can hold.

You could, I suppose, read characters one at a time
with getc() or one of its relatives, and develop the value
of the number as you go. That would avoid the ban on not
using strings, because by handling just one character at
a time, in isolation from others, you would form no strings.
Seems a pretty silly exercise, though.

Actually, it seems like a pretty interesting exercice for the OP.
Write a function that takes a FILE * and a pointer to an integer type, make
it read the steam and parse it as an decimal integer as per strtol, detect
and return an error code upon overflow, leave extra characters in the
stream, do not use a char array. The hard part will be "detect overflow"
portably without causing it ;-)

i'm not agree with you and CBF

why the behaviour not has to be this:

if the number not fit in the data object than push back all digits of
the last number in the FILE for conserve the stream not in error
i not remember well, it seems only the last char is ungetted,

if there is some error for get that number from the stream than the
stream flag for _FAIL is on
where goto==G and return==R

istream& operator>>(istream& istr, int& b)
{int ch, i;
uns state, base;

if( istr.f->flag & _FAIL ) G li;
base=10;
if(istr.flag & is_m::hex) base=16;
else if(istr.flag & is_m::oct) base= 8;
i=fgeti_m(istr.f, &ch, &state, base);
if(state!=0) istr.f->flag|=_FAIL;
else b=i;
li:;
R istr;
}

; uns __stdcall fgeti_m(FILE_m* pf, int* ch, uns* state, uns basen)
; legge un numero da "pf" e lo ritorna con formato
; |spaces||+ or -|<digits>
; *ch il prossimo carattere che si trovera' a leggere
; *ch==EOF <=errore o EOF nello stream
; nello stream tranne nel caso "bit_3" "bit_2" set
; di "*state"
; *state == bit_0 1 numero non preso, se altri flag non settati
; significa errore di parametro e lo stream
; non toccato
; *state == bit_1 2 overflow; overflow+ ritorna 0x7FFFFFFF=int_max
; overflow- ritorna 0x80000000=int_min
; *state == bit_2 4 impossibile riallocazione stream
; non sanabile
; *state == bit_3 8 impossibile riallocazione stream
; sanabile con ch
; 0k, 4k, 8i, 12r, 16c, 20b, 24Ra,
; 28P_pf, 32P_ch, 36P_state, 40P_basen
fgeti_m:
push ebx
push ecx
push edx
push esi
push ebp
push ebp
%define @pf [esp+28]
%define @ch [esp+32]
%define @state [esp+36]
%define @basen [esp+40]
%define @cnt 0
%define @ptr 4
%define @base 8
%define @flag 12
%define @fd 16
xor edx, edx
mov ebx, @state
mov ecx, @basen
cmp dword @state, 0
je .e1
mov dword[ebx], 0
mov esi, @pf
cmp dword @ch, 0
je .e0
cmp ecx, 36
ja .e0
cmp ecx, 1
jbe .e0
cmp esi, 0
je .e0
..c0:
push esi
call _fgetc_m
add esp, 4
cmp eax, -1
je .ce
mov ebp, eax
and eax, 0xFF
cmp dword[is+4*eax], 3
je .c0

mov dword[esp], 0
jmp short .b0
..ce:
mov ebx, @ch
mov [ebx], eax
..e0:
mov eax, @state
or dword[eax], 1
..e1:
mov eax, 0
jmp .cf
..b0:
mov eax, ebp
and eax, 0xFF
cmp al, '+'
jne .c1
..b1:
push esi
call _fgetc_m
add esp, 4
mov dl, al
cmp [tab+4*edx], ecx
jb .a3
push esi
push edx
call ungetc_m
jnc .a0
or dword[ebx], 4
mov eax, edx
jmp short .ce
..a0:
jmp short .a4
..a3:
mov ebp, edx
jmp short .c2
..c1:
cmp al, '-'
jne .b2
mov dword[esp], 1
jmp short .b1
..b2:
cmp [tab+4*eax], ecx
jb .c2
..a4:
push esi
push ebp
call ungetc_m
jnc .a5
or dword[ebx], 8
mov eax, ebp
..a5:
jmp .ce
..c2:
mov eax, ebp
..c4:
xor ebx, ebx
mov bl, al
xor eax, eax
jmp short .a6
..c5:
push eax
push esi
call _fgetc_m
add esp, 4
mov ebp, eax
mov bl, al
pop eax
..a6:
mov edx, [tab+4*ebx]
cmp edx, ecx
jae .c8
mov ebx, edx
mul ecx
cmp edx, 0
jne .ci
add eax, ebx
jc .ci
test eax, 0x80000000
jnz .ci
jmp short .c5
..ci: ;/ stato overflow
mov eax, 0x7FFFFFFF
mov edx, @state
or dword[edx], 2
..c6:
push eax
push esi
call _fgetc_m
add esp, 4
mov ebp, eax
mov bl, al
pop eax
cmp [tab+4*ebx], ecx
jb .c6
..c8:
mov ebx, eax
mov edx, @state
push esi
push ebp
call ungetc_m
jnc .c9
or dword[edx], 8
..c9:
cmp dword[esp], 1
jne .ca
neg ebx
test dword[edx], 2
jz .ca
dec ebx
..ca:
mov edx, @ch
mov [edx], ebp
mov eax, ebx
..cf:
%undef @cnt
%undef @ptr
%undef @base
%undef @flag
%undef @fd
%undef @pf
%undef @ch
%undef @state
%undef @basen
pop ebp
pop ebp
pop esi
pop edx
pop ecx
pop ebx
ret 16
/* uns __stdcall fgeti_m(FILE_m* pf, int* ch, uns* state, uns basen)
/* legge un numero da "pf" e lo ritorna con formato
/* |spaces||+ or -|<digits>
/* *ch il prossimo carattere che si trovera' a leggere
/* *ch==EOF <=errore o EOF nello stream
/* nello stream tranne nel caso "bit_3" "bit_2" set
/* di "*state"
/* *state == bit_0 1 numero non preso, se altri flag non settati
/* significa errore di parametro e lo stream
/* non toccato
/* *state == bit_1 2 overflow; overflow+ ritorna 0x7FFFFFFF=int_max
/* overflow- ritorna 0x80000000=int_min
/* *state == bit_2 4 impossibile riallocazione stream
/* non sanabile
/* *state == bit_3 8 impossibile riallocazione stream
/* sanabile con ch
/* 0k, 4k, 8i, 12r, 16c, 20b, 24Ra,
/* 28P_pf, 32P_ch, 36P_state, 40P_basen
fgeti_m:
< b, c, r, i, k, k
<< @pf=[s+28], @ch=[s+32], @state=[s+36], @basen=[s+40]
<< @cnt=0, @ptr=4, @base=8, @flag=12, @fd=16
r^=r; b=@state; c=@basen; D @state==0#.e1;
D*b=0; i=@pf; D @ch==0#.e0; c>36#.e0;
c<=1#.e0; i==0#.e0;
..c0: { _fgetc_m<(i); a==-1#.ce; k=a;
a&=0xFF; D[is+4*a]==3#.c0;
}
D*s=0; #.b0;
..ce: b=@ch; *b =a;
..e0: a=@state; D*a|=1;
..e1: a=0; ##.cf;
..b0: a=k; a&=0xFF; al=='+'!#.c1
..b1: _fgetc_m<(i);
rl=al;
[tab+4*r]<c#.a3;
ungetc_m(r, i);
jnc .a0| D*b|=4; a=r; #.ce;
..a0: #.a4;
..a3: k=r; #.c2;
..c1: al=='-'!#.b2| D*s=1; #.b1;
..b2: [tab+4*a]>=c!#.c2;
..a4: ungetc_m(k, i);
jnc .a5| D*b|=8; a=k;
..a5: ##.ce
..c2: a=k;
..c4: b^=b; bl=al; a^=a; #.a6;
..c5: < a | _fgetc_m<(i); k=a; bl=al | a;
..a6: r=[tab+4*b]; r>=c#.c8;
b= r;
mul c; r#.ci;
a+=b; jc .ci;
a&0x80000000| jnz .ci;
#.c5;
..ci: a=0x7FFFFFFF; r=@state; D*r|=2; // stato overflow
..c6: {< a| _fgetc_m<(i); k=a; bl=al | a; [tab+4*b]<c#.c6}
..c8: b=a; r=@state;
ungetc_m(k, i); jnc .c9 | D*r|=8;
..c9: D*s==1!#.ca| neg b; D*r&2!#.ca; --b;
..ca: r=@ch; *r=k; a=b;
..cf:
> @cnt, @ptr, @base, @flag, @fd
@pf, @ch, @state, @basen
b, c, r, i, k, k
ret 16

don't this post appear good :) ?

so there are no comment to this 'masterpice' of code? :)))
Oct 13 '07 #14

P: n/a
In data Sat, 13 Oct 2007 20:43:01 +0200, a\/b scrisse:
>don't this post appear good :) ?

so there are no comment to this 'masterpice' of code? :)))
it is a joke, that can not be a masterpiece of code for many of you
(but compare how i code it could be for me)
it appear almost everyone had kill filter me
Oct 16 '07 #15

This discussion thread is closed

Replies have been disabled for this discussion.