Question

I am using sscanf in my project to copy strings from source buffer to target buffer. For example:

char* target;
target = (char*)malloc(100 * sizeof(char));
char* source = "Hello World";
sscanf(source, "%[^\t\n]", target); // trying to copy "Hello World" into target.
printf("%s\n", target);//this will print "Hello World".

But this way of coding style is not accepted. What my manager want me to do is something like:

sscanf(source, "%11[^\t\n]", target); // NOTE: I've written "%11". here, 11 == length of hello world.

That means, he want me to provide format specifiers as well. (%11 in this case).

But, the problem is that source can be of varying length and I don't know how to write the correct format specifier for every varying length string.

Was it helpful?

Solution

Use:

sscanf(source, "%*[^\t\n]", maxlen, target)

where maxlen is the size you want to read.

There appears to be no trivial way to make a format string for sscanf (or any of it's siblings) take an arbitrary max length of the input string. The suggestion was based on printf being orthogonal to scanf, which turns out to not be the case.

You may find you have better luck using strtok and either strncpy or strdup to copy the token.

However, since it's tagged C++, why not use:

std::stringstream ss(source);  
std::string target;
getline(ss, target, "\t");

OTHER TIPS

For copying string use strcpy(). It does not allocate space, so you have to provide the second buffer too. There's also strncpy() which will not copy more than specified characters.

If you want to make a copy of a string in one go you can use strdup(), just don't forget to free the memory afterwards.

First, use strcpy() for this.

Second, the format specifier is just a string, so just use sprintf() to make it after taking strlen() of the string you want.

Use target = strdup(source) or if still obliged to use sscanf():

Dynamically create the format.

const char* source = "Hello World";
size_t n = 10;  // See note below
char* target;
target = (char*) malloc(n);  // (char *) is needed for C++, but not C
char format[1+20+5+1];
sprintf(format, "%%" "%zu" "[^\t\n]", n - 1);
sscanf(source, format, target); // trying to copy "Hello World" into target.
printf("%s\n", source);//this will print "Hello World".
printf("%s\n", target);//this will print "Hello Wor".

You would likely want n = strlen(source) + 1, but the above illustrates how a dynamically created format specifier for scanf() prevents buffer overrun in target.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top