ignoring whitespace with sscanf in C

18,269

Solution 1

You read it in as

sscanf(string, "%d %s %s %d", &NUMBER1, &NAME, &SECONDNAME, &NUMBER2);

then concatenate them

strcat(NAME," "); // Add space
strcat(NAME,SECONDNAME); // Add second name

Make sure that NAME has enough space to hold both the first and second name. You will also have to:

#include <string.h>

Solution 2

In order to come up with the solution (and tell whether it is even possible with sscanf), you need to provide more information about the format of your string. It is not possible to derive anything conclusive from a single example you provided so far.

In your particular case one needs to know where the name ends and the next number begins. How do you define that in your case? Are we supposed to assume that the first decimal digit character means the end of the name and the beginning of the number2? Or is it something more complicated? If the input string contains a "Tom16" sequence, is the entire "Tom16" supposed to be the name, or should we split it into "Tom" and leave 16 for number2?

Basically, your question, as stated, allows for no meaningful answer, only for random suggestions.

Update: Your description of the format of the string is still far from being complete, but I can suggest using the following format specifier in sscanf

sscanf(string, "%d %[^0123456789]%d", &number1, name, &number2)

This will work, assuming that the "numbers" you are referring to are composed of decimal digits only and assuming that name cannot contain any decimal digits. Also note that it will not include the leading space onto the name, but it will include the trailing space. If you don't want it you'll have to trim the trailing space from the name yourself.

In any case, parsing capabilities of sscanf are rather limited. They are normally inadequate for solving problem like yours. What I have above is probably the best you can get out of sscanf. If you need something even a little more elaborate, you'll have to parse your string manually, token by token, instead of trying to parse the whole thing in one shot with sscanf.

Solution 3

No, not with sscanf().
You can do it 'easily' with fgets(), and parsing the line character by character


/* basic incomplete version; no error checking; name ends with whitespace */

#include <ctype.h>
#include <stdio.h>

  int num1, num2;
  char name[250], line[8192], *p;

  fgets(line, sizeof line, stdin);
  num1 = num2 = 0;
  p = line;
  while (isdigit((unsigned char)*p) {num1 = num1*10 + *p - '0'; p++};
  while (isspace((unsigned char)*p)) p++;
  while (!isdigit((unsigned char)*p)) *name++ = *p++;
  while (isdigit((unsigned char)*p) {num2 = num2*10 + *p - '0'; p++};

Solution 4

You can't do this work with the sscanf function and a "central" string with an arbitrary number of spaces in it, since the whitespace is also your delimiter for the next field; if that %s matched strings with whitespace, it would "eat" also the 6.

If it's only your "central" field that is "special" and you have only those three fields, you should read your string backwards to find the beginning of the third field, and transform it in number; then you replace the character before the 6 with a \0, thus truncating the string before the third field.

Then you can use strtoul to convert the first field and to determine where it ends (using its second parameter); considering the string that starts from there and goes to the end of the truncated string you get the second field.

Solution 5

@AndreyT is pretty much correct. I'm going to guess that the middle field should stop at any digit. If that's the case, then yes sscanf can do the job:

sscanf(string, "%d %[^0-9] %d", &NUMBER1, NAME, &number2);

You really want to limit the amount that's read to the length of your buffer though:

char name[32];
sscanf(string, "%d %31[^0-9] %d", &number1, name, &number2);

I should add that technically this isn't portable as-is. To be entirely portable, you should use [^0123456789] instead of [^0-9]. Old versions of Borland compilers actually treated "0-9" as meaning the three characters '0', '-' and '9'. The standard permits this, though I don't know of any current compiler that takes its permission to be stupid.

Share:
18,269
camelCase
Author by

camelCase

Updated on June 04, 2022

Comments

  • camelCase
    camelCase almost 2 years

    I have a string such as "4 Tom Tim 6", and i am trying to scan those values with sscanf like this sscanf(string, "%d %s %d", &NUMBER1, NAME, &number2 )

    is there any way to do this and deposit in NUMBER1 the value 4, in NUMBER2 the value 6, and in NAME the value "Tom Tim"?

    I tried but sscanf splits "Tom" and "Tim" because there is a whitespacew between them and thus it also returns a incorrect value for NUMBER2.

    Update:

    Let me be more specific. There will always be a number at the beginning and at the end of the my string, and a substring between those numbers, which could have any length and any quantity of whitespaces, and what im trying to get is that substring in a single variable, and the numbers in the beggining and the end.

  • flight
    flight about 13 years
    Where does he mention scanf()?
  • stefan
    stefan about 13 years
    Also, please remember that sscanf etc is non-safe and can cause extremely potent bugs and security holes in any application.
  • stefan
    stefan about 13 years
    Yah but this will probably be a problem as you might have more than one space or non at all, in the name field..
  • stefan
    stefan about 13 years
    yes but since the question is so newbie its very likely he didn't really know what he asked for, nothing wrong with your answer tho.
  • flight
    flight about 13 years
    @stefan yes but since the question is so newbie, it's very likely he's not actually worried about the number of spaces, valid point though.