473,657 Members | 2,430 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How to sscanf return integer only

I have the following code:

sscanf(line, "%d", n_ptr) !=1 || n_ptr <=0;

It only partially works. If the user types a character other than 0-9 to
start the string it fails. However as long as the first character is an
integer it will allow letters in the following places

for Example:

H78 (fails as expected)
78 (works as expected)
7H8 ( doesn't fail as desired)


May 5 '06 #1
17 3468
On 2006-05-05, Yogi_Bear_79 <no****@spamsux .com> wrote:
I have the following code:

sscanf(line, "%d", n_ptr) !=1 || n_ptr <=0;

It only partially works. If the user types a character other than 0-9 to
start the string it fails. However as long as the first character is an
integer it will allow letters in the following places

for Example:

H78 (fails as expected)
78 (works as expected)
7H8 ( doesn't fail as desired)


But there _is_ an integer - 7. there's then stuff after the integer.

and what's "|| n_ptr <=0" supposed to do?
May 5 '06 #2
But there _is_ an integer - 7. there's then stuff after the integer.
It needs to fail if there are any characters other than integers or white
space

and what's "|| n_ptr <=0" supposed to do?


Not needed, removed, same results
May 5 '06 #3
On Thu, 4 May 2006 20:23:56 -0400, "Yogi_Bear_ 79" <no****@spamsux .com>
wrote:
I have the following code:

sscanf(line, "%d", n_ptr) !=1 || n_ptr <=0;
The third argument needs an & but I assume that is a typo.

If you want to know whether the data at line is a "well formed"
integer, use strtol which will tell you where it stopped extracting
data. Then examine that char for white space or '\0'.

It only partially works. If the user types a character other than 0-9 to
start the string it fails. However as long as the first character is an
integer it will allow letters in the following places

for Example:

H78 (fails as expected)
78 (works as expected)
7H8 ( doesn't fail as desired)


Remove del for email
May 5 '06 #4
Yogi_Bear_79 wrote:
But there _is_ an integer - 7. there's then stuff after the integer.


It needs to fail if there are any characters other than integers or white
space

and what's "|| n_ptr <=0" supposed to do?


Not needed, removed, same results


sscanf isn't the best tool for the job for a couple of reasons, not the
least of which is that trying to convert a number of too large a
magnitude results in undefined behavior.

The following program will read a line at a time from stdin and attempt
to convert it to an integer using the strtol function. If the line
contains any invalid characters, an error message is displayed and the
offending character is pointed out. If a range error occurs (the
number was too large/small to store in a long int), an appropriate
message is diaplayed. This version uses 'long int' and accepts
negative numbers, remove the minus sign from the string of allowed
characters if you just want to accept positive numbers. The code is a
little verbose since it implements error checking.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define BUF_MAX 80

int main (void) {
char buf[BUF_MAX];
long l;
size_t s;
while(fgets(buf , BUF_MAX, stdin) != NULL) {
if ((s = strspn(buf, "-0123456789 \t\n")) == strlen(buf)) {
errno = 0;
l = strtol(buf, NULL, 10);
if (errno == ERANGE) {
printf("number out of range!\n");
} else {
printf("number read was %ld\n", l);
}
} else {
while(s--)
putchar(' ');
putchar('^');
printf(" invalid character\n");
}
}
return 0;
}

The strspn function returns the number of characters in the input
string that are in the "allow" string, this must be the same as the
length of the string itself if all the characters are valid, otherwise
we print an error message displaying the location of the offending
character and continue.

The strtol function will skip leading whitespace and attempt to convert
the numeric part of the string to a long int. If an underflow or
overflow occurs then strtol returns LONG_MIN or LONG_MAX respectively
and sets errno to ERANGE. We just check errno and print an error if
appropriate, you could compare l to LONG_MIN or LONG_MAX to determine
the type of range error if desired.

If everything goes well, the converted number is displayed.

A couple of notes:

If the input consists of multiple numbers seperated by whitespace, only
the first one will be converted, you didn't specify what should happen
in this case.

If the input contains only of whitespace or the minus sign the
converted value will be 0.

Entering more than BUF_MAX characters at a time may cause unintended
(but not undefined) behavior.

If an invalid input line contains a tab character before the invalid
character, the error message may not correctly point to the invalid
character.

Addressing these caveats is left as an exercise to the reader.

Robert Gamble

May 5 '06 #5
Barry Schwarz wrote:
On Thu, 4 May 2006 20:23:56 -0400, "Yogi_Bear_ 79" <no****@spamsux .com>
wrote:
I have the following code:

sscanf(line, "%d", n_ptr) !=1 || n_ptr <=0;


The third argument needs an & but I assume that is a typo.


<snip>

From its name, I would guess that n_ptr is set to point to an int and is
defined as

int * n_ptr;
--
==============
Not a pedant
==============
May 5 '06 #6

"Barry Schwarz" <sc******@doezl .net> wrote in message
news:ar******** *************** *********@4ax.c om...
On Thu, 4 May 2006 20:23:56 -0400, "Yogi_Bear_ 79" <no****@spamsux .com>
wrote:
I have the following code:

sscanf(line , "%d", n_ptr) !=1 || n_ptr <=0;


The third argument needs an & but I assume that is a typo.

If you want to know whether the data at line is a "well formed"
integer, use strtol which will tell you where it stopped extracting
data. Then examine that char for white space or '\0'.

It only partially works. If the user types a character other than 0-9 to
start the string it fails. However as long as the first character is an
integer it will allow letters in the following places

for Example:

H78 (fails as expected)
78 (works as expected)
7H8 ( doesn't fail as desired)


I think I understand now. The code as written is reading the line up until
it encounters a non-integer. So 7 & 7H8 both return the same results. And
from yor sufggestion above it will stop extracting at the H which I can use
strtol to examine, and if it stops on anything other than white spaces I
have my error?

Remove del for email

May 5 '06 #7
On Fri, 5 May 2006 09:15:57 +0100, "pemo" <us***********@ gmail.com>
wrote:
Barry Schwarz wrote:
On Thu, 4 May 2006 20:23:56 -0400, "Yogi_Bear_ 79" <no****@spamsux .com>
wrote:
I have the following code:

sscanf(line, "%d", n_ptr) !=1 || n_ptr <=0;


The third argument needs an & but I assume that is a typo.


<snip>

From its name, I would guess that n_ptr is set to point to an int and is
defined as

int * n_ptr;


How often do you compare a pointer to less than or equal to zero? If
he had coded *n_ptr <= 0 I would agree with you. Let's agree the code
as written is confusing.
Remove del for email
May 5 '06 #8
Groovy hepcat Yogi_Bear_79 was jivin' on Thu, 4 May 2006 20:23:56
-0400 in comp.lang.c.
How to sscanf return integer only's a cool scene! Dig it!
I have the following code:

sscanf(line, "%d", n_ptr) !=1 || n_ptr <=0;
Presumably n_ptr is a pointer. If not, then not only is it
misleadingly named, but it is also causing undefined behaviour since
sscanf() wants a pointer there. And if n_ptr is a pointer, then the
comparison n_ptr <= 0 makes little or no sense. Perhaps you meant
*n_ptr <= 0?
Also, this line reads in a number (assuming all is correct) and
checks for an error, but takes no action if an error has been
determined to have occurred. Rather pointless, isn't it?
It only partially works. If the user types a character other than 0-9 to
start the string it fails. However as long as the first character is an
integer it will allow letters in the following places

for Example:

H78 (fails as expected)
78 (works as expected)
7H8 ( doesn't fail as desired)


If you must use sscanf() for this, try it this way:

char dummy;
....
if(sscanf(line, "%d%c", n_ptr, dummy) != 1)
{
/* Non-numerical input detected. Handle this error somehow. */
}

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technicall y correct" English; but since when was rock & roll "technicall y correct"?
May 7 '06 #9

"Robert Gamble" <rg*******@gmai l.com
Yogi_Bear_79 wrote:
> But there _is_ an integer - 7. there's then stuff after the integer.


It needs to fail if there are any characters other than integers or white
space

> and what's "|| n_ptr <=0" supposed to do?


Not needed, removed, same results


sscanf isn't the best tool for the job for a couple of reasons, not the
least of which is that trying to convert a number of too large a
magnitude results in undefined behavior.

The following program will read a line at a time from stdin and attempt
to convert it to an integer using the strtol function. If the line
contains any invalid characters, an error message is displayed and the
offending character is pointed out. If a range error occurs (the
number was too large/small to store in a long int), an appropriate
message is diaplayed. This version uses 'long int' and accepts
negative numbers, remove the minus sign from the string of allowed
characters if you just want to accept positive numbers. The code is a
little verbose since it implements error checking.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define BUF_MAX 80

int main (void) {
char buf[BUF_MAX];
long l;
size_t s;
while(fgets(buf , BUF_MAX, stdin) != NULL) {
if ((s = strspn(buf, "-0123456789 \t\n")) == strlen(buf)) {
errno = 0;
l = strtol(buf, NULL, 10);
if (errno == ERANGE) {
printf("number out of range!\n");
} else {
printf("number read was %ld\n", l);
}
} else {
while(s--)
putchar(' ');
putchar('^');
printf(" invalid character\n");
}
}
return 0;
}

The strspn function returns the number of characters in the input
string that are in the "allow" string, this must be the same as the
length of the string itself if all the characters are valid, otherwise
we print an error message displaying the location of the offending
character and continue.

The strtol function will skip leading whitespace and attempt to convert
the numeric part of the string to a long int. If an underflow or
overflow occurs then strtol returns LONG_MIN or LONG_MAX respectively
and sets errno to ERANGE. We just check errno and print an error if
appropriate, you could compare l to LONG_MIN or LONG_MAX to determine
the type of range error if desired.

If everything goes well, the converted number is displayed.

A couple of notes:

If the input consists of multiple numbers seperated by whitespace, only
the first one will be converted, you didn't specify what should happen
in this case.

If the input contains only of whitespace or the minus sign the
converted value will be 0.

Entering more than BUF_MAX characters at a time may cause unintended
(but not undefined) behavior.

If an invalid input line contains a tab character before the invalid
character, the error message may not correctly point to the invalid
character.

Addressing these caveats is left as an exercise to the reader.

Robert Gamble


I am unable to discern the OP's intent. [snipped from OP:]
sscanf(line, "%d", n_ptr) !=1 || n_ptr <=0;
would have wanted to come back with a bunch of concatenated digits. What
if, instead, you wanted a robust means of coming back with an unsigned long?
Elsethread, you hinted that strtol might not be a bad idea.
long strtol(const char *s, char **endp, int base)
The arguments look quite cryptic to me. Joe
May 7 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
4035
by: Brent Lievers | last post by:
Greetings, I have a question about parsing a fixed-width integer from a string. Lines of data are being read from a file having a very strict column-delimited format. In my example below, columns 0-7 are an integer and columns 8-23 are a float. In _most_ files, the first few columns of the float are blank space to make it human readable. But not always. So, once they have been read from the file, I try to parse out the different...
3
4762
by: whisper | last post by:
Hello: I am trying to write code to read in a bunch of lines from stdin, each containing a (variable) number of integers and writing each integer in a separate line to stdout. I came up the code below. I could not get sscanf to work because it does not increment its position
4
4244
by: smshahriar | last post by:
Hi, I want to scan from the following string all the hex numbers and populate an array of integers: 0x27 0x00 0x30 0x00 0x33 0x00 0x36 0x00
10
5445
by: baumann | last post by:
hi, 1) first test program code #include <stdio.h> int main(void) { char * file = "aaa 23 32 m 2.23 ammasd"; int i2,i3;
4
2023
by: baumann | last post by:
hi all there has 2 program 1) the first test program code #include <stdio.h> int main(void) {
10
2974
by: broeisi | last post by:
What advantages does sscanf offer over scanf? I had the following code: #include <stdio.h> #include <string.h> int main(void) { int start, finish, values;
4
1804
by: lynx_ace | last post by:
Hi everyone. I need a little bit help here...I have an assignment and it is working fine until the last part which I can't solve. So here's the code in simple form #define maxlength 200 while( fgets( command, MAXLLENGTH, stdin ) != NULL ) {
7
2292
by: Joachim Schmitz | last post by:
Hi folks What would be the expected and correct output of the following #include <stdio.h> int main (void) { char buffer1 = "(10,20,30)"; char buffer2 = "(10,20,30 )"; /* add two white spaces between 30
5
2308
by: a | last post by:
After reading FAQ comp.lang.c section 12 and googling again, still there is no threads talking about reading a series of numbers. The input files, somehow structured, is exemplified below: <presence/absence of n space/tab on the first n lines> 12 <presence/absence of n space/tab here>0<presence/absence of n space/tab here>90 10 23 43 0 0 0 0 0 0 0 90 0 0 0 0 88 0 0 0 ...
0
8402
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8829
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8734
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8508
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8608
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7341
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6172
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4164
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4323
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.