Check Structure, add items if not already in structure. C - c

I'm trying to do some practice programming and I've come to a, for me, a difficult problem.
The problem is I'm supposed to write a program the will take the make and model of a car that was "entered" and place it in the structure, if the make an model are not there, otherwise it does nothing.
This is what I have so far, and I keep getting errors:
#include <stdio.h>
#include <string.h>
void addCar(struct car u, int* count, char *make[], char *model[]);
struct car { char make[30]; char model[30]; };
int main(void)
{
struct car unique[10] = {{"Ford", "Explorer"}, {"Honda", "Civic"},
{"Honda", "Accord"}, {"Chevy", "Malibu"}};
int i, count = 4;
addCar(unique, &count, "Ford", "Mustang");
}
void addCar(struct car u, int* count, char *make[], char *model[])
{
}
The line that says addCar(unique, &count,... it's saying "Argument type 'struct car' is incomplete" and the last line says "conflicting types for addCar"
Could you all give me a few pointers, please?
EDIT:
Okay, here is what my code is now, but I still can't get it to work. Any other suggestions would be appreciated!
#include <stdio.h>
#include <string.h>
struct car { char make[30]; char model[30]; };
void addCar(struct car *u, int *count, char *make, char *model);
int main(void)
{
struct car unique[10] = {{"Ford", "Explorer"}, {"Honda", "Civic"},
{"Honda", "Accord"}, {"Chevy", "Malibu"}};
int i, count = 4;
printf("%s", unique[0].make);
addCar(unique, &count, "Ford", "Mustang");
}
void addCar(struct car *u, int *count, char *make, char *model)
{
int i = 0;
for (i; i < *count; i++)
{
if ((u[i].make != make) && (u[i].model != model))
{
strcpy(u->make, make);
strcpy(u->model, model);
count++;
}
}
for (i = 0; i < *count; i++)
printf("%s, %s", u[i].make, u[i].model);
}

struct car unique[10] = {{"Ford", "Explorer"}, {"Honda", "Civic"},
{"Honda", "Accord"}, {"Chevy", "Malibu"}};
This is an array of struct car, therefore, you need to declare your addCar function as follow
void addCar(struct car *u, int *count, char *make, char *model)
*make and *model represent 2 strings. You have a mistake when you have char *make[], which declares an array of string.

Your function prototype for addCar is defined and uses 'struct car' before you define 'struct car'. Try moving the structure definition above the prototype for addCar.

Here are a few things that I figured out when looking at your code.
In this case, I think it's best if you use while loop rather than for loop.
Secondly, if you want to make sure that the car you want to add does not exist in the list, I suggest you use this
while (i < *size) {
if ((u[i].make == make) && (u[i].model == model)) { break; } // check if the car is already in the list
i++;
}
It checks the whole list for the existence of an element with the same make and model.
Here is the code I modified from yours. I hope it helps you.
#include <stdio.h>
#include <string.h>
struct car { char make[30]; char model[30]; };
void addCar(struct car *u, int *count, char *make, char *model);
int main(void)
{
struct car unique[10] = {{"Ford", "Explorer"}, {"Honda", "Civic"},
{"Honda", "Accord"}, {"Chevy", "Malibu"}};
int i, count = 4;
addCar(unique, &count, "Ford", "Mustang");
for (i = 0; i < count; i++) {
printf("%s, %s\n", unique[i].make, unique[i].model);
}
}
void addCar(struct car *u, int *size, char *make, char *model)
{
int i = 0;
while (i < *size) {
if ((u[i].make == make) && (u[i].model == model)) { break; } // check if the car is already in the list
i++;
}
if (i == *size) { // car found
struct car c;
strcpy(c.make, make);
strcpy(c.model, model);
u[i] = c;
(*size)++;
}
}

Related

Swapping struct array elements

I have difficulty applying the pass by reference and pass by value separation in structs.How can I swap the elements of the fixed size struct array as below.
struct try{
int num;
char name[10];
};
int main(){
struct try book[3];
void swapper(/********/);// <-what should be the argument of this function
}
void swapper(/********/){//swap second and third element of struct array
/*how the swap may be done?
temp=book[2];
book[2]=book[3];
temp=book[3];*/
}
There are a lot of ways to do what you're asking. One approach:
#include <stdio.h>
struct try {
int num;
char name[10];
};
void
swapper(struct try *a, int b, int c)
{
struct try tmp = a[b];
a[b] = a[c];
a[c] = tmp;
}
void
display(const struct try *t, size_t count)
{
while( count-- ){
printf("%d: %s\n", t->num, t->name);
t += 1;
}
}
int
main(void) {
struct try book[] = {
{ 1, "foo"},
{ 2, "bar"},
{ 3, "baz"}
};
display(book, sizeof book / sizeof *book);
swapper(book, 1, 2);
display(book, sizeof book / sizeof *book);
return 0;
}

I can't find my segmentation fault: 11 error

I am new to C and wanted to break the series of videos to try a project, but I am stuck on a segmentation error. I get that that means I am trying to access memory I'm not allowed to, but I don't see the issue... I have a lot of code so I'll paste the parts that seem like they might be causing the problem and take out the includes. I am making a command-line text adventure game where two players can choose their name, class, and race (and currently the game ends after it asks them for the input). I appreciate it:
main.c
int main() {
// See term dimesions
// Create Player
struct User* Player;
CreatePlayer(Player);
// Create Player
struct User* Player2;
CreatePlayer(Player2);
return 0;
}
story.c
void CreatePlayer(struct User* Player) {
char name[MAXINPUT];
char class[MAXINPUT];
char race[MAXINPUT];
// Ask for name
printf("%sWhat is your name?\n:\t", KNRM);
getInput(name);
printf("%sHello %s!\n", KNRM, name);
{
// Ask for class
char question[] = "What is your class (Type '1' for Fighter or '2' for Mage)?\n:\t";
char options[] = "12";
char coorilations[][MAXINPUT] = {"Fighter", "Mage"};
questionLoop(question, options, coorilations, class);
InitializeClass(Player, class);
printf("%sYou are now a %s!\n", KNRM, class);
}
{
// Ask for race
char question[] = "What is your race (Type '1' for Human or '2' for Elf)?\n:\t";
char options[] = "12";
char coorilations[][MAXINPUT] = {"Human", "Elf"};
questionLoop(question, options, coorilations, race);
printf("%sYou are now a %s!\n", KNRM, race);
}
strcpy(Player->name, name);
strcpy(Player->race, race);
}
modules.c
void InitializeClass(struct User* Player, char* class) {
if (compare(class, "Fighter")) {
strcpy(Player->class.name, "Fighter");
Player->class.maxHealth = 10;
Player->class.health = 10;
Player->class.strength = 7;
} else if (compare(class, "Mage")) {
strcpy(Player->class.name, "Mage");
Player->class.maxHealth = 7;
Player->class.health = 7;
Player->class.strength = 10;
}
}
void getInput(char res[]) {
int i = 0;
int c;
printf("%s", KMAG);
c = getchar();
while(c != '\n') {
res[i++] = c;
c = getchar();
}
res[i] = '\0';
}
void questionLoop(char question[], char options[], char coorilations[][MAXINPUT], char var[]) {
printf("%s-------------------------------\n", KGRN);
printf("%s%s", KNRM, question);
getInput(var);
for(int i = 0; i < strlen(options); i++) {
if (options[i] == var[0] && var[1] == '\0') {
strcpy(var, coorilations[i]);
printf("%s", KNRM);
return;
}
}
printf("%sSorry that was not an option...\n", KNRM);
questionLoop(question, options, coorilations, var);
}
int compare(char one[], char two[]) {
for (int i = 0; one[i] != '\0'; i++) {
if (one[i] != two[i]) {
return 0;
}
}
return 1;
}
modules.h
#ifndef HEADER_FILE
#define HEADER_FILE
#define MAXINPUT 20
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KYEL "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMAG "\x1B[35m"
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
// Classes
struct Class {
char name[MAXINPUT];
int strength;
int health;
int maxHealth;
};
// User struct
struct User {
char name[MAXINPUT];
char race[MAXINPUT];
struct Class class;
};
// Utilities
void getInput(char res[]);
void questionLoop(char question[], char options[], char coorilations[][MAXINPUT], char var[]);
int compare(char one[], char two[]);
// Game Setup Functions
void CreatePlayer(struct User*);
void InitializeClass(struct User* Player, char* class);
// Game Functions
void GameLoop(struct User*);
void ViewStats(struct User*);
#endif
You never allocate memory for your Player, so from you main method, you call CreatePlayer(), which in turns calls questionLoop(), which does nothing in terms of memory allocations, and then InitializeClass(), which does (amongst others):
strcpy(Player->class.name, "Fighter");
but Player doesn't exist, since you haven't actually create it, you haven't allocated for it, and thus a Segmentation fault occurs (here on the very next lines of that method).
Try dynamically allocating memory using malloc() (e.g. struct User* player = malloc(sizeof(struct User));, and don't forget to free() it when you are done.
This declares a pointer:
struct User* Player;
It is, however, completely uninitialized. It cannot be used before you populate it with something. The CreatePlayer function should assume this responsibility.
Typically these functions look like:
struct User* CreatePlayer() {
struct User *player = malloc(sizeof(struct User));
if (player == NULL) {
return NULL;
}
// Do stuff with player
return player;
}
Where that pattern can be used for any "Create" type function.

trying to add a variable of a certain type inside an array of that type

So i want to create an array of a structure that i made called jogo
Structure:
typedef struct jogo
{
int ident;/*idp of a product*/
char nome[1024]; /* string that describes a team eg. Barcelona */
char *equipas[2]; /*array of strings like {"Barcelona","Madrid"}*/
int score[2]; /*array of strings like {"Barcelona","Madrid"}*/
}* jogo;
I want to create an array without a specific size to store variables of type jogo.
When i type (add) a nome:equipa1:equipa2_score1:score2 like a elclassico:barcelona:madrid:1:0,i want to create a variable of type jogo and store it inside the array sistema_jog.
if i store something and the array is full i want reallocate the size of the array in order to store more variables of type jogo.
But for some reason im always getting segmentation fault core dumped when i try to do it and i dont know why.
Program:
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024 /* max characters of a word */
#define MAX_SIZE 5
int line = 1; /* counts the number of lines of the stdin */
static int size = MAX_SIZE;
int i = 0; /*ident of the variable jogo*/
int size_until = 0;
typedef struct jogo
{
int ident;/*idp of a product*/
char nome[MAX_CHARS]; /* string that describes a team eg. Barcelona */
char *equipas[2];
int score[2];
}* jogo;
jogo *sistema_jog;
void a(char nome[],char team1[],char team2[],int score1,int score2);
int team_not_in(char team1[],char team2[]);
int nome_in(char nome[]);
void cria_jogo(jogo s,char nome[],char equipa1[],char equipa2[],int score1,int score2);
int main() {
char c; char nome_jg[MAX_CHARS]; char eq1[MAX_CHARS]; char eq2[MAX_CHARS]; int pont1; int pont2;
sistema_jog = (jogo*) calloc(MAX_SIZE,sizeof(jogo));
while ((c = getchar())!= 'x') {
switch (c)
{
case 'a':
{
scanf("%1023[^:\n]:%1023[^:\n]:1023%[^:\n]:%d:%d",nome_jg,eq1,eq2,&pont1,&pont2);
i++;
printf("nome: %s",sistema_jog[0]->nome);
//a(nome_jg,eq1,eq2,pont1,pont2);
break;
}
}
}
return 0;
}
int nome_in(char nome[])
{
int i;
for(i=0; i < size; i++)
{
if (strcmp(sistema_jog[i]->nome,nome) == 0)
return 1;
}
return 0;
}
int team_not_in(char team1[],char team2[])
{
int i;
for (i=0;i<size;i++)
{
if((strcmp(sistema_jog[i]->equipas[0],team1) != 0) || (strcmp(sistema_jog[i]->equipas[1],team2) != 0))
return 1;
}
return 0;
}
void cria_jogo(jogo s,char nome[],char equipa1[],char equipa2[],int score1,int score2)
{
strcpy(s->nome,nome);
strcpy(s->equipas[0],equipa1);
strcpy(s->equipas[1],equipa2);
s->score[0] = score1;
s->score[1] = score2;
}
void a(char nome[],char team1[],char team2[],int score1,int score2)
{
int NL = line;
if (nome_in(nome) == 1)
printf("%d Jogo existente.",NL);
else if (team_not_in(team1,team2) == 0)
{
printf("%d Equipa existente.",NL);
}
else
{
jogo novo_jogo = (jogo) calloc(sizeof(jogo),sizeof(jogo));
cria_jogo(novo_jogo,nome,team1,team2,score1,score2);
if (size_until <= MAX_SIZE)
{
sistema_jog[size_until] = novo_jogo;
size_until++;
}
else
{
sistema_jog = (jogo*) realloc(system, sizeof(jogo)*size_until);
sistema_jog[size_until] = novo_jogo;
size_until++;
}
}
}
I am not surprised that you are confused.
As Christian Gibbons, Barmar and user12986714 said jogo must be your jogostruct and not a pointer to jogo. I supposed you changed, at some stage, } jogo; to }* jogo; because of compilation errors. But, it was not the original problem and after you are confused.
Let me explain shortly, try this basic code :
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024 /* max characters of a word */
#define MAX_SIZE 5
int line = 1; /* counts the number of lines of the stdin */
static int size = MAX_SIZE;
int i = 0; /*ident of the variable jogo*/
int size_until = 0;
typedef struct jogo
{
int ident;/*idp of a product*/
char nome[MAX_CHARS]; /* string that describes a team eg. Barcelona */
char *equipas[2];
int score[2];
}* jogo;
typedef struct jogo2
{
int ident;/*idp of a product*/
char nome[MAX_CHARS]; /* string that describes a team eg. Barcelona */
char *equipas[2];
int score[2];
} jogo2;
int main() {
printf("sizeof jogo %d\n",sizeof(jogo));
printf("sizeof jogo2 %d\n",sizeof(jogo2));
return 0;
}
As you could see jogo has a pointer size and jogo2 has the size of your struct.
More, there are various problems in your code. Everything is briefly commented directly in the code. Do not hesitate to ask questions.
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024
#define MAX_SIZE 5
int line = 1;
// static int size = MAX_SIZE; // Not useful. It is the same than MAX_SIZE
// int i = 0; this variable is not really used
int size_until = 0;
typedef struct jogo
{
// int ident; Never used
char nome[MAX_CHARS];
char equipas[2][1024]; // equipas is an array of two strings. If you use char *equipas[2], you will have to alloc memory for each string
int score[2];
} jogo; // * has been removed
jogo **sistema_jog; //sistema_jog is an array of pointer to jogo struct. You allocate it after.
// you could also have an array of jogo struct but it would need more modifications in your code.
// I suppose the confusion is here. To train, you could try to do : jogo * sistema_jog and to modify what it is needed in your code.
void a(char nome[],char team1[],char team2[],int score1,int score2);
int team_not_in(char team1[],char team2[]);
int nome_in(char nome[]);
void cria_jogo(jogo* s,char nome[],char equipa1[],char equipa2[],int score1,int score2); // *: s is a pointer to jogo struct. See comment on sistema_jog declaration
int main() {
char c; char nome_jg[MAX_CHARS]; char eq1[MAX_CHARS]; char eq2[MAX_CHARS]; int pont1; int pont2;
sistema_jog = (jogo**) calloc(MAX_SIZE,sizeof(jogo*)); // Each element of sistema_jog is a pointer to a jogo struct
while ((c = getchar())!= 'x') {
switch (c)
{
case 'a':
{
scanf("%1023[^:\n]:%1023[^:\n]:%1023[^:\n]:%d:%d",nome_jg,eq1,eq2,&pont1,&pont2); // be carefull, see % and 1023 in the third field of your code
// i++; not used elsewhere
a(nome_jg,eq1,eq2,pont1,pont2);
break;
}
}
}
// Only to check
for (int i=0; i<size_until;i++)
printf ("%s:%s:%s:%d:%d\n",
sistema_jog[i]->nome,
sistema_jog[i]->equipas[0],
sistema_jog[i]->equipas[1],
sistema_jog[i]->score[0],
sistema_jog[i]->score[1]);
return 0;
}
int nome_in(char nome[])
{
int i;
for(i=0; i < size_until; i++) // size_until : You have to check only elements that exist either you have less or more elements than size (static int = MAX_SIZE)
{
if (strcmp(sistema_jog[i]->nome,nome) == 0)
return 1;
}
return 0;
}
int team_not_in(char team1[],char team2[])
{
int i;
for (i=0;i<size_until;i++) // size_until : Idem as above
{
if((strcmp(sistema_jog[i]->equipas[0],team1) != 0) || (strcmp(sistema_jog[i]->equipas[1],team2) != 0))
return 1;
}
return 0;
}
void cria_jogo(jogo* s,char nome[],char equipa1[],char equipa2[],int score1,int score2) // * : s is a pointer to jogo struct
{
strcpy(s->nome,nome);
strcpy(s->equipas[0],equipa1);
strcpy(s->equipas[1],equipa2);
s->score[0] = score1;
s->score[1] = score2;
}
void a(char nome[],char team1[],char team2[],int score1,int score2)
{
int NL = line;
if (nome_in(nome) == 1)
printf("%d Jogo existente.",NL);
/* else if (team_not_in(team1,team2) == 0)
{
printf("%d Equipa existente.",NL);
} */ // I do not understand the objective of this test. So, I commented it. But it is not the question
else
{
jogo* novo_jogo = (jogo*) malloc(sizeof(jogo));
cria_jogo(novo_jogo,nome,team1,team2,score1,score2);
if (size_until < MAX_SIZE) // = has been removed. Index of array goes from 0 to size of array-1
{
sistema_jog[size_until] = novo_jogo;
size_until++;
}
else
{
sistema_jog = (jogo**) realloc(sistema_jog, sizeof(jogo**)*(size_until+1)); // *: see comment on sistema_jog declaration, +1: array index goes from 0 to size-1
// Remark : It is not efficient to realloc one by one. It would better to realloc MAX_SIZE by MAX_SIZE. You could try to do it
sistema_jog[size_until] = novo_jogo;
size_until++;
}
}
}

Incompatible pointer type when making structure of function pointers

I'm trying to make a array of structures which contain a string and a function pointer, however when I compile I get a warning that I've initialized from an incompatible pointer type.
I have no idea why (sorry if I sound ignorant, I'm fairly new to C programming).
typedef struct
{
char Player1[2], Player[2], **gameGrid;
int height,width;
int moveNum, player1Num, player2Num;
bool player1Win, player2Win;
}Game;
typedef int (*pointer_func)(Game *);
typedef struct
{
char *funcName;
pointer_func *f;
}userFunc;
int save(Game *struc);
int load(Game *struc);
int move(Game *struc);
int quit(Game *struc);
void free_grid(Game *struc);
int main(){
//initialised variables
userFunc Name_arr[] = {
{"save",save},
{"load",load},
{"quit",quit},
{"move",move}
};
The four functions being referenced are as follows:
int save(Game *struc)
{
char *str, *inputString, *writeString;
FILE *fp;
int nextPlayer;
int maxRead = 20;
bool DIRresponse;
while(true)
{
printf("Please provide a file name (20 characters max): ");
inputString = input_String(inputString, maxRead, stdin);
if((DIRresponse = check_Directory(inputString)) == true){
printf("That name already exists, choose another\n");
continue;
}
else
break;
}
if(struc->moveNum % 2 == 0)
nextPlayer = struc->player1Num;
else
nextPlayer = struc->player2Num;
sprintf(str,"%s.txt",inputString);
fp = fopen(str,"w");
sprintf(writeString, "%d %d %d %d %d", nextPlayer, struc->height,
struc->width, struc->moveNum, struc->moveNum);
fprintf(fp,writeString);
fclose(fp);
return 0;
}
int move(Game *struc)
{
return 1;
}
int load(Game *struc)
{
return 1;
}
int quit(Game *struc)
{
free_grid(struc);
exit(EXIT_SUCCESS);
}
You have a mismatch in levels of pointers:
typedef int (*pointer_func)(Game *); << Pointer type
typedef struct
{
char *funcName;
pointer_func *f; << Pointer to a pointer type.... OOPS
}userFunc;
Make *f -> f and it should work.

Why updated structure variable not printing

This is my code in which if student marks is greater than 85,scholarship status will be changed to sanctioned, but after updating it is not printing
#include<stdio.h>
#include<string.h>
struct scholor
{
char name[25];
int sem;
int marks;
char status;
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",&s1.name,&s1.sem,&s1.marks,&s1.status);
sanction(s1.marks,&s1.status);
printf("%s",s1.status);
}
status is a single char but you are storing a string into it, effectively doing out of bounds access (undefined behaviour). Change it to an array and then you'll be able to copy.
struct scholor
{
char name[25];
int sem;
int marks;
char status[128];
};
and adjust the calls and passing (since status is an array now -- its name gets converted into a pointer t its first element when passed to functions):
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
Other suggestions:
1. Use a standard prototype for main such as: int main(void)
2. You could usr strcpy to copy the string as opposed to doing it yourself.
Your struct should have status as a character array not a character .Moreover when you scanf an array dont write & before because the name itself points to the assdress of the first element.Your corrected program is :
struct scholor
{
char name[25];
int sem;
int marks;
char status[16];
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
}

Resources