Dynamic struct in C - c

I am trying to read the inputed name, save it in a dynamic struct, add a number at the end if it and count it up. I managed to do the first part, but i cant seem to pass the struct address to the function that should count, nor make the function work.
struct ime_dadoteke
{
unsigned char *ime;
unsigned char velikost;
//this is the struct im working with
};
This is the main:
struct ime_dadoteke *ime;
ime = ime_init();
int i=1;
do
{
naslednje_ime(ime, i); /*here is the problem with passing the
address. I also tried &ime with parameter
struct ime_dodoteke **ptr.
I get error cannot convert argument 1
from 'ime_dadoteke *' to 'ime_dodoteke *' */
i++;
} while (i <= st_korakov);
This is the first function which works:
struct ime_dadoteke* ime_init()
{
int i;
struct ime_dadoteke *rtn = (struct ime_dadoteke*)malloc(sizeof(struct ime_dadoteke));
printf_s("Vnesi ime slike.\n");
rtn->ime =(unsigned char*)malloc(sizeof(unsigned char));
for (i=0; rtn->ime[i-1]!=10; i++)
{
scanf("%c", &rtn->ime[i]);
rtn->ime = (unsigned char*)realloc(rtn->ime, (i+2)*sizeof(unsigned char));
};
rtn->ime[i]='\0';
rtn->velikost = i;
fseek(stdin, 0, SEEK_END);
return rtn;
};
And this is the skeleton of the function that should count the number at the end of the name. I didnt build it yet because i get a problem: pointer to incomplete class is not allowed.
void naslednje_ime(struct ime_dodoteke *ptr, int i)
{
struct ime_dadoteke *ime = ptr;
ptr /*ptr is underlined (error) */->ime[ptr /*ptr is underlined (error) */->velikost - 1] = '0';
};
Also note i created the struct with size of string in it because strlen() doesnt wanna take a non const char. Is there a way around this?

The error message pointer to incomplete class is not allowed means the structure (you told us that referencing members of the struct ime_dadoteke via pointer struct ime_dadoteke *ptr caused the error message) is not defined in the source unit where naslednje_ime is defined. You need to put the struct definition in a header file and include it wherever you use it, also in the file where you define naslednje_ime.

Related

Pass a string in a struct to a function and return it

I want to return the name of the smallest city population-wise, if it is the second city. (Please don't mind the if statement, I know it's bland), the missing return is what bothers me.
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
typedef struct Coordinate{
int x,y;
}Coordinate;
typedef struct city{
char name[20];
int population;
Coordinate coordinates;
}city;
char *rSmallestCity(city **cl, int n)
{
char *rtrn = NULL;
if(cl[n-2]->population>cl[n-1]->population)
{
rtrn = &cl[n-1]->name;
}
return rtrn;
}
int main()
{
city c1 ={.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4};
city c2 ={.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2};
city *clist[2];
clist[0]=&c1;
clist[1]=&c2;
printf("\n%s is smallest\n",rSmallestCity(clist,2));
}
warning: assignment to 'char ' from incompatible pointer type 'char ()[20]' [-Wincompatible-pointer-types]|
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
A good question. And your assumption is correct. Creating a variable inside a function it's existence ends upon leaving the function. But in this case, because the struct member name is already a char * you do not need to create another variable. Just return c1.name. (see code example below.)
A few other suggestions:
In the struct declaration:
typedef struct Coordinate{
int x,y;
}Coordinate;
You've used the same symbol (Coordinate) for the struct name, and for it's typedef. This is not a good practice. If you need both a struct name and a typedef, pick different symbols. BTW, in this this example, only one or the other is needed. Say you pick the typedef, then the struct is completely defined by:
typedef struct {
int x,y;
}Coordinate;
That suggestion applies to both struct declarations in your example code.
The signatures for the main function do not include int main(){...} rather
int main(void){..., return 0;} and int main(int argc, char *argv[]){..., return 0;}
The following code example illustrates some of the other suggestions for improvements in comments under your post,
typedef struct {
int x,y;
}Coordinate;
typedef struct {
char name[20];
int population;
Coordinate coordinates;
}city;
//return char * rather than char to allow for full null terminated char array (string)
char * rSmallestCity(city c1[],int cityCount)//generisize function prototype to
{ //to easily accommodate bigger arrays if needed
long long size, sizeKeep = 8e9; //index and population. initialize larger than possible population
int indexKeep = 0;
//note you do not need to define a char *, the struct already contains one
for(int i=0; i<cityCount; i++)//use a loop rather than a single comparison, keep the smalles
{
size = c1[i].population;
sizeKeep = (size < sizeKeep) ? indexKeep = i, size : sizeKeep;
}
printf("\n%s\n",c1[indexKeep].name);
return c1[indexKeep].name;
};
int main(void)//use minimum signature for main, and call return before leaving.
{
//combining your original declarations and assignments for struct
//into a single declaration/definition.
city c1[] = {{.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4},
{.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2}};
int cityCount = sizeof(c1)/sizeof(c1[0]);
printf("\n%s is smallest",rSmallestCity(c1, cityCount));
return 0;
};
The solution that I originally left in comment under OP (remove & in the line &cl[n-1]->name;) needs some explanations to avoid problems later.
(It is an educational answer not a full answer on pointers, array decay, ... And many examples can be found on stackoverflow. I tried to simplify)
Try this simple code.
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1);
printf("%p\n",&myString1);
}
The output is the same, but an array name and the address of an array name are not the same. The array name is evaluated to the address of its first element. So it works in your case but a warning is issued during compilation and it is very important. Firstly, do not remove compilation warnings.
Now, try this code :
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1+1);
printf("%p\n",&myString1+1);
}
The outputs are different. Because myString1 is evaluated to char* and &myString1 to char [25]. So +1, in the first, case adds one (sizeof char) to the pointer and in the other case, it adds 25.
Delete the "&" in the line:
rtrn = &cl[n-1]->name;
To extremely simplify, you assigned an "address of char[]" to a char*, but array syntax makes it work regardless.

Understanding pointer structs in C

I am trying to understand an assignment I have before I have to take a final. I am trying to understand what exactly I am declaring.
So in a given file the typedef struct's are declared as so:
(Struct Declaration)
/** The following two structs must be defined in your <gamename>.c file **/
typedef struct game_position_t *game_position;
/* move struct must code enough information to reverse the move, given the resulting position */
typedef struct move_t *move;
I have then built the structs out as so (yes this has to be separated just because it is interfaced programming):
(Struct Definition)
/** The following two structs must be defined in your <gamename>.c file **/
struct game_position_t {
int mathy;
int numrows;
int *sizes;
};
/* move struct must code enough information to reverse the move, given the resulting position */
struct move_t {
int rownum;
int move_size;
};
Then an example of a functions and declaration of game_position for example is:
(Example Function)
/* return the starting position, NULL if error */
game_position starting_position(int me_first, int argc, char **argv) {
if (argc < 3) {
printf("\n\nToo few arguments, see help below\n\n");
game_help(argv[0]);
return NULL;
}
int mathy;
if (strcmp(argv[2],"search")==0)
mathy = 0;
else if (strcmp(argv[2],"mathy")==0)
mathy = 1;
else {
printf("\n\nSecond argument must be \"search\" or \"mathy\", see help below\n\n");
game_help(argv[0]);
return NULL;
}
int play_default = (argc==3);
if (play_default) printf("\n\nOK, we will play the default game of 7 5 3 1\n\n");
int defaultgame[4] = {7,5,3,1};
game_position result = malloc(sizeof(struct game_position_t)*1);
result->mathy = mathy;
if (result) {
result->numrows = (play_default ? 4 : argc-3);
result->sizes = malloc(sizeof(int)*(result->numrows));
int row;
for (row=0; row<(result->numrows); row++)
(result->sizes)[row] = (play_default ? defaultgame[row] : strlen(argv[row+2]));
}
return result;
}
So my main misunderstanding is when using a struct declaration in this manner, specifically putting the * before the name like this, typedef struct move_t *move;. Is that previous line saying move it a struct pointer or dereferencing move? Continuing from that. When defining them I just use the struct name such as struct move_t. I don't fully understand how they are linking together and in what matter. Then inside the function I just declare game_position, but still need to use a derefencer, 'p->`, to access it fields. So if someone could explain to me when these struct variables are points to structs and when they are the actual struct.
An example of my misunderstanding is that in the Example Function after result was declared. I first thought to use the . operator to access and set it's fields. I then changed it due to compiler errors, but now I want to understand my misunderstanding. And why did I I have to malloc game_position_t and not game_position?
typedef defines a type, so typedef struct move_t *move defines a new type named move, which is a pointer type, pointing to struct move_t. So after this if you define a variable with move ptr, ptr will have a pointer type so that you should use the syntax of accessing members through a pointer. When allocating memory for it, of course you have to specify the exact size of the structure other than the size of a pointer, that's sizeof(struct move_t)

Deferencing pointer to incomplete type error in C

I'd like to know why I am getting this,
Error:
error: dereferencing pointer to incomplete type
strncpy(variables->part1[i], environ[i], placement);
main Code:
struct vars {
char **part1;
char **part2;
} ;
static struct vars *variables;
exportenviron(&variables);
function Code:
void exportenviron(struct vars* variables)
{
int i;
char *pch;
int placement;
for(i=0; environ[i]; i++) {
pch = strchr(environ[i], '=');
placement = pch-environ[i]+1;
strncpy(variables->part1[i], environ[i], placement);
}
}
The file containing exportenviron isn't seeing the actual definition of your struct: instead, it only knows that struct vars exists, but not what's in it. For example, perhaps you have a header file vars.h included by the .c file with exportenviron in it, and vars.h contains only struct vars;

better usage of structures in embedded field

I'm bit new to c programming and i want to learn and use the structure facility in C programming.
I'm working in the embedded programming field of 8bit controllers.
I have a situation in which
objective:
To set time and date or more things.
To get time and date or more things.
Problem: I have two source files main.c and set_get.c i have a struct
varaible in main.
Aim : to set and get rtcc values from registers in pic18 series controllers and to create a test platform.
main()
{
struct data
{
unsigned char hour=10;
unsigned char date=20;
} entry;
entry=set_time_date(entry);
entry=get_time_date();
while(1);
}
and in set_get.c
i have two functions
//here struct parameter will be the input from main.c
struct data
{
unsigned char hour=10;
unsigned char date=20;
};
struct set_time_date(struct x)
{
struct data p1;
p1.hour=x.hour;
p1.date=x.date;
//do set hour register with p.hour value
//do set date register with p.date value
return(p1);
}
struct get_time_date(void)
{
struct data p1;
p1.hour= do read from hour register;
p1.date= do read from day register;
return(p1);
}
I would like to have your inputs on this and correct me if i have made any mistakes in the following pattern.I have done in this method so as to reduce global structs.
And im keenly waiting your review on this piece of code.Correct me if im wrong
Regards
Arookie
Note, there is a rich library of time functions included in C89, C99, etc.
time_t time (time_t *Current_Calendar_Time);
clock_t clock (void);
char *ctime (const time_t *Calendar_Time);
Just to name a few. But in keeping with the theme of what you have already done...
First, This code segment will not compile. Assignments cannot be made inside the struct definition:
struct data
{
unsigned char hour=10;
unsigned char date=20;
};
However, once the struct is defined, you can make assignments to each individual member (see examples in code example below) Or you can make a block assignment, like this:
//Note, I am using a typedef variation of your original for illustration:
typedef struct data{
unsigned char hour;
unsigned char date;
} data;
//make block assignment here:
// hour date
struct data a = {0x34, 0xA5};
Next, passing a pointer to struct is sometimes better than passing the struct itself. i.e. when volume of data is large, passing address (~4bytes) is preferable to passing possibly hundreds of bytes. (For the size of your struct, it is really not a concern) My examples will use pointers:
For readability, create a type:
//you originally used unsigned char for member types. I changed it to
//accommodate puctuation,as often, timestrings and datestrings use
//puncutation such as : or /
//The unsigned version is below this one...
#define TIME_LEN 20
#define DATE_LEN 20
typedef struct {
char hour[TIME_LEN];
char date[DATE_LEN];
} DATA;
//use DATA to create the other instances you need:
DATA entry, *pEntry;
//Your function prototypes become:
void set_time_date(DATA *x); //no need to return time in set function
DATA * get_time_date(void);
//In main, initialize pointer to struct this way:
int main(void)
{
pEntry = &entry;//initialize pointer pEntry to address of entry
sprintf(pEntry->date , "%s", "12/23/2014");
sprintf(pEntry->hour , "%s", "10:12:13");
set_time_date(pEntry);
pEntry = get_time_date();
return 0;
}
void set_time_date(DATA *x)
{
sprintf(pEntry->date, "%s", x->date);
sprintf(pEntry->hour, "%s", x->hour);
}
DATA * get_time_date(void)
{
sprintf(pEntry->date, "%s", "01/23/2014");
sprintf(pEntry->hour, "%s", "10:10:00");
return pEntry;
}
using unsigned char
In this section, changes have been made to accommodate minimization of global struct. By creating a typedef of the struct, say in a header file, you can then simply use DATA * where needed to create a local instance of the struct, and pass it as an argument...
//Your function prototypes become:
void set_time_date(DATA *x); //no need to return time in set function
DATA * get_time_date(DATA *x); //Edited to include argument
//In main, initialize pointer to struct this way:
int main(void)
{
//Create local instance of DATA:
DATA entry={0}, *pEntry;
pEntry = &entry;//initialize pointer pEntry to address of entry
pEntry->date = 0x12;
pEntry->hour = 0x23;
set_time_date(pEntry);
pEntry = get_time_date(pEntry);
//print results showing values of both pEntry and entry
printf("pEntry->date: 0x%x\n", pEntry->date);
printf("entry.date: 0x%x\n", entry.date);
printf("pEntry->hour: 0x%x\n", pEntry->hour);
printf("entry.hour: 0x%x\n", entry.hour);
//After the assignment: "pEntry = &entry;" (above)
//pEntry is pointing to the the same location
//in memory as the start of entry. (this is the reason for that assignment)
//Every subsequent assignment you make to pEntry, is also being
//written to entry, without explicitly having to
//write: entry.date = 0x23 etc. (indeed, it is the same location
//in memory you are writing to)
return 0;
}
void set_time_date(DATA *x)
{
x->date = 0xBC;
x->hour = 0x45;
}
DATA * get_time_date(DATA *pX)
{
//Commented following two lines, passed in as argument:
//DATA x, *pX; //now passed in as argument
//pX = &x;//initialize pointer pX to address of x
pX->date = 0x23;
pX->hour = 0x34;
return pX;
}
Produces following output

how do i get values stored in struct?

I am trying to retrieve values from an array of structs. I do not know the correct ways to retrieve them.
Here is my struct:
struct entry{
char name[NAME_SIZE];
int mark;
};
typedef struct entry Acct;
Acct dism2A03[MAX_ENTRY];
How i assigned values:
void add_new(char *name,int mark){
printf("%s,%d",name,mark);
int v=0;
v=entry_total;
strcpy(dism2A03[v].name,name);
dism2A03[v].mark = mark;
}
What i tried (DOES NOT WORK):
int m=0;
for(m=0;m<MAX_ENTRY;m++){
char name[NAME_SIZE] = dism2A03[m].name;
line 75 >> int mark = dism2A03[m].mark;
printf("\nEntry %d",m);
printf("%s",name);
printf("%d",mark);
}
ERROR:
p9t2.c: In function ‘main’:
p9t2.c:75:5: error: invalid initializer
Your first attempt implies existence of getfield function that takes a struct and a multicharacter char literal and gets the field; there is no such function in C.
Your second attempt is much closer: rather than trying to assign the name to an array, assign it to a char pointer, like this:
int m=0;
for(m=0;m<MAX_ENTRY;m++){
// Since you aren't planning on modifying name through pointer,
// you can declare the pointer const to make your intentions clear.
const char *name = dism2A03[m].name;
int mark = dism2A03[m].mark;
printf("\nEntry %d",m);
printf("%s",name);
printf("%d",mark);
}

Resources