How do I set a value to a variable by passing the variales name in C? - c

char whatVar[] = "";
float phValue, ecValue, tempValue;
I am not sure if this is possible or not in C. Each of the float values will be set randomly. I would like to set their values depending on what the char whatVar corresponds to. For example, lets say char whatVar[] = "phValue"; How do I point to the variable name inside whatVar to then set the value? I would like to achieve this without using if conditionals or a switch.

Don't; use an array. Tying your program logic to the names of your variables is a horrible idea. Variable names exist to help you as a programmer reason about what the code is doing. Beyond that the do not (and should not) have any significance.
Instead, use a collection where the index/bucket/mapping/whatever has logical meaning. It is very common for beginners to do exactly as you want to do, but it is almost certainly a bad idea. Sounds to me like you want a string -> float map or hash table.

You will have to implement the translation of whatVar onto the actual variable value manually. C language has no such immediate feature.
It can be done by if/switch ladder. Or it can be done by pre-building a table that "projects" (maps) variable names to variable addresses (and, if necessary, types). You will have to manually search through the table. It will still have if's though, unless you develop some sort of [minimal] perfect hashing function for your names (see Steve Jessop's comment).

This is outside of the language specification and I think if this is a feature that you wish to have in the language another language would be of more use to you that has this kind of functionality in it.
The only way I can think of implementing this is by doing some preprocessing tricks, which just seems like a bad idea. With this method you will not have if's in the code it self but some very unmaintainable preprocessing.

why not ?
if(strcmp(whatVar, "phValue") == 0)
{
phvalue = 3; //some value
}
and so on and so forth.
Edit : if the ifs and the switch is not desired then we can use some sort of stl map ing between the string representations as the keys and their variables as the values.

If you really really want to do this, you can use the dlsym function (as long as the variables you are accessing are global). Here's a quick example:
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
float phValue, ecValue, tempValue;
int main(int argc, char *argv[]) {
int i;
phValue = 0;
ecValue = 0;
tempValue = 0;
printf("Before:\n");
printf("\tphValue = %f\n", phValue);
printf("\tecValue = %f\n", ecValue);
printf("\ttempValue = %f\n", tempValue);
for(i = 1; i < argc; i += 2) {
float *varptr = (float *)dlsym(RTLD_MAIN_ONLY, argv[i]);
*varptr = atof(argv[i+1]);
}
printf("\nAfter:\n");
printf("\tphValue = %f\n", phValue);
printf("\tecValue = %f\n", ecValue);
printf("\ttempValue = %f\n", tempValue);
}
And a demo:
% gcc varname.c -ldl
% ./a.out phValue 12.1 tempValue 4.3 ecValue 2.2
Before:
phValue = 0.000000
ecValue = 0.000000
tempValue = 0.000000
After:
phValue = 12.100000
ecValue = 2.200000
tempValue = 4.300000

Related

Increase a variable number by 1

I have code in which I have a large number of characters all declared as being 1 higher than the other.
e.g. m1, m2, m3...
is there any way to increase the number I'm searching for by 1 in a for loop?
I have a long string of letters that I need to check to see if any of them match to the individual, but I cannot use strings due to situational limitations.
a1 is the particular character I'm looking for, m1 is the first in a long string of characters I am having to store as individuals
My attempt that wouldn't run:
for (a1 != m["%d"], &check, check++)
Unfortunately due to the limits of my application I can only use stdio.h and stdlib.h in my solution. Any help would be greatly appreciated
Variable names are used by the compiler, but are not part of the generated executable and therefore not accessible at runtime. You can simulate something like that by an array initialized with the addresses of the respective variables:
#include <stdio.h>
int main() {
int a0=0,a1=10,a2=15;
int *a[3] = { &a0, &a1, &a2 };
for (int i=0; i<3; i++) {
int val = *(a[i]);
printf("a%d:%d\n",i,val);
}
}
Output:
a0:0
a1:10
a2:15

How to take characters from an array and store them in a variable?

#include <stdio.h>
#include <stdlib.h>
int main()
{
int agecalc;
int nextyr;
int birthday;
int currentday;
int agecalcu;
int randomnumbers;
birthday = 1987;
currentday = 2016;
nextyr = currentday + 1;
agecalc = currentday - birthday;
randomnumbers = 7890;
char My[] = "Sayan Banerjee";
printf("%s 's birthday is %.3d \n", My , agecalc);
agecalcu = agecalc + 1;
/* alternatively I can use one int and change the variable stored in agecalc by stating that
agecalc = currentday - birthday +1; But I think that is just messy and disturbs a lot of code. declaring a new int is
better and less intrusive. this way when I may need to use agecalc again, i dont have to worry about the value stored in that
variable. */
printf("%.5s will turn %.3d on %d.\n \a", My , agecalcu , nextyr);
printf("The username for %s is %.6d \n", My , randomnumbers);
// the thing here is that I cannot shorten a value stored in a value unless its in an array
// but I can express it in other ways like 1 to 01.
/* The thing is that I cannot store two %s in one argument/code. this freezes the code. better way would be to
create another variable and then try to edit that.*/
//this is an experiment to see whether I can take characters from an array and store it in a variable
int user;
My [0,1,2,3,4,5] = user;
printf("%s is also %s", My , user );
return 0;
}
The main question I have is in the last line. I am a newbie to coding and have just started learning. I was just playing around and noticed that if I put in two %s in the same argument the program kind of crashes. So, I was thinking if I can take certain characters in the array My and store them in a variable and then print it?
Is it possible? or am I just looking at this in the wrong way?
Sorry for the messy post.
Thanks for all your help.
My [0,1,2,3,4,5] = user;
This line is equivalent to saying
My[5] = user;
That's because of the comma operator
//this is an experiment to see whether I can take characters from an array and store it in a variable
You can. But what you are doing right now is assigning an un-assigned value to the 5th element of the My array. int val = My[5] is perfectly fine to do not the other way round though.
The crash is happening because your code is trying to interpret an integer as a null terminated string because of %s format specifier that you gave
printf("%s is also %d", My , user ); // %d for integers
Your code in current state is in Undefined Behavior land.
To copy certain characters from an existing array into the target array you will need more than one variable. A single variable will just hold a single character.
char user[6];
user[5] = '\0'; // fill the last character as null to be a valid C string
user[0] = My[0];
user[1] = My[1];
user[<any other index you want>] = My[<The index you want>];
You can save yourself much energy, time and effort by simply using functions from string.h which has bunch of utilities for string manipulation. Probably what you need for your current problem is strncpy
As an orthogonal suggestion, compile your code with the highest warning level supported by your compiler. The compiler will shout out these issues at compile time.
For eg gcc -Wall filename.c
Following line does not do what you think:
this:
My [0,1,2,3,4,5] = user;
is actually the same thing as this:
My [5] = user;
Read about the comma operator.
Anyway, you cannot store the whole Myarray in a single int variable.
Here you are using %s for printing user which is not a char* but an int
printf("%s is also %s", My , user );
This results in undefined behaviour, most likely a crash on modern systems.
As for your question it is a bit unclear, you maybe want this:
#include <string.h>
...
char user[20];
strcpy(user, My);
printf("%s is also %s", My , user);
which will print:
Sayan Banerjee is also Sayan Banerjee

The strange copy behavior of Intel Cilk Plus array notation

I'm using Intel Cilk Plus array notation to practice vector programming.
However, I met strange copy behaviors of array assignments.
The problem to solve is parallel prefix. D is input, and P is output.
//Wrong result code. Tested on Intel icc 14.0.2.
void vec_prefix(int n, int D[n], int P[n]) {
P[0:n] = D[0:n]; //initial copy
int bound=1;
int * Buf1 = _mm_malloc(n*sizeof(int), 16);
int * Buf2 = _mm_malloc(n*sizeof(int), 16);
while(bound<n){
Buf1[0:n-bound] = P[0:n-bound];
Buf2[0:n-bound] = P[bound:n-bound];
//printf("WHY??\n"); //Add this fence, the result will be correct.
P[bound:n-bound] = Buf1[0:n-bound] + Buf2[0:n-bound];
bound<<=1;
}
_mm_free(Buf1); _mm_free(Buf2);
}
If I remove the comment of the line "printf", the result is correct. Otherwise, wrong.
But if all copies follow the descriptions in the Intel's document, the code should be correct.
It seems if there is no such as memory fence, the first two lines' Buf1/Buf2 copy are not finished, and the add operation later uses some unstable value.
Or, the compiler optimizer just use copy-propagation to remove the copy, and create "P[bound:n-bound] = P[0:n-bound] + P[bound:n-bound]". This is undefined in Intel's document.
//Correct result code
void vec_prefix(int n, int D[n], int P[n]) {
P[0:n] = D[0:n]; //initial copy
int bound=1;
int * Buf1 = _mm_malloc(n*sizeof(int), 16);
while(bound<n){
//direct copy part
Buf1[0:bound] = P[0:bound];
//add part
Buf1[bound:n-bound] = P[bound:n-bound] + P[0:n-bound];
//copy back
P[0:n] = Buf1[0:n];
bound<<=1;
}
_mm_free(Buf1);
}
Ref: Intel's document
http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011Update/compiler_c/optaps/common/optaps_par_cean_prog.htm
https://www.cilkplus.org/tutorial-array-notation
Your code looks correct to me. No "fence" should be required. I filed an internal bug report for it with the Intel compiler group with an example of all ones as input. Thanks for the example.
If the compiler were working correctly, you could even shorten the while loop to:
while(bound<n){
Buf1[0:n-bound] = P[0:n-bound];
P[bound:n-bound] = Buf1[0:n-bound] + P[bound:n-bound];
bound<<=1;
}
The second array section assignment is okay since the overlap for P is exactly. Alas icc exhibits its bug for this example too.

What is the easiest way to test if certain values exist in mutliple arrays?

I know this might seem like hw question, and be my guest to treat it as such because this is a self-learning exercise.
What would be the easiest way to test if certain values exist within mutliple arrays?
For example:
Pseudo code
if array a contains a value of 4 and
array b contains a value of 2 and
array c contains a value of 6
then procede to procedure x
What I have so far in implementation
#include<stdio.h>
void x(void){/* do stuff */}
int main()
{
char fndA = 0;
char fndB = 0;
char fndC = 0;
int a[5] = {1,2,3,5,6};
int b[5] = {1,2,2,3,4};
int c[5] = {1,3,4,5,6};
for(int i=0;i<5;i++)
{
if(a[i]==4){fndA=1;}
}
//repeat for-loop for b/fndb and c/fndC
if (fndA && fndB && fndC) {x();}
return 0;
}
In this example, x() never gets called because a 4 does not exis in array a. But will I ultimately have to build a for loop for each array I want to test? Thanks
Yes. But you can obviously create a function that does the loop. You need to pass the array, its size and the element you are looking for to that function.
int array_contains_int(int *arr, size_t size, int value) {
int i;
for(i = 0; i < size; i++)
if(arr[i] == value)
return 1;
return 0;
}
Yes. The code you wrote is basically what you would do. In general, you seem to be treating arrays as sets, in which case you could think of this as an abstract datatype with the signature of sets. If instead you had these arrays implemented some other way, you might be able to abstract the member() function to have a lower running time, generally O(log(n)) (for a tree based implementation). However, yes, whatever you do, you will want to do an AND over your member() function.
I would make a function that takes an int and an array and returns true or false. Then and three of those together.
This has the added benefit of not calling later loops if one of the first one returns false in the condition.

how to numerically integrate a variable that is being calculate in the program as a pointer (using e.g. trapezoidal rule) in c language

I have a code, that was not made by me.
In this complex code, many rules are being applied to calculate a quantity, d(x). in the code is being used a pointer to calculate it.
I want to calculate an integral over this, like:
W= Int_0 ^L d(x) dx ?
I am doing this:
#define DX 0.003
void WORK(double *d, double *W)
{
double INTE5=0.0;
int N_X_POINTS=333;
double h=((d[N_X_POINTS]-d[0])/N_X_POINTS);
W[0]=W[0]+((h/2)*(d[1]+2.0*d[0]+d[N_X_POINTS-1])); /*BC*/
for (i=1;i<N_X_POINTS-1;i++)
{
W[i]=W[i]+((h/2)*(d[0]+2*d[i]+d[N_X_POINTS]))*DX;
INTE5+=W[i];
}
W[N_X_POINTS-1]=W[N_X_POINTS-1]+((h/2)*(d[0]+2.0*d[N_X_POINTS-1]+d[N_X_POINTS-2])); /*BC*/
}
And I am getting "Segmentation fault". I was wondering to know if, I am doing right in calculate W as a pointer, or should declare it as a simple double? I guess the Segmentation fault is coming for this.
Other point, am I using correctly the trapezoidal rule?
Any help/tip, will very much appreciate.
Luiz
I don't know where that code come from, but it is a lot ugly and has some limits hard-encoded (333 points and increment by 0.003). To use it you need to "sample" properly your function and generate pairs (x, f(x))...
A possible clearer solution to your problem is here.
Let us consider you function and let us suppose it works (I believe it does't, it's a really obscure code...; e.g. when you integrate a function, you expect a number as result; where's this number? Maybe INTE5? It is not given back... and if it is so, why the final update of the W array? It's useless, or maybe we have something meaningful into W?). How does would you use it?
The prototype
void WORK(double *d, double *W);
means the WORK wants two pointers. What these pointers must be depends on the code; a look at it suggests that indeed you need two arrays, with N_X_POINTS elements each. The code reads from and writes into array W, and reads only from d. The N_X_POINTS int is 333, so you need to pass to the function arrays of at least 333 doubles:
double d[333];
double W[333];
Then you have to fill them properly. I thought you need to fill them with (x, f(x)), sampling the function with a proper step. But of course this makes no too much sense. Already said that the code is obscure (now I don't want to try to reverse engineering the intention of the coder...).
Anyway, if you call it with WORK(d, W), you won't get seg fault, since the arrays are big enough. The result will be wrong, but this is harder to track (again, sorry, no "reverse engineering" for it).
Final note (from comments too): if you have double a[N], then a has type double *.
A segmentation fault error often happens in C when you try to access some part of memory that you shouldn't be accessing. I suspect that the expression d[N_X_POINTS] is the culprit (because arrays in C are zero-indexed), but without seeing the definition of d I can't be sure.
Try putting informative printf debugging statements before/after each line of code in your function so you can narrow down the possible sources of the problem.
Here's a simple program that integrates $f(x) = x^2$ over the range [0..10]. It should send you in the right direction.
#include <stdio.h>
#include <stdlib.h>
double int_trapezium(double f[], double dX, int n)
{
int i;
double sum;
sum = (f[0] + f[n-1])/2.0;
for (i = 1; i < n-1; i++)
sum += f[i];
return dX*sum;
}
#define N 1000
int main()
{
int i;
double x;
double from = 0.0;
double to = 10.0;
double dX = (to-from)/(N-1);
double *f = malloc(N*sizeof(*f));
for (i=0; i<N; i++)
{
x = from + i*dX*(to-from);
f[i] = x*x;
}
printf("%f\n", int_trapezium(f, dX, N));
free(f);
return 0;
}

Resources