Problem using sscanf fgets and overflow checking

This is a discussion on Problem using sscanf fgets and overflow checking within the C Programming forums, part of the General Programming Boards category; Hi,
I have trouble using sscanf and fgets to check for overflow.
I will post the assignment specification so I ...

Problem using sscanf fgets and overflow checking

Hi,
I have trouble using sscanf and fgets to check for overflow.
I will post the assignment specification so I could help whoever would kindly like to offer his/her help.

__________________________________________________

1) The program should expect 2 decimal integers per line. Let's call these n1 and n2.
2) For each such input line it should output the value of n1 + 2 * n2 (followed by a newline character '\n').
3) If there are not 2 integers on the line or there is something other than exactly 2 integers other than whitespace, the corresponding output should be the line "illegal input".

4) If the input is legal but the entered n1 or n2 or the calculated output value would be greater than the maximum long int value, then the corresponding output should be "overflow".
5) If it would be less than the minimum (i.e. most negative) long int value, then the corresponding output should be "underflow".

• You can assume that the input line does not contain the null char '\0';
• You can also assume that no legal input line is longer than 50 characters (not counting the '\n' character). If such a line is encountered, the output should be "illegal input".

RESTRICTION: n1 and n2 should be declared to be "long int". Do not try to use a "larger type" to detect overflow/underflow. Instead, use the return values, etc. to detect overflow/underflow.

You are expected to use appropriate functions in your assignments. For example, reading the input one character at a time here is not appropriate.

__________________________________________________

Now to my question. I have trouble checking if the input line is longer than 50 characters using fgets and sscanf.
Same with overflow. How do I check if n1 or n2 is overflow/underflow? As for the calculated result I think I could manage that.
I guess I would check if n1 > LONG_MAX - n2.

I think I will be able to do the program by reading character by character but the point of this assignment is to use tools such as sscanf fgets strlen and so on...

I have this assignment due in 2 days and I will appreciate any comments, hints, help before then?

It seems the matter is a bit more complex. Even i was surprised as it had never occurred to me a need to check for arithmetic overflows. I found the following very informative, although a bit advanced page.http://www.fefe.de/intof.html
I think you need the simple solutions at the start...

1. if input line is longer than the buffer provided - fgets will not store \n character - so just check its present in the resulting buffer
2. to check that n1 and n2 are out of range - scan them with sscanf, check the return value to be sure that both values are parsed, check the position with &#37;n to see that the parsing stopped at \n character, then sprintf them back to the temp buffer and compare the 2 buffers to see that numbers are parsed ok
3. do not forget - you need 2*n2

To xuftugulus:
True this advanced but very useful, thank you. I even bookmarked the page
But unfortunately it doesn't help my question.

To vart
Thank you very much for your reply.

1. if input line is longer than the buffer provided - fgets will not store \n character - so just check its present in the resulting buffer

I figured that out just before I read your comment and was very glad you confirmed it and I added an extra step to check that there is nothing other than two integers. I posted the code I wrote so far below (commented) so whoever have a similar question can benefit from it and I will be glad if you can skim through it.

3. do not forget - you need 2*n2

Thank you

2. to check that n1 and n2 are out of range - scan them with sscanf, check the return value to be sure that both values are parsed, check the position with &#37;n to see that the parsing stopped at \n character, then sprintf them back to the temp buffer and compare the 2 buffers to see that numbers are parsed ok

Unfortunately, I still can't check n1 and n2 for over/underflow. I understood the idea that I have to reconstruct the input into a string using the variables "n1" and "n2" right after executing sscanf and then use strcmp on the two strings.
So it would be something like this
sprintf(tempstr, "%ld %ld", n1, n2);
Now the problems I faced with this method is how to reconstruct the string to be exactly the same? For instance how to I deal with white space? I might be able to trim the two strings from all white spaces before comparison but even then how do I deal with inputs like?
> 00000001111 00003
or this
> +123 --3
n1 and n2 wouldn't obviously have all the zeros neither the positive and double negation signs stored in.

While reading the man page of sprintf I saw this modifier you talked about %n and though it would be useful. I still don't know how to use it though (even after an extensive google search)?
I get a Bus Error with
sprintf(tempstr, "%ld %ld %n", n1, n2, %n3); /*n3 is an int*/

As promised here is my code below:

Code:

#include <stdio.h>
#include <limits.h>
#include <inttypes.h>
#include <string.h>
#define MAX 50 /* MAX is 50 since I can assume that no legal input is more than 50 chars excluding the \n */
long n1, n2;
int c;
char str[MAX+2];
/* This is the string where I will store the input.
I added 2 to MAX to leave room for the new line character as well as for the (null) character
which is added automatically after fgets execution. */
int main(void)
{
if (fgets(str, MAX + 2, stdin) == str) /* To check if fgets ran..successfully..*/
{
if (str[strlen(str)-1] == '\n')
/* I subtracted 1 from strlen to get to the character before the null which should be \n */
{
if (sscanf(str, "%ld %ld %1s", &n1, &n2, %c) == 2)
{
if(c == '\0')
{
if n1 and n2 is not over/underflow /* I am stuck with this part */
{
if (n1 > LONG_MAX - (2*n2))
printf("overflow\n");
if (n1 < LONG_MIN - (2*n2))
printf("underflow\n");
else
printf("%d\n", n1 + (2*n2));
}
}
else
{
printf("illegal input\n");
}
}
else
{
printf("illegal input\n");
}
}
else
{
printf("illegal input\n");
}
}
if (fgets(str, MAX + 2, stdin) == '\0')
/* This means that we have reached EOF so we need to check for illegal input of more than 50 char differently
becuase there might not be a \n */
{
if(strlen(str) <= MAX)
{
/* I will call a function with the above code which starts with if n1 and n2 ... */
}
else
{
printf("illegal input\n");
}
}
else
{
printf("illegal input\n");
}
return 0;
}

One option would be to NOT use sscanf(), but rather parse the string yourself, and use strtol() - as this allows for overflow checking (it clamps the number to the range MIN_LONG..MAX_LONG, and sets errno to "ERANGE" [I think]) - it also gives you a pointer back to the character where it stopped parsing, which you can check if it's at the end of the string or not [e.g. on a space, '\n' or '\0' character, depending on the circumstance) - you could also use the "parsed to" pointer to find the next string to parse, as strtol() will allow whitespace at the beginning of the string.