assigning struct in switch not working - c

In my program, I'm trying to create a new struct based od switch statement, but when I do so, the compiler returns an error:
Syntax error before '{' token on the row with the position assignment
I'm using dev-c++ 4.9.9.2 as an IDE (i think it's using MinGW as compiler). IT's for my brother's programming assignment I'm helping him with, I haven't seen C in a few years, so I'm rusty (and I wasn't a champion before either).
Here's simplified code:
typedef enum{TOP_RIGHT = 0,TOP_LEFT,BOTTOM_RIGHT,BOTTOM_LEFT} diagonal_t;
typedef struct
{
int row;
int column;
} position_t;
...
void checkDiagonal(diagonal_t diagonal_to_check)
{
...
position_t position;
switch(diagonal_to_check)
{
case TOP_RIGHT:
position = {0,0}; //here's the error, but I don't know how to repair it.
//how to create a new struct here without disrupting the
//switch?
break;
case TOP_LEFT:
position = {0,0};
break;
....
}
}

The var_of_type_struct = { init_value } syntax works only in definitions; it does not work in assignments.
Three common ways to deal with is are
Defining a function that initializes your struct
Defining a function that sets fields to parameters that you pass, and
Assigning the individual fields of your struct.
Approach 1:
void init_pos(position_t *p) {
p->row = 0;
p->column = 0;
}
...
case TOP_LEFT:
init_pos(&position);
break;
Approach 2:
void set_pos(position_t *p, int r, int c) {
p->row = r;
p->column = c;
}
...
case TOP_LEFT:
set_pos(&position, 0, 0);
break;
Approach 3:
case TOP_LEFT:
position.row = 0;
position.column = 0;
break;

You can't do that: assignment and initialization are not the same thing. You are attempting to use initializer syntax in an assignment. You'll have to set both fields manually:
case TOP_RIGHT:
position.row = 0;
position.column = 0;
/* ... */

You need to cast to struct type, like this:
position = (position_t){0, 0};

Related

iterating through a structure in C

I am working on a project that involves the implementation of the Stack data structure via a singly linked list. More specifically, I am wondering if there is a way to automatically cycle(iterate) through the attributes of a struct which happen to be of different data types -- it would greatly help when reading input, or when adding more attributes, so, I don't have to manually change everything.
Specific struct
typedef struct Student
{
char regNumber[30];
char fName[30];
char lName[30];
char email[50];
int phoneNumber;
short age;
} Student;
For example: attribute[0] would be regNumber, attribute[1] would be fName, attribute[n] would be the n^{th} element
I cannot think of any good way to do this that neither uses undefined behavior, nor very weird constructs. And the fact that you want fields of different type does not make it easier.
If I wanted to write code like this (which I don't) I would probably do something like this.
void *get_attr(struct Student *student, int field)
{
switch(field) {
case 0 : return (void*)&student->regNumber;
case 1 : return (void*)&student->fName;
case 2 : return (void*)&student->lName;
case 3 : return (void*)&student->email;
case 4 : return (void*)&student->phoneNumber;
case 5 : return (void*)&student->age;
}
return NULL;
}
and then you can use it like this:
int main()
{
struct Student s = { "xxx333", "Jonny", "BGood", "my#email.com", 12345, 22 };
printf ("%s\n%s\n%s\n%s\n%d\n%d\n",
(char*)get_attr(&s, 0),
(char*)get_attr(&s, 1),
(char*)get_attr(&s, 2),
(char*)get_attr(&s, 3),
*(int*)get_attr(&s, 4),
*(short*)get_attr(&s, 5)
);
}
Spontaneously, I don't see a good way around those casts. One way, but not necessarily a good way, is to do something like this:
union attr_field {
char *c;
int *i;
short *s;
};
enum attr_type { CHAR, INT, SHORT };
struct attr {
union attr_field attr;
enum attr_type type;
};
struct attr get_attr2(struct Student *student, int field)
{
struct attr ret;
switch(field) {
case 0 : ret.attr.c = student->regNumber; ret.type = CHAR; break;
case 1 : ret.attr.c = student->fName; ret.type = CHAR; break;
case 2 : ret.attr.c = student->lName; ret.type = CHAR; break;
case 3 : ret.attr.c = student->email; ret.type = CHAR; break;
case 4 : ret.attr.i = &student->phoneNumber; ret.type = INT; break;
case 5 : ret.attr.s = &student->age; ret.type = SHORT; break;
}
return ret;
}
void print_attr(struct attr a)
{
switch(a.type) {
case CHAR: printf("%s\n", a.attr.c); break;
case INT: printf("%d\n", *a.attr.i); break;
case SHORT: printf("%d\n", *a.attr.s); break;
}
}
int main()
{
struct Student s = { "xxx333", "Jonny", "BGood", "my#email.com", 12345, 22 };
for(int i=0; i<6; i++) {
struct attr a = get_attr2(&s, i);
print_attr(a);
}
}
Note that I sometimes used struct and sometimes pointer to struct as argument to functions. The choice was not due to any particular reason. It just happened to be that way. You can do it either way, and both have their pros and cons. If performance is an issue, I'd go for pointers. Same thing with the union. I could have chosen a char array and used strncpy instead. And I could have skipped the pointers for int and short. Here my thought was something like that it's more clear if ALL union members are pointers. But you have to make your own decisions about all this. If you go for pointers, it might be wise to use the const qualifier where appropriate.
If you really want to do so, I guess you could do something like this:
void *attribs[6];
attribs[0] = (void*)s.regNumber;
printf("%s", (char*)attribs[0]);
That could be combined with the techniques mentioned above. For instance
struct attr attribs[6];
for(int i=0; i<6; i++)
attribs[i] = get_attr2(&s, i);

Using a loop to call 'sequentially' named functions in C

Say I have functions foo_1(), foo_2(),...foo_n()
How could I use a loop to call them, that is how could 'convert' a string to a function call:
for (i = 0; i < n; i++)
switch (fork()) {
case 0: //child process
*COMVAR+=m;
//call foo_i()
exit(4);
case -1:
exit(5);
}
You cannot have the compiler or runtime do this automatically in C, but you can manually list the function pointers and invoke them in a loop, i.e.:
// create your function prototype, which all functions must use
typedef void(*VoidFunc)(void);
// create the array of pointers to actual functions
VoidFunc functions[] = { foo_1, foo_2, foo_3 };
// iterate the array and invoke them one by one
int main(void)
{
for (int i = 0; i < sizeof(functions) / sizeof(*functions); i++)
{
VoidFunc fn = functions[i];
fn();
}
return 0;
}
Keep in mind that void func() is not the same as void func(void) in C.
Nope.
The best you can do involves an array of function pointers
#include <stdio.h>
typedef int (*fx)(void); // fx is pointer to function taking no parameters and returning int
int foo_1(void) { printf("%s\n", __func__); return 1; }
int foo_2(void) { printf("%s\n", __func__); return 2; }
int foo_three(void) { printf("%s\n", __func__); return 3; }
int main(void) {
fx foo[3] = { foo_1, foo_2, foo_three };
for (int k = 0; k < 3; k++) {
printf("foo[%d]() returns %d\n", k, foo[k]());
}
}
see code running on ideone
Generally , your approach isn't possible in C.
But you can do it by using switch statement.
Though you have to write little bit of code.
switch (n)
​{
case 1:
foo_1();
break;
case 2:
foo_2();
break;
case 3:
foo_3();
break;
.
.
.
case n:
foo_n();
break;
default:
// code to be executed if n doesn't match any constant
}
Higher level languages that have reflection such as Java is able to do such kind of operations, but C does not. In Java, you can do something like below:
You have a class named MyClass
public class MyClass {
public void myMethodName(String arg1);
}
You can use below flow to call myMethodName using String form.
Class myObject = new MyClass();
Class<?> c = Class.forName("MyClass");
Class[] argTypes = new Class[] { String[].class };
Method method = c.getDeclaredMethod("myMethodName", argTypes);
method.invoke(myObject, params);
Here is the official document: https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html

Call c functions from fortran(type enum)

Recently,I call c function from fortran with iso_c_binding.But I found some c code.such as:
typedef enum
{
STRUMPACK_FLOAT,
STRUMPACK_DOUBLE,
STRUMPACK_FLOATCOMPLEX
} STRUMPACK_PRECISION;
typedef enum
{
STRUMPACK_MT,
STRUMPACK_MPI_DIST
} STRUMPACK_INTERFACE;
typedef struct
{
int solver;
STRUMPACK_PRECISION precision1;
STRUMPACK_INTERFACE interface1;
}STRUMPACK_SparseSolver;
int STRUMPACK_init(STRUMPACK_SparseSolver * S,
STRUMPACK_PRECISION precision1, STRUMPACK_INTERFACE interface1, int verbose)
{
S->precision1 = precision1;
S->interface1 = interface1;
switch (interface1)
{
case STRUMPACK_MT:
{
switch (precision1)
{
case STRUMPACK_FLOAT:
printf("srtumpack_float %d\n", verbose);
break;
case STRUMPACK_DOUBLE:
printf("srtumpack_double %d\n", verbose);
break;
default:
printf("ERROR: wrong precision!");
}
}
break;
default:
printf("ERROR: wrong interface!");
}
return 0;
}
I don't know that call this c subfunction with Fortran.because of this structs:
typedef enum
{
STRUMPACK_MT,
STRUMPACK_MPI_DIST
} STRUMPACK_INTERFACE;
I don't know how to solve this problem . I will appreciate any contribution, suggestion about the problem.
Thanks
That isn't a structure, but an enum (enumeration) supported by ISO binding entity ENUM.
In case your binding miss enumerations the following is a workaround.
Enums in C are more or less constant integers which values are assigned by compiler in generally increasing way. You can also force values for each enum member using assignment as in:
typedef enum
{
STRUMPACK_FLOAT = 0,
STRUMPACK_DOUBLE,
STRUMPACK_FLOATCOMPLEX = 100
} STRUMPACK_PRECISION
In this case i.e. we impose to STRUMPACK_FLOATCOMPLEX the value 100. We made the same with the first member, in any case the first member have value 0 by default. The second member STRUMPACK_DOUBLE will get the value 1 as progressive increment from previous member.
Anyway you can get better info on how enum works googling on the net.
In your case the easier way to solve the problem is to convert enums in definitions and using int's as type like in:
#define STRUMPACK_FLOAT 0
#define STRUMPACK_DOUBLE 1
#define STRUMPACK_FLOATCOMPLEX 2
typedef int STRUMPACK_PRECISION;
#define STRUMPACK_MT 0
#define STRUMPACK_MPI_DIST 1
typedef int STRUMPACK_INTERFACE;
typedef struct
{
int solver;
STRUMPACK_PRECISION precision1;
STRUMPACK_INTERFACE interface1;
} STRUMPACK_SparseSolver;
int STRUMPACK_init(STRUMPACK_SparseSolver * S, STRUMPACK_PRECISION precision1,
STRUMPACK_INTERFACE interface1, int verbose)
{
S->precision1 = precision1;
S->interface1 = interface1;
switch (interface1)
{
case STRUMPACK_MT:
{
switch (precision1)
{
case STRUMPACK_FLOAT:
printf("srtumpack_float %d\n", verbose);
break;
case STRUMPACK_DOUBLE:
printf("srtumpack_double %d\n", verbose);
break;
default:
printf("ERROR: wrong precision!");
}
}
break;
default:
printf("ERROR: wrong interface!");
}
return 0;
}

Enum. Can't find what's wrong

In a header file:
typedef struct apartment_t* Apartment;
typedef enum { EMPTY, WALL } SquareType;
struct apartment_t {
SquareType** squares;
int width;
int length;
int price;
};
in the source file:
int apartmentTotalArea(Apartment apartment) {
int countEmpty = 0;
for (int i=0;i<apartment->length;i++)
for (int j=0;j<apartment->width;j++) {
SquareType Square = apartment->squares[i][j];
switch(Square) {
case Square.EMPTY: // Bad
countEmpty++;
break;
case Square.WALL: // Bad
break;
}
}
This function counts the empty spots in a given 2d array. I'm facing a problem in the switch, it'll mark both cases as bad statements. What's wrong with my code? Thank you.
There is no such thing as Square.EMPTY or Square.WALL in your code. Use:
switch(Square) {
case EMPTY: // Juse EMPTY, not Square.EMPTY
countEmpty++;
break;
case WALL:
break;
}

Referencing the values in pointers to arrays (c)

Note: Fixed (decription at bottom)
For some reason the following code:
(*p_to_array)[m_p->number_of_match_positions] = (*p_to_temp_array)[k];
where the types are:
match_pos_t (*p_to_array)[];
match_pos_t (*p_to_temp_array)[];
int number_of_match_positions;
int k;
BTW: match_pos_t is a struct:
typedef struct match_pos
{
char* string;
long match_position;
}match_pos_t;
causes a 'syntax error before '(' error'
This error does not occur if this code replaced with other code.
Could someone give me an idea of why this is causing a syntax error, and how I should fix this problem?
Entire relevant code:
typedef struct match_pos
{
char* string;
long match_position;
}match_pos_t;
typedef struct match_positions
{
int number_of_match_positions;
match_pos_t (*match_positions)[];
}match_positions_t;
typedef struct search_terms
{
int number_of_search_terms;
char* search_terms[];
}search_terms_t;
int BMH_string_search(char* search_string, char* file_string, match_positions_t* match_positions)
{
return 0;
}
int determine_match_pos(search_terms_t** s_terms, char* file, match_positions_t* m_p)
{
int i,j,k;
match_positions_t* temp_m_p;
i=0;
/* s_terms is a null terminated data structure */
while((*s_terms+i) != NULL)
{
for(j=0; j<(*s_terms+i)->number_of_search_terms; j++)
{
/* search for the string positions */
BMH_string_search((*s_terms+i)->search_terms[j], file, temp_m_p);
/* load out search positions into the return array */
if(temp_m_p->number_of_match_positions != 0)
{
int total_m_ps = m_p->number_of_match_positions + temp_m_p->number_of_match_positions;
m_p->match_positions = (match_pos_t (*)[])realloc(m_p->match_positions, sizeof(match_pos_t)*total_m_ps);
k = 0;
for( ; m_p->number_of_match_positions<total_m_ps; m_p->number_of_match_positions++)
{
(*(m_p->match_positions))[m_p->number_of_match_positions] = (*(temp_m_p->match_positions))[k];
k++;
}
}
free(temp_m_p);
}
i++;
}
return 0;
}
It appears I have been rather stupid. An extra set of parenthesis around the values being referenced does the trick (question code has been updated with fix):
Original:
(m_p->*match_positions)[m_p->number_of_match_positions] = (temp_m_p->*match_positions)[k];
Fixed:
(*(m_p->match_positions))[m_p->number_of_match_positions] = (*(temp_m_p->match_positions))[k];
If anyone has an explanation, though, about why the first is incorrect, rather than the second, it would be nice to hear though, as I thought that
object->*object2
was the same as
*(object->object2)
Is this correct or is there some c definitions that I am missing out on here?
I thought that object->*object2 was the same as *(object->object2)
No, in C, the . and -> operators expect an identifier as their right operand. The .* and ->* operators don't exist in C, you have to spell out *(structure.member) or *(structure_ptr->member) manually.

Resources