473,756 Members | 5,656 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Strtol vs sscanf

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
on conversion (like scanf does). Is there some workaround for it ?

Please criticize the code below: I have a feeling I am missing a simple
and elegant solution, since the problem is so simple itself.

Moreover, there is a *bug* in the code: what happens when I have a 0 as
a number ?
Reading will stop then. How do I get around that ?

Are my malloc() error statements correct ? In general, is it not better
to state in
the malloc error's before exiting which variables failed to get
malloc'ed ?
#include <stdio.h>
#define MAX 80

int main() {
int i, n;
char *line, **errline, *lineA, *lineB;

line=malloc(MAX *sizeof(char));
errline=malloc( sizeof(*errline ));

if ((line == NULL) || (errline==NULL) ) {
fprintf(stderr, "Could not allocate memory");
exit(-1);
}

while (fgets(line,MAX , stdin)!=NULL) {
lineA=line;
while ((n=(int)strtol (lineA, errline, 0))!=0) {
printf("%d \n", n);
lineA=*errline;
// printf("Line is now at %s \n",lineA);
}
}
}

Nov 14 '05 #1
3 4784
whisper wrote:
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
on conversion (like scanf does). Is there some workaround for it ?
One possibility is to use the "%n" specifier in the
sscanf() format string. This tells you how many characters
the sscanf() operation "swallowed, " which you can use to
get the next sscanf() to begin its scan after the already-
used characters.
Please criticize the code below: I have a feeling I am missing a simple
and elegant solution, since the problem is so simple itself.
You are certainly working *much* too hard. I see no
reason to use malloc() at all for this task; every dynamic
allocation requires a pointer, but it does not follow that
every pointer requires a dynamic allocation!
Moreover, there is a *bug* in the code: what happens when I have a 0 as
a number ?
Reading will stop then. How do I get around that ?
sscanf() will detect the "no more data" condition and
report it "out of band," independently of the converted
number, so you need not reserve any special value. strtol()
sets a pointer (`errline' in your code) to the first byte
after converted material, or to the start of the string if
nothing could be converted; use that pointer to discover
when you've reached the end of the line.
Are my malloc() error statements correct ? In general, is it not better
to state in
the malloc error's before exiting which variables failed to get
malloc'ed ?
Halting the program on a malloc() failure is reasonable
for some programs, unreasonable for others; there is no one
error-handling strategy that works in all cases. exit(-1)
is a dubious practice, since -1 will have different meanings
on different C implementations ; it's better to use either
EXIT_SUCCESS or EXIT_FAILURE (both from <stdlib.h>, which
you should have included anyhow since that's where malloc()
and strtol() are declared -- in fact, your compiler ought to
have given a diagnostic for this use of malloc() without a
declaration).

Printing out the names of internal variables involved
in a failure condition may be useful to you the programmer
(it may help your debugging), but is spectacularly unhelpful
to an end user who doesn't have access to your source code.
If your newsreader told you "Could not allocate memory for
buffer_3 in function filter_redo_del egate()", would you be
able to make any sense of it?
#include <stdio.h>
#define MAX 80

int main() {
int i, n;
char *line, **errline, *lineA, *lineB;

line=malloc(MAX *sizeof(char));
errline=malloc( sizeof(*errline ));

if ((line == NULL) || (errline==NULL) ) {
fprintf(stderr, "Could not allocate memory");
exit(-1);
}

while (fgets(line,MAX , stdin)!=NULL) {
lineA=line;
while ((n=(int)strtol (lineA, errline, 0))!=0) {
printf("%d \n", n);
lineA=*errline;
// printf("Line is now at %s \n",lineA);
}
}
}


Here's a considerably simpler version, using no dynamic
memory allocation at all:

#include <stdio.h>
#include <stdlib.h>
#define MAX 80

int main(void) {
char line[MAX];

while (fgets(line, sizeof line, stdin) != NULL) {
char *here, *next;
for (here = line; ; here = next) {
long value;
value = strtol(here, &next, 0);
if (next == here)
break;
printf ("%ld\n", value);
}
}

return EXIT_SUCCESS;
}

With not much more effort you could detect garbage inputs
like "123XYZ" and "99999999999999 999999999999999 999999999".

--
Er*********@sun .com

Nov 14 '05 #2
whisper wrote:
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.
Question: Do you want to know whether a line break happened between
numbers?
I came up the code below.

I could not get sscanf to work because it does not increment its
position
on conversion (like scanf does). Is there some workaround for it ?

Please criticize the code below: I have a feeling I am missing a simple
and elegant solution, since the problem is so simple itself.

Moreover, there is a *bug* in the code: what happens when I have a 0 as
a number ?
Reading will stop then. How do I get around that ?

Are my malloc() error statements correct ? In general, is it not better
to state in
the malloc error's before exiting which variables failed to get
malloc'ed ?
#include <stdio.h> #include <stdlib.h> /* malloc, exit */ #define MAX 80 Rather call that LINE_MAX or some such: It is clearer.
int main() {
int i, n; i is unused char *line, **errline, *lineA, *lineB; lineB is unused
line=malloc(MAX *sizeof(char)); sizeof(char) is _always_ 1. Use MAX*sizeof *line or just MAX. errline=malloc( sizeof(*errline ));

if ((line == NULL) || (errline==NULL) ) {
fprintf(stderr, "Could not allocate memory"); Insert
free(line);
here: If line==NULL, free(line) does nothing, otherwise
the malloc()ed memory gets freed.
Better yet: Check immediately after trying to malloc().
Apart from that: Instead of char **errline, use char *endptr
and pass &endptr -- saves one malloc() and free() and is IMO
less opaque.
exit(-1); exit(EXIT_FAILU RE); }

while (fgets(line,MAX , stdin)!=NULL) {
lineA=line;
while ((n=(int)strtol (lineA, errline, 0))!=0) { you are losing information here, moreover, if LONG_MAX>INT_MA X
(or LONG_MIN<INT_MI N), you are in trouble, having invoked undefined
behavior. printf("%d \n", n);
lineA=*errline;
// printf("Line is now at %s \n",lineA);
}
} Do not forget to free()!!!
free(line);
free(errline); }


Your program stops (without errors encountered) only at
reading of EOF. Is that intended?
Moreover: Your use of strtol is rather strange.
I will comment further on that later on.

If you want to use a scanf()-like function, do not use sscanf(),
rather use fscanf() for an arbitrary number of numbers per line:

#include <stdio.h>

int main (void)
{
int num;

while (fscanf(stdin," %d",&num)==1)
printf("%d\n", num);

return 0;
}

Back to strol:
I would do it like that

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>

#define LINE_MAX 80

int main (void) {
int num;
char *line, *nptr, *endptr;

line = malloc(LINE_MAX *sizeof *line);
if ( line == NULL ) {
fprintf(stderr, "Could not allocate memory");
exit(EXIT_FAILU RE);
}

while (fgets(line,LIN E_MAX, stdin) != NULL) {
int err=0;
nptr=line;
while (!err) {
long tmp = strtol(nptr, &endptr, 0);

switch (tmp) {
case LONG_MIN:
case LONG_MAX:
/* Check for range error */
errno = 0;
tmp = strtol(nptr, &endptr, 0);
if (errno==ERANGE)
err = 1;
break;
case 0:
if (nptr==endptr) {
err = 1;
break;
}
default:
if (tmp>INT_MAX || tmp<INT_MIN) {
err = 1;
break;
}

printf("%d\n",n um=(int)tmp);
break;
}
nptr = endptr;
}
}

free(line);
return 0;
}
Note, however, that fgets() is not safe. Have a look at the
FAQ or google for one of the various Pop's Device vs fgets()
discussions.
For the future: Read the manpage of functions you are using
(google for "man strtol", e.g.)

Cheers
Michael
--
E-Mail: Mine is a gmx dot de address.
Nov 14 '05 #3


whisper wrote:

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
on conversion (like scanf does). Is there some workaround for it ?

Please criticize the code below: I have a feeling I am missing a simple
and elegant solution, since the problem is so simple itself.

Moreover, there is a *bug* in the code: what happens when I have a 0 as
a number ?
Reading will stop then. How do I get around that ?

Are my malloc() error statements correct ? In general, is it not better
to state in
the malloc error's before exiting which variables failed to get
malloc'ed ?

#include <stdio.h>
#define MAX 80

int main() {
int i, n;
char *line, **errline, *lineA, *lineB;

line=malloc(MAX *sizeof(char));
errline=malloc( sizeof(*errline ));

if ((line == NULL) || (errline==NULL) ) {
fprintf(stderr, "Could not allocate memory");
exit(-1);
}

while (fgets(line,MAX , stdin)!=NULL) {
lineA=line;
while ((n=(int)strtol (lineA, errline, 0))!=0) {
This is not how you use strtol - you seem to be confused about how to
use the second argument. The proper way is:

char *ptr;
long int n;
char *line;

/* assume 'line' has been filled with a null-terminated string */

n = strtol( line, &ptr, 0 );

At this point, ptr points to the first character in 'line' that was not
read as part of the number that translates into 'n'.

printf("%d \n", n);
lineA=*errline;
// printf("Line is now at %s \n",lineA);
}
}
}


--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Common User Interface Services
M/S 2R-94 (206)544-5225
Nov 14 '05 #4

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

Similar topics

11
2997
by: nrk | last post by:
Isn't: char s = "--4"; char *endptr; strtol(s, &endptr, 0); supposed to return 0 and set endptr to s? I have run into an implementation (not gcc, gcc does what I expect) that is returning LONG_MIN!! I am afraid to see what it did to endptr :-)
10
5123
by: Peter Dunker | last post by:
Hi, I will check a String which should contain a HEX value. I know that strtol is the right function for this job. But what happens when I will check a hex string with 8 bytes? That I can check that the string is correct i know. long value; char src="0x1234567812345678"
16
2668
by: David Scarlett | last post by:
Another two questions... Is behaviour defined when the first argument of strtol is NULL? And if the string contains only digits, is the 2nd argument (assuming it wasn't NULL) guaranteed to be set to a pointer to a pointer to '\0'? Thanks.
2
2997
by: Marlene Stebbins | last post by:
Suppose I'm using strtol() to convert a command line string to a number and I want to check that the input to strtol() is not non-numeric. strtol() returns zero if input is non-numeric, so I can write something like this: if((x = strtol(argv, NULL, 10))==0) exit(EXIT_FAILURE); That catches non-numeric input alright, but zero is a perfectly good number that might be input to my program. How can I use
10
5470
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
2029
by: baumann | last post by:
hi all there has 2 program 1) the first test program code #include <stdio.h> int main(void) {
5
6405
by: jchludzinski | last post by:
I'm using strtok() to parse thru a line and read different numbers: float value; char *token; token = strtok( line, " " ); .... sscanf( token, "%f", &value ); These results are less precise than I had expected:
3
3224
by: dstevel | last post by:
The signature for strtol is: strtol( const char*, char**, int) So.. if we start with a passed "const char*" (pointer to const char), then we can't create a non-const char pointer pointer to that const char pointer as in: void func( const char* a ) {
8
3285
by: lovecreatesbea... | last post by:
Does this part of C code call and check strtol() correctly? port = strtol(argv, &endptr, 10); if (argv == endptr){ fprintf(stderr, "%s\n", "Invalid port number form"); return 1; } if (port == 0 && errno == EINVAL){ perror("strtol()"); return 1;
0
9454
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
9271
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10028
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
9868
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
9836
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,...
1
7242
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
5139
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
5301
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2664
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.