tags:

views:

75

answers:

5

How can I use a variable to specify the field length when using scanf. For example:

char word[20+1];
scanf(file, "%20s", word);

Also, is it correct to use 20+1 (since it needs to add a \0 at the end?). Instead, I'd like to have something like:

#define MAX_STRING_LENGTH 20

and then

char word[MAX_STRING_LENGTH+1];
scanf(file, "%"MAX_STRING_LENGTH"s", word); // what's the correct syntax here..?

Is this possible? How about if it's a variable like:

int length = 20;
char word[length+1];
scanf(file, "%" length "%s", word); // what's the correct syntax here..?

Thanks.

A: 

http://www.manpagez.com/man/3/scanf/

I don't see one. Therefore you're going to be creating your formatting string with sprintf or whatever (if you were coding in C++ you wouldn't be using either).

Your macro version is possible. You could look in the boost preprocessor library for STRINGIFY and either use it or see how it works.

Are you really writing in C++ here or in C? If in C then you're doing what you have to do. If you're actually writing C++ and not just considering the two the same language then you have many much better options for reading data from strings.

Noah Roberts
+3  A: 

The following should do what you need for the first case.

#define MAX_STRING_LENGTH 20
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x

{
  ...
  char word[MAX_STRING_LENGTH+1];     
  scanf(file, "%" STRINGIFY(MAX_STRING_LENGTH) "s", word);
  ...
}

NOTE: Two macros are required because if you tried to use something like STRINGIFY2 directly you would just get the string "MAX_STRING_LENGTH" instead of its value.

For the second case you could use something like snprintf, and at least some versions of C will only let you allocate dynamically sized arrays in the heap with malloc() or some such.

torak
A: 

If you're using regular scanf (Linux), you have two solutions :

#define MAX_STRING_LENGTH_STR "20"
scanf(file, "%"MAX_STRING_LENGTH_STR"s", word);

OR

#define MAX_STRING_LENGTH 20
sprintf(format, "%%%ds", MAX_STRING_LENGTH);
scanf(file, format, word);

However, it seems to be use this code with Visual Studio :

char str[21];
scanf("%20s", str, 21);
Doomsday
A: 

This is one of the more annoying inconsistencies between the *printf() and *scanf() families. For some reason you can use wildcards in *printf() conversion specifiers and provide values for them in the argument list, but there's no equivalent for *scanf().

Ugly as it is, I would prefer to use a separate sprintf() operation to build the format string, rather than rely on stringization macros:

#define LENGTH 20
char word[LENGTH+1];
char format[5];

sprintf(format, "%%%ds", LENGTH);
fscanf(file, format, word); 

At least this is somewhat intuitive; as torak points out, you have to go through two levels of indirection with stringization macros (as you don't want to stringize the macro, but what the macro expands to).

John Bode
A: 

There's a difference here between C90, C99, and C++. In C++, you can use any integral constant expression, so

const int max_string_size = 20;
int this_string[max_string_size + 1];

is legal. In C99, the expression doesn't have to be constant; if it isn't, you get a variable length array. In the older C90, the expression couldn't include variables, so the above would not compiler, and you'd have to use

#define MAX_STRING_SIZE 20
char this_string[MAX_STRING_SIZE + 1];
David Thornley