Comparing a string with a struct member in C - c

I am attempting to create a small ticket pricing system. The user inputs the people accompanying them to the theme park as a command line argument (senior/adult/child/student) including themselves (what they are according to that list) and I compare the command line arguments with the struct members named tier - this part will be completed later with pointers to check each one, but until then I'm just attempting to get this lesser version of the completed program to work and cannot seem to. It won't allow me to compare a struct member (string) with a command line argument. I'm finding rectifying this slightly confusing because the error message
strcmpare.c:17:29: error: use of undeclared identifier 'senior' if (strcmp(argv[a], senior.tier[a]) == 0)
isn't yielding any clues as to what I should do. Here's the code so far (I am using the cs50 course and sandbox, thus the cs50.h header file. Apologies in advance, I'm not sure what the equivalent is in C):
#include <cs50.h>
#include <stdio.h>
#include <string.h>
struct ages
{
char tier[7];
int price;
};
void structorganizer(struct ages senior, struct ages adult, struct ages child, struct ages student);
int main(int argc, string argv[])
{
for (int a = 0; a <= (argc-1); a ++)
{
if (strcmp(argv[a], senior.tier[a]) == 0)
{
printf("no errors");
return 0;
}
printf("scrutinise more");
return 1;
}
}
void structorganizer(struct ages senior, struct ages adult, struct ages child, struct ages student)
{
strcpy(senior.tier, "Senior");
senior.price = 10;
strcpy(adult.tier, "Adult");
adult.price = 30;
strcpy(child.tier, "Child");
child.price = 0;
strcpy (student.tier, "Student");
student.price = 20;
}

I'm finding rectifying this slightly confusing because the error message isn't yielding any clues as to what I should do.
On the contrary, it actually tells you EXACTLY what to do. That's not always the case with error messages, but here it is. The variable senior is not declared, so you need to declare it.
So where should you do that. You seem to want to use structorganizer to initialize things. Usually, global variables are a thing you want to avoid and there are certainly better ways of solving this, but just to quickly get things working. Remove all arguments from the function and declare global variables before, and call structorganizer first thing in main like this:
struct ages
{
char tier[8]; // Changed to 8 because you need one more than the string length
int price;
};
// Evil global variables, just to make code work with as little
// changes as possible
struct ages senior, adult, ages, child, student;
void structorganizer(); // Init the evil globals
int main(int argc, string argv[])
{
structorganizer();
// Continue as before
That should be enough to just get the code working, but you clearly need to spend more time with the basics here. The code you're writing right now is too advanced for you. No shame in trying though :)
There are absolutely cases where it's good to use an initializer function, but I cannot really say that this is one of them. I would declare them in main like this:
int main(int argc, string argv[])
{
struct ages senior = { .tier = "Senior", .price=10 };
struct ages adult = { .tier = "Adult", .price=30 };
struct ages child = { .tier = "Child", .price=0 };
struct ages student = { .tier = "Student", .price=20 };

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.

How to gain access to objects locked behind doublepointer? (C)

In a homework task I must gain access to object specifics (i.e pID, Code), which are located in a structure. However, I need to link my function with the objects first (**ppObjects), but since I am dealing with a doublepointer, I seem to be having an issue.
It is worth noting that when I tried the same commands but function was PrintNewObject(HeaderC* pStruct4) it worked fine - so I am guessing it is an issue with me having to use doublepointer when dealing with pStruct4.
I have provided the code that I have tried below. While compiling it shows no error, but upon trying to print something from it, it says that obj is a nullpointer.
The function that I would like to link with ppObjects.
int InsertNewObject(HeaderC** pStruct4){
HeaderC* testinH;
for (testinH = *pStruct4; testinH != NULL; testinH = testinH->pNext)
{
int count = 0;
while (count < 26) //one for every letter in the alphabet, as ppObjects is an array
{
Object9* obj;
obj = (Object9*)testinH->ppObjects[count]; //the line that does not seem to properly define
printf("%lu", obj->Code); //running this line crashes my program
count++;
}
}
Header, where we can see that ppObjects is a doublepointer.
typedef struct headc
{
void **ppObjects; // Pointer to the array of pointers to objects.
// Objects may be of types Object1-10
char cBegin; // The first letter of ID of objects related to
// header is cBegin.
struct headc *pNext;
} HeaderC;
The object I was provided in the hometask is below. This is what I would get access to after defining
typedef struct ob9
{
char *pID;
unsigned long int Code;
Date3 *pDate3;
struct ob9 *pNext;
} Object9;
I get an error saying that obj is nullpointer when I try to print anything from obj.
If this is poorly worded, I am sorry. I tried my best to make this understandable yet not too long. Any help is appreciated!

Looking for ways to improve this code or if there is anything I shouldn't do [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
Trying to learn C so I made this short program to try and mimic classes. Is there anything with this code that I should not do with C or any ways that I can improve it at all like best practices or anything?
structs.h
struct weapon {
char name[30];
int damage;
int durability;
};
struct player {
int health;
int armor_level;
int currency;
struct weapon player_weap;
};
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "structs.h"
struct player new_player();
void main() {
struct player user = new_player();
printf("The players health is %d.\n", user.health);
printf("The players armor is %d.\n", user.armor_level);
printf("The players currency is %d.\n", user.currency);
printf("The players weapon is the %s.\n", user.player_weap.name);
printf("The players weapon does %d damage and has %d durability.\n", user.player_weap.damage, user.player_weap.durability);
}
struct player new_player() {
struct player new_player;
new_player.health = 100;
new_player.armor_level = 0;
new_player.currency = 0;
strcpy(new_player.player_weap.name, "Starter Sword");
new_player.player_weap.damage = 1;
new_player.player_weap.durability = 100;
return new_player;
}
Well there are few points:-
In case the structure is not too big you can do it in this way. It is perfectly correct.
malloc is computationally more costlier than copying variables on return from a function. In case the structure size is bigger then you should malloc it. That way you won't end up using a huge amount of memory in stack.
You should try to think of making the code reusable. You can keep a function which will print a structure. Something like (the same reason you kept a seperate function for getting an instance of struct).
void printPlayer(struct player p){
...
}
That way any time you try to print it - you would just call it. This saves you from repeating the same code of printing multiple times.
Another thing is, you can typedef the struct player to something more readable. In this case player is itself readable but in some cases typedef helps. But well that's debatable.
Also the main() should be (the OS expects an integer back)
int main(void){
..
return 0;
}
You can move the declaration of the function printPlayer or new_player to the header itself. That makes much more sense.
One another thing is using suitable names. structs.h is not a good name for a header file. In this project there won't be any struct header file? Keep the name Player.h or Game.h. That is much more readable.
Use header guards
#ifndef PLAYER_H
#define PLAYER_H
struct weapon {
char name[30];
int damage;
int durability;
};
struct player {
int health;
int armor_level;
int currency;
struct weapon player_weap;
};
#endif
It's just a matter of preference, but when I've used structs for things like that I've always done typedef to give myself a new data type. It makes writing the code easier, and helps me better comprehend what it is happening.
typedef struct {
char name[30];
int damage;
int durability;
} Weapon;
typedef struct {
int health;
int armor_level;
int currency;
Weapon player_weap;
} Player;
So instead of declaring a function like
struct player new_player();
You would do it like this
Player new_player();
It simulates the process of working with classes much better, IMO. Also, whoever told you to use void main() is horribly out of touch. Don't ever use that unless you're writing a kernel or a microcontroller or something. It's int main(void) for pretty much every programming environment. Make sure you return 0; if your program has finished running successfully.

get_symbol function in C

Im building a symbol table and im having a hard time writing get_symbol, which has the arguments of (symbol_table symtab, char sym). I have to write code for 2 functions get_symbol and set_symbol, I'm having some trouble understanding what a symbol table is and how to write out these two functions. it says that get_symbol() has two arguments: the symbol table, and the symbol name whose value should be retrieved. If the symbol name is one of A,B,C the corresponding value from the symbol table should be returned. if it is not one of those names, then 0 should be returned. If any one could help that would be great thanks for your time.
symbol_table.c Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "globals.h"
#include "symbol_table.h"
typedef struct symbol_table_s {
int a,b,c;
}*symbol_table_rep;
status init_symbol_table (symbol_table *p_symtab)
{
symbol_table_rep st = malloc(sizeof(struct symbol_table_s));
if (st == NULL)
return ERROR;
st->a = st->b = st->c = 0;
*p_symtab = (symbol_table) st;
return OK;
}
void destroy_symbol_table (symbol_table *p_symtab)
{
free(*p_symtab);
*p_symtab = NULL;
}
void set_symbol(symbol_table *p_symtab, char sym, int value)
{
/* WRITE CODE FOR THIS */
}
int get_symbol (symbol_table symtab, char sym)
{
/* WRITE CODE FOR THIS FUNCTION */
symbol_table_rep symtab;
if (A,B,C)
{
return symbol_table;
}else{
return 0;
}
}
symbol_table.h Code:
#ifndef _SYMBOL_TABLE_H
#define _SYMBOL_TABLE_H
#include "globals.h"
ABSTRACT_TYPE(symbol_table);
status init_symbol_table (symbol_table *p_symtab);
void destroy_symbol_table(symbol_table *p_symtab);
void set_symbol (symbol_table *p_symtab, char sym, int value);
int get_symbol (symbol_table symtab, char sym);
#endif
There are a number of other problems with your code, not least that you are passing the entire symbol table by value into get_symbol. How much of the code you're showing did you write, and how much is boiler-plate code you're supposed to leave as-is?
Here is an implementation of a symbol table where the symbols are single character and the values are just ints, as with your code. But this supports more than 3 symbols.
// symbol_table.h
struct symbol_table;
struct symbol_table* init_symbol_table(void);
void destroy_symbol_table(struct symbol_table *p_symtab);
void set_symbol (symbol_table *p_symtab, char sym, int value);
int get_symbol (const symbol_table *symtab, char sym);
// symbol_table.c
#include <limits.h>
#include <stdlib.h>
#define ARRAYSIZE(a) (sizeof(a)/sizeof((a)[0]))
struct symbol_table
{
// On rare systems, UCHAR_MAX == SIZE_MAX, and this array size will not work.
// Most people will never write code for such a system though. We'll ignore them.
int values[UCHAR_MAX+1];
};
struct symbol_table* init_symbol_table (void)
{
struct symbol_table *p = malloc(sizeof(struct symbol_table));
if (p)
{
size_t i;
for (i=0; i<ARRAYSIZE(p->values); ++i)
p->values[i] = 0;
}
return p;
}
void destroy_symbol_table(struct symbol_table *p)
{
free(p);
}
void set_symbol (symbol_table *p, char sym, int value)
{
p->values[(unsigned char)sym] = value;
}
int get_symbol (const symbol_table *p, char sym)
{
return p->values[(unsigned char)sym];
}
If you need to keep the function interface identical (complete with the rather bizarre definition of symbol_table) then you can just implement get_symbol and set_symbol with some simple conditional statements: either a sequence of if statements or a switch statement.
If you're having difficulty with that then go re-read the parts of your course materials which deal with character types and if. If your course materials don't cover that, then you should find some other resources for learning the C language; try starting with the items mentioned at Great C tutorial?
Yes, I could write the get_symbol and set_symbol code for you but I believe the help you're looking for is more around figuring out how to get started with the problem rather than a getting a finished result without understanding.
The key thing I believe you need to achieve is to get a detailed understanding of what specific actions the computer needs to take to return the value of one of the symbols. Start by stating that, as precisely as you can, in any notation at all (a diagram, or in English, whatever). Then try to implement that understanding in the C language.
This process of first understanding the mechanism by which you will solve the problem - that is, what specifically you want to make the computer do - is totally central to the process of learning to program. That learning experience is the thing this kind of homework is intended to provide, I guess. But nobody can do it for you. Showing you completed code might not help, because it won't push into your head the "Aha!" insight.
If you're really, totally, stuck, start with this implementation:
void set_symbol(symbol_table *p_symtab, char sym, int value)
{
/* WRITE CODE FOR THIS LATER */
}
int get_symbol (symbol_table symtab, char sym)
{
return 0;
}
It clearly does the wrong thing, but it will compile. Then work on it by modifying it to return a fixed value for A, for B, and for C. Then refer to your learning materials about how to access the members of a structure. Change the code to always return the value of the a member. Then try to figure out how to distinguish between the cases where the caller wants to fetch the value of A or B or C. You might find it helpful to 'artifically' set the members a b and c of the symbol table to some characteristic value to make sure you're returning the correct one (but remember to remove that code later).
Once you have done that, start working on implementing set_symbol. By the time you have made get_symbol work, set_symbol should be easy.

Examine C structure in Visual C

I'm using a structure within a structure like this in VS2010 (simplified:)
struct s_ptx
{
char xyz[33];
int newCount;
} ptx;
struct s_stream
{
struct ptx[20];
int count;
} Stream[20];
Everything is hunky dory until I try to examine this structure in the debugger:
eg, if I try to "watch" Stream[0].ptx[3].xyz, it gives some cryptic message ("CXX0058 Error: overloaded operator not found.")
I did a lot of searching on the Web, and found this is not an uncommon problem, and that
the only way to examine these sorts of structures is through adding a complex bit of
code to the autoexp.dat file.
It would be one thing if it were C code that the autoexp.dat file required but, alas, it is something else, and it would be very time-consuming to learn this new language just to do what I want to do.
So, my question:
does anyone know of a way to examine these sorts of structs in the VS debugger natively
does anyone know of some code that I could copy into my autoexp.dat to do the job
is anyone interested in writing this code as a service to me and all of mankind?
struct s_stream
{
struct ptx[20]; // **what is this ???**
int count;
} Stream[20];
i think 2nd structure should be like this
struct s_stream
{
struct s_ptx temp[20];
int count;
} Stream[20];
this code workd fine in my gcc
#include <stdio.h>
struct s_ptx
{
char xyz[33];
int newCount;
} ptx;
struct s_stream
{
struct s_ptx temp[20];
int count;
} Stream[20];
main()
{
printf("this works fine %s",Stream[0].temp[3].xyz);
}

Resources