0

For example, I have this block:

int nFirst, nSecond;
char sInput[10];
printf("Which variable to change to 10?");
scanf("%s", &sInput);
// BAD - inflexible and unmaintainable
if(strcmp(sInput,"nFirst") ==0){
    nFirst = 10;
}
else if (strcmp(sInput,"nSecond")==0) {
    nSecond =10;
}

Is there a nice way to do this? like treat a string as if its a variable name?

6
  • 1
    Whoa, why would you wanna do that? Commented Nov 1, 2013 at 12:01
  • 1
    You cannot treat a string as a variable name. You can do a hash map ẇith strings as keys and variable pointers as values. Commented Nov 1, 2013 at 12:01
  • 1
    As a minor note, your use of strcmp() is wrong; it doesn't return bool, it returns int with 0 meaning "strings are equal". Commented Nov 1, 2013 at 12:05
  • 1
    How tying required user input to the implementation details of your program is more flexible and maintainable than your current code? Commented Nov 1, 2013 at 12:05
  • 1
    @OrCyngiser I see it's corrected now, good. Also, it's "a function": in C, there are no methods. Commented Nov 1, 2013 at 12:19

5 Answers 5

1

No, there is no "nice" way of doing this in C. Variable names (typically) aren't preserved in the generated machine code, except to support debugging. C doesn't have a built-in mechanism for translating a string value into a reference to a variable of the same name.

You would have to map variable names to variables manually. You could build a lookup table, associating a string value with the address of the corresponding variable:

struct vn {
  char *varname;
  void *addr;
  Typeinfo t;
};

where Typeinfo is some enumeration or other mechanism for encoding the type of the variable, giving you something to the effect of

int foo;
double bar;
char *blurga;
struct vn varsByName[] = { {"foo", &foo, IntType}, 
                           {"bar", &bar, DoubleType}, 
                           {"blurga", blurga, CharPtrType} };

I don't recommend doing this.

Sign up to request clarification or add additional context in comments.

Comments

0

Another, platform-dependent approach is to put all your variables into a shared library and then have access to them by names. Have a look at dlsym/dlopen functions.

void* handle = dlopen("mysymbols.so", RTLD_LOCAL | RTLD_LAZY);
int* var = (int*) dlsym(handle, user_typed_name);
*var = 10; /* modify the variable */

Comments

0

You could implement something like a dictionary or a two-dimensional array which contains the "variable name" and the value. Then this comes down to setting an array element to a new value.

Other than that: C# and other object oriented languages would allow this through reflection, but as C itself isn't object oriented, you can not do that (C++ support for this seems to be very limited).

1 Comment

Whoops, looks like C++ can not easily do that (read here: stackoverflow.com/questions/41453/…). I'll update my answer.
0

You can do it with a macro:

#define MAYBESET(name) if (strcmp(sInput, #name) ==0 ){ name = 10; }

#name is the real value of name changed to a string literal.

1 Comment

This is still inflexible as it requires the macro to be called for each valid variable at build time. It reduces the visual code footprint but doesn't solve what the poster asked for. Also, it eliminates a potentially huge benefit of the else clause as used by the poster, increasing average runtime.
0

For a small number of variables then your algorithm should perform well. If there are many variables that could be changed, rather than just two, then another algorithm should be considered. Making this pretty and clear isn't exactly easy in C. If you really wanted this to be faster you could either do a hash table or use a switch/case like:

int First, Second; // Note that I got rid of your leading n
char sInput[10];
printf("Which variable to change to 10?");
scanf("%s", &sInput);
// BAD - inflexible and unmaintainable
// referring to character array overflow potential, I assume

switch (sInput[0])
{
     case 'F':
         if (0 == strcmp("irst", sInput+1) )
         {
              First = 10;
         } else 
         {
              // error
         }
         break;
    case 'S':
         if (0 == strcmp("econd", sInput+1) )
         {
              Second = 10;
         } else 
         {
              // error
         }
         break;
    default:
         // error
         break;
}

If you don't like the way that this looks then you could use macros (#define) to make it less big looking, but it would turn out the same. Another option that you could employ would be to write a small program that output the source code of this program which would handle all of the repetitive and tedious parts.

Another way to do this, if all of the variables are of the same type, would be to create an array of them and input their index in rather than a name, but then you have to add code to check against inputting an index out of range of the size of the array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.