Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using sscanf to read strings

Tags:

c

input

scanf

I am trying to save one character and 2 strings into variables. I use sscanf to read strings with the following form :

N "OldName" "NewName"

What I want : char character = 'N' , char* old_name = "OldName" , char* new_name = "NewName" .

This is how I am trying to do it :

sscanf(mystring,"%c %s %s",&character,old_name,new_name);
printf("%c %s %s",character,old_name,new_name);

The problem is , my problem stops working without any outputs . (I want to ignore the quotation marks too and save only its content)

like image 968
kata Avatar asked Feb 08 '23 05:02

kata


2 Answers

When you do

char* new_name = "NewName";

you make the pointer new_name point to the read-only string array containing the constant string literal. The array contains exactly 8 characters (the letters of the string plus the terminator).

First of all, using that pointer as a destination for scanf will cause scanf to write to the read-only array, which leads to undefined behavior. And if you give a string longer than 7 character then scanf will also attempt to write out of bounds, again leading to undefined behavior.

The simple solution is to use actual arrays, and not pointers, and to also tell scanf to not read more than can fit in the arrays. Like this:

char old_name[64];  // Space for 63 characters plus string terminator
char new_name[64];

sscanf(mystring,"%c %63s %63s",&character,old_name,new_name);

To skip the quotation marks you have a couple of choices: Either use pointers and pointer arithmetic to skip the leading quote, and then set the string terminator at the place of the last quote to "remove" it. Another solution is to move the string to overwrite the leading quote, and then do as the previous solution to remove the last quote.

Or you could rely on the limited pattern-matching capabilities of scanf (and family):

sscanf(mystring,"%c \"%63s\" \"%63s\"",&character,old_name,new_name);

Note that the above sscanf call will work iff the string actually includes the quotes.

Second note: As said in the comment by Cool Guy, the above won't actually work since scanf is greedy. It will read until the end of the file/string or a white-space, so it won't actually stop reading at the closing double quote. The only working solution using scanf and family is the one below.

Also note that scanf and family, when reading string using "%s" stops reading on white-space, so if the string is "New Name" then it won't work either. If this is the case, then you either need to manually parse the string, or use the odd "%[" format, something like

sscanf(mystring,"%c \"%63[^\"]\" \"%63[^\"]\"",&character,old_name,new_name);
like image 115
Some programmer dude Avatar answered Feb 12 '23 01:02

Some programmer dude


You must allocate space for your strings, e.g:

char* old_name = malloc(128); 
char* new_name = malloc(128);

Or using arrays

char old_name[128] = {0};
char new_name[128] = {0};

In case of malloc you also have to free the space before the end of your program.

free(old_name);
free(new_name);
like image 29
LPs Avatar answered Feb 12 '23 02:02

LPs