I think this is an impossible assignment...could you help?

J

Jack

Ok, here's the deal...my instructor wants us to do the following
program. Only one problem: what must I use to get this program to work
right? Do I use combinations of if, for and while statements, or just
if statements or what? I have tried nested if and while statements and
CANNOT get the program to execute properly... Perhaps an experienced
programmer(unlike myself) could give me a little insight on how to do
this problem...
ANY help would greatly be appreciated. If there's nething i can help
someone else with...i will...THANK YOU

COMSC 1613 Programming I (C) Programming Assignment
3

In this assignment, you will write a 'C' function that will approximate
the action of the command scanf("%d",&x); namely, to read ASCII
character
digits from the standard input stream and convert/interpret the sequence
into a binary integer.

Consider the following implementation of main.

#include
#define INVALID 0x80000000

long scan_int(void); /* the prototype */

int main(void)
{long num, i;
printf("\nenter an integer: ");
for(i=1; (num = scan_int()) != -999; printf("\n\n\nenter an integer: "))
{ if (num == INVALID)
printf("\n you entered an invalid sequence\n");
else
{
printf("\nthe %ld-th integer read was %ld\n", i, num);
++i;
}
}
return (0);

}

Use this main() as a driver. You write function
long scan_int(void);

The function scan_int will use getchar() to read one character at a time
from the standard input and from the digits read compute "on the fly"
the
integer value they represent. The function will return the integer
computed. If the data entered is not appropriate to be interpreted as
an
integer, the function will return INVALID as defined in the program.
White space will be used to mark the beginning and end of a number.

Do not use arrays/strings and do not use atoi() and do not use scanf()
or
fscanf() or any other library functions other than getchar(). Comment
your code thoroughly.

The following is an example execution of the program you will write:

Script command is started on Fri Aug 19 16:19:47 CDT 2011.
$ a.out

enter an integer: 457

the 1-th integer read was 457

enter an integer: -34

the 2-th integer read was -34

enter an integer: +1

the 3-th integer read was 1

enter an integer:

-967835

the 4-th integer read was -967835

enter an integer: 45h5

you entered an invalid sequence

enter an integer: ---56

you entered an invalid sequence

enter an integer: 45+9

you entered an invalid sequence

enter an integer: hello

you entered an invalid sequence

enter an integer: -

you entered an invalid sequence

enter an integer: +

you entered an invalid sequence

enter an integer: -999

$
 
I

Ian Collins

Ok, here's the deal...my instructor wants us to do the following
program. Only one problem: what must I use to get this program to work
right? Do I use combinations of if, for and while statements, or just
if statements or what? I have tried nested if and while statements and
CANNOT get the program to execute properly... Perhaps an experienced
programmer(unlike myself) could give me a little insight on how to do
this problem...
ANY help would greatly be appreciated. If there's nething i can help
someone else with...i will...THANK YOU

COMSC 1613 Programming I (C) Programming Assignment
3

In this assignment, you will write a 'C' function that will approximate
the action of the command scanf("%d",&x); namely, to read ASCII
character
digits from the standard input stream and convert/interpret the sequence
into a binary integer.

Consider the following implementation of main.

#include
#define INVALID 0x80000000

long scan_int(void); /* the prototype */

int main(void)
{long num, i;
printf("\nenter an integer: ");
for(i=1; (num = scan_int()) != -999; printf("\n\n\nenter an integer: "))
{ if (num == INVALID)
printf("\n you entered an invalid sequence\n");
else
{
printf("\nthe %ld-th integer read was %ld\n", i, num);
++i;
}
}
return (0);

What awful style!
}

Use this main() as a driver. You write function
long scan_int(void);

Start of with your own main, calling scan_int for progressively more
complex inputs, starting with one digit, then two or more then add a
sign until you get the complete funtion:

int main(void)
{
long result;

puts("enter 1");

assert( scan_int(void) == 1 );

// start with the return here until this passes.

puts("enter 11");

assert( scan_int(void) == 11 );

// then move it here and so on until all cases work.

puts("enter -1");

assert( scan_int(void) == -1 );

// add more tests here.

return 0;
}
 
J

Jack

Ian --- you may have misudnerstood, the problem is to WRITE this scan_int
function! It is NOT given.
 
J

John Gordon

In said:
Ok, here's the deal...my instructor wants us to do the following
program. Only one problem: what must I use to get this program to work
right? Do I use combinations of if, for and while statements, or just
if statements or what? I have tried nested if and while statements and
CANNOT get the program to execute properly... Perhaps an experienced
programmer(unlike myself) could give me a little insight on how to do
this problem...

A good start would be to show us what you wrote. Perhaps we can explain
where you went wrong.
 
J

Jack

A good start would be to show us what you wrote. Perhaps we can explain
where you went wrong.

John --- Sure. Thought this forum was empty for a while, good to get a
reply at last. I'd like to fix this up by 4PM today!

here is the code I have already written...maybe you could
expand to it a little?

long scan_int(void)
{
int c ; /* character, nb type is int not char to allow EOF */
int sign='+'; /* + for positive number, - for negative */
long sum=0; /* stores sum */

while((c=getchar())==' '); /* whitespace delimeters */

if(c=='-') /* negative */
{sign='-';
c=getchar();
while((c=getchar())==' ');
if(c<'0'||c>'9')
return(INVALID);}

else if(c=='+') /* positive */
{sign='+';
c=getchar();
while((c=getchar())==' ');
if(c<'0'||c>'9')
return(INVALID);}

if(c<'0'||c>'9')
{while(c!=' ') /* space delimeter */
c=getchar();
return(INVALID);}

if(c=='-'||c=='+')
return INVALID;

if(c>='0'&&c<='9')
{while(c>='0'&&c<='9')
{sum=sum*10+(c-48); /* update sum */
c=getchar();}
}

else return(INVALID);

if(sign=='-')
sum=sum*(-1);
return(sum);}
 
J

John Gordon

In said:
John --- Sure. Thought this forum was empty for a while, good to get a
reply at last. I'd like to fix this up by 4PM today!
here is the code I have already written...maybe you could
expand to it a little?

Unfortunately I don't really have the time to make detailed code comments.
But here's a general program flow that might help you:

1. Read and discard whitespace.
2a. If the next char is a minus sign, remember it so you can make the
final return value negative.
2b. Else if the next char is a plus sign, ignore it because we assume
numbers are positive anyway.
3. Read one or more digits, computing the value of sum as we go.
4. Read and discard whitespace.
5. Read and discard a carriage return. (I think you missed this in
your original effort.)
6. Return sum.

At each step in the process, you know what kind of input you're expecting,
and if you get bad input, return INVALID.

Good luck!
 
I

Ian Collins

On 08/31/11 09:20 AM, Jack wrote:

Context?
Ian --- you may have misudnerstood, the problem is to WRITE this scan_int
function! It is NOT given.

No, I didn't. I was suggesting how you should start to write the
function. Start with the most basic case and grow it from there.

This is a classic learning excise for test driven development!
 
K

Keith Thompson

Jack said:
John --- Sure. Thought this forum was empty for a while, good to get a
reply at last. I'd like to fix this up by 4PM today!

here is the code I have already written...maybe you could
expand to it a little?

long scan_int(void)
{
int c ; /* character, nb type is int not char to allow EOF */
int sign='+'; /* + for positive number, - for negative */
long sum=0; /* stores sum */

while((c=getchar())==' '); /* whitespace delimeters */

if(c=='-') /* negative */
{sign='-';
c=getchar();
while((c=getchar())==' ');
if(c<'0'||c>'9')
return(INVALID);}

else if(c=='+') /* positive */
{sign='+';
c=getchar();
while((c=getchar())==' ');
if(c<'0'||c>'9')
return(INVALID);}

if(c<'0'||c>'9')
{while(c!=' ') /* space delimeter */
c=getchar();
return(INVALID);}

if(c=='-'||c=='+')
return INVALID;

if(c>='0'&&c<='9')
{while(c>='0'&&c<='9')
{sum=sum*10+(c-48); /* update sum */
c=getchar();}
}

else return(INVALID);

if(sign=='-')
sum=sum*(-1);
return(sum);}

I find your code layout difficult to read (though not much worse than
the code in your original post, which presumably was from the
assignment).

I've taken the liberty of reformatting it. I have made no semantically
significant changes. I filtered it with "indent -kr", then made a few
more cosmetic changes.

long scan_int(void)
{
int c; /* character, nb type is int not char to
allow EOF */
int sign = '+'; /* + for positive number, - for negative
*/
long sum = 0; /* stores sum */

while ((c = getchar()) == ' ') { /* whitespace delimiters */
/* nothing */
}

if (c == '-') { /* negative */
sign = '-';
c = getchar();
while ((c = getchar()) == ' ') {
/* nothing */
}
if (c < '0' || c > '9') {
return INVALID;
}
}

else if (c == '+') { /* positive */
sign = '+';
c = getchar();
while ((c = getchar()) == ' ') {
/* nothing */
}
if (c < '0' || c > '9') {
return INVALID;
}
}

if (c < '0' || c > '9') {
while (c != ' ') { /* space delimiter */
c = getchar();
}
return INVALID;
}

if (c == '-' || c == '+') {
return INVALID;
}

if (c >= '0' && c <= '9') {
while (c >= '0' && c <= '9') {
sum = sum * 10 + (c - 48); /* update sum */
c = getchar();
}
}

else {
return INVALID;
}

if (sign == '-') {
sum = sum * (-1);
}
return sum;
}

Some comments on the code itself:

Return statements do not require parentheses.

48 is the ASCII encoding for '0', but how is the reader expected to know
that? Just write '0'.

You have a lot of redundancy. For example, the blocks for c == '-' and
c == '+' could be combined.

In the "update sum" block, the "if" is unnecessary. A while loop will
not be executed (or, if you prefer, will iterate 0 times) if the
condition is initially false.

To negate a number, you can use the unary "-" operator; multiplication
by -1 is overkill.
 
B

Ben Bacarisse

Jack said:
John --- Sure. Thought this forum was empty for a while, good to get a
reply at last. I'd like to fix this up by 4PM today!

A reply was posted with in half an hour. That's about as good as you
can expect from Usenet (you may be reading this as a web forum but it is
really a Usenet news group).
here is the code I have already written...maybe you could
expand to it a little?

long scan_int(void)
{
int c ; /* character, nb type is int not char to allow EOF */
int sign='+'; /* + for positive number, - for negative */
long sum=0; /* stores sum */

while((c=getchar())==' '); /* whitespace delimeters */

So far so good but do you really find that easy to read? I'd write it
like this:

long scan_int(void)
{
int c; /* character, nb type is int not char to allow EOF */
int sign = '+'; /* + for positive number, - for negative */
long sum = 0; /* stores sum */

while ((c = getchar()) == ' '); /* whitespace delimeters */

Note the indentation and extra spaces. They get even more significant
later.

On a more important note, ' ' is not the only white space. Look up the
function in the header ctype.h (isspace, etc.) or, if you think you
should not use these yet, write a more complex test.
if(c=='-') /* negative */
{sign='-';
c=getchar();
while((c=getchar())==' ');
if(c<'0'||c>'9')
return(INVALID);}

else if(c=='+') /* positive */
{sign='+';
c=getchar();
while((c=getchar())==' ');
if(c<'0'||c>'9')
return(INVALID);}

I find this very hard to read all jammed-up like that. Do you really
want to accept input like this: " + 99"? scanf's %d format does not
so I suspect you should not do so either.
if(c<'0'||c>'9')
{while(c!=' ') /* space delimeter */
c=getchar();

Are you sure this loop will end? Here's a tip: every time you write a
loop ask if will always end. If you think it will try to prove yourself
*wrong*. If you can't find any way to make the loop go on forever, you
may be safe!
return(INVALID);}

In general, input functions should not read stuff that they don't
understand. If there is non-numeric data you should probably leave it
alone. Unfortunately you are hampered by a terrible specification. If
you do as you are told (emulate scanf and use the given driver) you can
not test non-numeric input because it will be left unread.
if(c=='-'||c=='+')
return INVALID;

if(c>='0'&&c<='9')
{while(c>='0'&&c<='9')
{sum=sum*10+(c-48); /* update sum */

48? Hint: what does this do: printf("%d\n", '0'); ?
c=getchar();}
}

else return(INVALID);

You are very nearly home and dry.

Once you've tidied it up, I think you will find that you can remove a
few of the invalid return tests. It's tempting to return an error as
soon as you know something is wrong, but the code is often easier to
follow if you have fewer tests and later ones will often catch earlier
errors.
if(sign=='-')
sum=sum*(-1);
return(sum);}

You can set sign to anything you like as soon as you see the + or the -
in the input. Given that freedom, can you think of something to set it
to that would simplify this last bit if code?

I've likely missed some tings because the code is all crushed up and not
easy for me to read, but it looks pretty close to done.
 
I

Ian Collins

John --- Sure. Thought this forum was empty for a while, good to get a
reply at last. I'd like to fix this up by 4PM today!

here is the code I have already written...maybe you could
expand to it a little?

long scan_int(void)
{
int c ; /* character, nb type is int not char to allow EOF */
int sign='+'; /* + for positive number, - for negative */
long sum=0; /* stores sum */

In addition to the other comments, most of those comments would be
considered excessive, especially the last one!
 
E

Eric Sosman

Unfortunately I don't really have the time to make detailed code comments.
But here's a general program flow that might help you:

1. Read and discard whitespace.
2a. If the next char is a minus sign, remember it so you can make the
final return value negative.
2b. Else if the next char is a plus sign, ignore it because we assume
numbers are positive anyway.
3. Read one or more digits, computing the value of sum as we go.
4. Read and discard whitespace.
5. Read and discard a carriage return. (I think you missed this in
your original effort.)
6. Return sum.

Steps 4 and 5 seem ill-advised. YMMV.
 
J

John Gordon

Steps 4 and 5 seem ill-advised. YMMV.

The problem spec does explicitly say that numbers will be bounded by
whitespace, although the examples given seem to indicate that it is
optional.

Number 5 should be "carriage return or EOF".
 
I

Ike Naar

if(c=='-') /* negative */
{sign='-';
c=getchar();
while((c=getchar())==' ');

There's one getchar() too many. You discard the character
after the '-' sign without ever looking at it.
E.g. in the input string "-42" the '4' is discarded.

The same happens in the code fragment for '+'.
 
B

BartC

#include
#define INVALID 0x80000000

long scan_int(void); /* the prototype */

int main(void)
{long num, i;
printf("\nenter an integer: ");
for(i=1; (num = scan_int()) != -999; printf("\n\n\nenter an integer: "))
{ if (num == INVALID)
printf("\n you entered an invalid sequence\n");
else
{
printf("\nthe %ld-th integer read was %ld\n", i, num);
++i;
}
}
return (0);

}

Use this main() as a driver. You write function
long scan_int(void);

You may or may not get extra marks by submitting an alternate version of
main() that is easier on the eye. For example:

#include <stdio.h>

#define INVALID 0x80000000
#define ENDCODE -999

long scan_int(void); /* the prototype */

int main(void) {
long num, i=0;

while (1) {

printf("\nEnter an integer (%d to end): ",ENDCODE);

num = scan_int();

if (num == ENDCODE)
return(0);
else if (num == INVALID)
printf("\n You entered an invalid sequence\n");
else
printf("\nThe %ldth integer read was %ld\n", i++, num);
}
}
 
B

blmblm

[ snip ]

Ben, even for beginner programs this level of commenting seems
excessive. The comment about the type of c is not amiss in a
beginner program, but -- what information does "stores sum" provide
that the variable name doesn't?? (I notice that I am not the only
person to comment on this, um, comment.)

[ snip ]
Do you really
want to accept input like this: " + 99"? scanf's %d format does not
so I suspect you should not do so either.

But it seems apparent from the example execution that this function
is not supposed to behave *exactly* like scanf, and in fact the
overall description says that the desired function will "approximate"
the behavior of scanf (and apparently the treatment of errors is one
reason to say "approximate" rather than "emulate").

[ snip ]
In general, input functions should not read stuff that they don't
understand. If there is non-numeric data you should probably leave it
alone. Unfortunately you are hampered by a terrible specification. If
you do as you are told (emulate scanf and use the given driver) you can
not test non-numeric input because it will be left unread.

I guess it all depends on what you think "approximate" means. :)
See above.

Another problem with the specification, IMO anyway, is that it
disallows a legitimate "int" value, namely -2147483648 (0x8000000).
Then again, a function that takes no arguments and returns an int --
well, the options for signalling that an error has occurred do seem
kind of limited.

[ snip ]
 
B

blmblm

You may or may not get extra marks by submitting an alternate version of
main() that is easier on the eye. For example:

"May or may not" indeed. Sort of a :) here. Some instructors
respond better than others to students "improving" (or actually
improving) their code.
#include <stdio.h>

#define INVALID 0x80000000
#define ENDCODE -999

long scan_int(void); /* the prototype */

int main(void) {
long num, i=0;

while (1) {

Normally I'd vote for putting the assignment to num in the loop
condition, but in this case your approach avoids duplicating the
prompt, so -- a win, maybe.
printf("\nEnter an integer (%d to end): ",ENDCODE);

IMO changing the prompt to include the stop value is quite an
improvement, and I wonder why the original program didn't!
 
K

Keith Thompson

John Gordon said:
The problem spec does explicitly say that numbers will be bounded by
whitespace, although the examples given seem to indicate that it is
optional.

Number 5 should be "carriage return or EOF".

Note that a carriage return (or newline; is that what was meant?) *is*
whitespace.
 
J

John Gordon

In said:
Note that a carriage return (or newline; is that what was meant?) *is*
whitespace.

Sure. But if you're reading keyboard input and you don't differentiate
between newline and other kinds of whitespace, how would you ever know
that the user pressed Enter thus signaling end-of-input?
 
K

Keith Thompson

John Gordon said:
Sure. But if you're reading keyboard input and you don't differentiate
between newline and other kinds of whitespace, how would you ever know
that the user pressed Enter thus signaling end-of-input?

The same way scanf("%d", &i) does, perhaps? It returns as soon as
numeric input is finished, so it doesn't distinguish between a space and
a newline.

On the other hand, if you want to enforce one number per input line, the
specification should say something like "skip whitespace other than
newline".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top