In C, what is the best way to ignore the commas when using scanf
on a number like 1,000,000?
We should use "%[^\n]", which tells scanf() to take input string till user presses enter or return key.
So we use “%[^\n]s” instead of “%s”. So to get a line of input with space we can go with scanf(“%[^\n]s”,str);
scanf() just stops once it encounters a whitespace as it considers this variable "done".
I would say the best way is to not use scanf
for this. At least not using any number formats.
Instead read it as a string, then remove the commas, and finally convert to a number.
There are a number of ways to remove the commas (or any other character you want to skip). One of the easiest (and most flexible) is to simply walk two pointers down the input string shifting all the digits together ignoring the commas. (you must be sure to nul-terminate after the final digit).
An example would be:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#define MAXC 25
long xstrtol (char *p, char **ep, int base);
int main (void) {
char string[MAXC] = "";
char *rp, *wp; /* a read pointer and write pointer */
int c;
long n = 0;
rp = wp = string;
printf ("enter number with ',': ");
if (!fgets (string, MAXC, stdin)) {
fprintf (stderr, "error: insufficient input.\n");
return 1;
}
/* work down each char in string, shifting number together */
while (*rp && (('0' <= *rp && *rp <= '9') || *rp == ',')) {
if (*rp == ',') { rp++; continue; } /* skip commas */
*wp++ = *rp; /* shift digits together */
rp++;
}
*wp = 0; /* nul-terminate */
if (*rp != '\n') /* flush input buffer */
while ((c = getchar()) != '\n' && c != EOF) {}
printf ("\n string : %s\n", string);
n = xstrtol (string, &rp, 10); /* convert string to long */
printf(" n : %ld\n\n", n);
return 0;
}
/** a simple strtol implementation with error checking.
* any failed conversion will cause program exit. Adjust
* response to failed conversion as required.
*/
long xstrtol (char *p, char **ep, int base)
{
errno = 0;
long tmp = strtol (p, ep, base);
/* Check for various possible errors */
if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
(errno != 0 && tmp == 0)) {
perror ("strtol");
exit (EXIT_FAILURE);
}
if (*ep == p) {
fprintf (stderr, "No digits were found\n");
exit (EXIT_FAILURE);
}
return tmp;
}
(note: xstrtol
simply provides error checking on the conversion of string
to long
)
Use/Output
$ ./bin/nwithcomma
enter number with ',': 1,234,567
string : 1234567
n : 1234567
Look it over and let me know if you have any questions. You can check against INT_MIN
and INT_MAX
if you want to cast the result to int
, but it is just as easy to leave the answer as a long
.
As a Function
As pointed out, it would be far more useful as a function. You can move the code to a simple conversion function, and adjust the main code as follows:
...
#define MAXC 25
long fmtstrtol (char *s);
long xstrtol (char *p, char **ep, int base);
int main (void) {
char string[MAXC] = "";
printf ("enter number with ',': ");
if (!fgets (string, MAXC, stdin)) {
fprintf (stderr, "error: insufficient input.\n");
return 1;
}
printf(" number : %ld\n\n", fmtstrtol (string));
return 0;
}
/* convert comma formatted string to long */
long fmtstrtol (char *s)
{
if (!s || !*s) {
fprintf (stderr, "fmtstrtol() error: invalid string.\n");
exit (EXIT_FAILURE);
}
char *rp, *wp; /* read pointer, write pointer */
int c;
rp = wp = s;
while (*rp && (('0' <= *rp && *rp <= '9') || *rp == ',')) {
if (*rp == ',') { rp++; continue; }
*wp++ = *rp;
rp++;
}
*wp = 0;
if (*rp != '\n') /* flush input buffer */
while ((c = getchar()) != '\n' && c != EOF) {}
return xstrtol (s, &rp, 10);
}
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With