Structures used to store postal codes - c

It asks me to create a hash function that turns the postal code into an integer by summing its characters. This is my code. I haven't got to the hash function yet.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct PostalCode
{
int size;
char *array[6];
} PostalCode;
int main()
{
int size = 6, i;
PostalCode *h = malloc(sizeof(PostalCode));
h->size = size;
h->array = malloc(sizeof(char)*size);
printf("Please enter your postal code: \n");
for (i=0; i<6; i++)
scanf(" %c", &(h->array[i]));
}
And the errors I get now are: postalcode.c:9:11: error: assignment to expression with array type
h->array = malloc(sizeof(char)*size);

The line
char *array[6]
declares an array of 6 pointers to char, and that's not what you want here. You can just make it
char * array
and resolve the error that way, or follow chux's advice, i.e. have
char array[6]
in which case you don't need the line that's causing the error, just remove it. No need to dynamically allocate the array.
A few other suggestions:
If your postal code is always 6 characters, then you don't really
need the PostalCode structure, unless you plan on keeping some other
information about the postal code there. You could just do
typedef char PostalCode[6];
Of course, if you expect postal codes to have
variable length, then size might help.
Regardless of whether you want a struct or typedef a char array, hard-coding the value 6 is a bad idea. If it's always 6 characters, then you can #define it; or if you keep the size in the structure, then make sure you initialize it and use the struct member instead of the literal number 6.
There is no need to dynamically allocate memory here, but if you do make sure you free it.
Good luck!

Related

expression must have pointer to object type with structs

* I find my mistake. c was already an int in this program . It was a big program(for me) and I had 20 variables and got confused. thank you. by the way, this option for copying a struct worked for me in the end.
I am trying to copy a structure, and it tells me that i need to put a pointer I think.
I like to mention that I didnt use pointers in all my program.
I've done a code of a game. it's a 500 hundred code and ran smoothly, until I tried to copy a structure.
I equaled it with a lot of people that did similar to me, and they don't have my problem. I also searched in all of the web.
It writed to me two types of errors that I will add below.
thank you!
#include <stdio.h>
#include <string.h>
typedef struct player {
char name[ARR_SIZE]; // player's name, up to 20 chars
int age; // player's age, 0 - 120
int defense; // defense power, 1 - 100
int attack; // attack power, 1 - 100
}player;
typedef struct team {
char name[ARR_SIZE]; // team's name
int numberOfPlayers; // number of players in the team, up to MAX_PLAYERS
player teamPlayers[MAX_PLAYERS]; // array of the team players
int points; // the team points in the league
int wins; // number of wins
int draws; // number of draws
int losses; // number of losses
}team;
team b[MAX_TEAMS_NUMBER];
team c[MAX_TEAMS_NUMBER]; (1)
** the part of the code itself**
int main ()
{
for (int i = 0; i < number_of_teams; i++)
{
c[i] = b[i]; (2)
}
}
I denoted numbers near the problematic lines
(1)'c': 'team[10]' differs in levels of indirection from 'int'
(2) Expression must have a pointer to object type
In C, the code order is very important. Here, you first try to create an array of "teams", then you tell the compiler what a "team" is. As it will read your code line by line, it doesn't know what a team is when reading your 2 first lines.
You must move the 2 first lines after your structures.
Keep in mind this problem can also occur with functions : if you use a function BEFORE its declaration, the compiler will detect an error. (declaration isn't implementation, you can implement a function at the bottom of your code but you need to declare it using a prototype.)

I cannot read a structure in another one in c language

I am trying to read a structure which contains another structure and then write it in a binary file. However, when i check if the structure was well read from the keyboard, the structure FIRMA is not read correctly. The value of 'nrang' is always 0 and the 'localitate' string is something very odd.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char localitate[10];
int nrang;
} FIRMA;
typedef struct
{
char nume[20];
int varsta;
FIRMA firma;
} ANG;
int main()
{
FILE* f;
ANG* a;
int n,i;
if ((f=fopen("fis.txt","wb"))==NULL) exit(1);
printf("number?\n");
scanf("%d",&n);
a=(ANG*)malloc(n*sizeof(ANG*));
printf ("Dati valorile");
for (i=0; i<n; i++)
{
scanf("%s%d",&a[i].nume,&a[i].varsta);
scanf("%s",&a[i].firma.localitate);
scanf("%d",&a[i].firma.nrang);
fwrite(&a[i],sizeof(a[0]),1,f);
printf("%s\n%d\n%s\n%d\n",a[i].nume,a[i].varsta,a[i].firma.localitate,a[i].firma.nrang);
}
}
Note that sizeof(ANG*) is not the same as sizeof(ANG) (the former is the size of the pointer -- probably 8 -- whereas the latter is the size of the structure -- probably 40), which means you're only allocating about 1/5 of the memory you intend to. As a result, the later code winds up writing and reading past the end of what's been allocated, which has undefined behavior.
One practice that helps people with this is to get into the habit of using sizeof(*ptr) when allocating for a pointer ptr, which will always give you the size of what it points to so you don't have to think of "do I need sizeof(ANG) or sizeof(ANG*) here?". This is particularly useful when allocating multi-dimensional arrays (e.g. int ***three_d_array = malloc(n * sizeof(*three_d_array))).

issue when ordering an array of structs in C

I want to order an array of structs by the first letter of a studentĀ“s name. The code that I made so far is the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int cod;
char* name;
int mark;
}student;
void print(student* class){
int i;
for (i=0;i<4;i++){
printf("%d\n",class[i].cod);
printf("%s\n",class[i].name);
printf("%d\n",class[i].mark);
printf("\n");
}
}
int main(int argc, char *argv[])
{
int ind,i;
int cod=1000;
student class[4];
student temp;
int lengthData=10;
for (i=0;i<4;i++)
{
class[i].name=malloc(sizeof(char)*lengthData);
}
class[0].cod=cod;
class[0].name="Joseph";
class[0].mark=15;
cod++;
class[1].cod=cod;
class[1].name="Jonathan";
class[1].mark=16;
cod++;
class[2].cod=cod;
class[2].name="Karen";
class[2].mark=17;
cod++;
class[3].cod=cod;
class[3].name="Anna";
class[3].mark=20;
print(class);
for (ind=1;ind<4;ind++){
temp=class[ind];
i=ind-1;
while (i>=0){
if (temp.name[0]<class[i].name[0]){
class[i+1]=class[i];
class[i]=temp;
i--;
}
else break;
}
}
printf("ordered data\n");
print(class);
system("PAUSE");
return 0;
}
I am using DevC++ and when I run it the program hangs, but when I add the following lines before the loop for the bubble sort (only for testing):
class[3]=class[2];
printf("%s\n",class[3].name);
for (ind=1;ind<4;ind++){
...
The program works even though one record (3) has been replaced by the data of record (2).
Any help?
You have quite a few problems:
First of all you leak memory, since you allocate memory and make name point to that, then you make name point somewhere else. You need to copyinto the memory you allocate.
Secondly, also with the name member, once you copy into the memory, you will go out of bounds since you only allocate five bytes for each string, but you have strings of up to at least nine characters (ten with the terminator).
Thirdly, and more about going out of bounds, your class array only have three elements, yet you access four elements of the array.
The reassignment of the name pointer won't cause more problems than a temporary memory leak, since you don't attempt to pass the pointer to free. The second problem isn't really an issue because you don't copy the strings yet. The third problem on the other hand, that will lead to undefined behavior as soon as you execute that code.

Why will this not print?

Before you feel the need to mark this as a duplicate post, please don't. I have read all the threads on pointers, arrays, and functions I could find but almost all of them are far too advanced to be of any help to me.
I'm not getting an error, however my code will not print my array. It seems the issue here is using scanf. I don't think the values entered are actually being put into the array in main(). I've tried using pointers, but then I get the error "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" whenever I try to use scanf to collect user inputted values to put into the array.
What I am working on is limited to declaring my array in the main() function, but all the operations are to be performed in promptData() function. Any help would be great, I'm at my wits end trying to figure this out on my own.
#import <stdio.h>
void promptData(double data[], int numElem);
int main(int argc, const char * argv[])
{
int size, i;
double array[size];
promptData(array, size);
for (i = 0; i < size; i++)
printf("%.2lf\n", array[i]);
return 0;
}
void promptData(double data[], int numElem)
{
int i;
printf("Enter integer values for size of array.\n");
scanf("%i", &numElem);
for (i = 0; i < numElem; i++)
{
printf("Enter array values.\n");
scanf("%lf", &data[i]);
}
}
Your program has undefined behaviour because variable size was not initialized and has indeterminate value.
You should at first in main ask the user to enter the size of the array then define the array itself and only after that fill it with values.
For example
int main(int argc, const char * argv[])
{
int size = 0;
printf( "Enter a positive integer value for the size of the array: ");
scanf( "%i", &size);
if ( size == 0 ) exit( 1 );
double array[size];
promptData(array, size);
//...
Also in C there is no such a directive as
#import <stdio.h>
Use instead
#include <stdio.h>
At least in ANSI C 89 and C 90, you can't give a variable as the size of an array. The size of array should be known at compile time. You should be doing something like double array[size];.
Even in C99, where you can have variable sized arrays; the variables should contain proper index values at the time you declare the array. In that case, you should read the number from stdin and then declare the array.
Also in C, all parameters are passed by value. This means every function takes a copy of the parameters in the function. If you want to modify a variable's value, you should pass a pointer to it, and then modify the pointer's dereferenced value, something like:
void change(int *x)
{
*x = 7;
}
void first(void)
{
int x = 5;
change(&x);
printf("%d\n", x);
}
Adding on to the other, correct, answer by Zenith, if you want a dynamically allocated array (like you want to be able to change its size based on user input), then your only option is to use one of the memory allocation functions like malloc().
Once you actually have the size in your main function, declare your array like this:
int *myArray = malloc(sizeof(int) * size));//note that malloc will return a NULL if it fails
//you should always check
if(myArray != null) {
//do stuff with myArray like you were. You can just use myArray[] as long as you
//make SURE that you don't go beyond 'size'
}
free(myArray);
//VERY important that every malloc() has a free() with it
Note: untested, but the idea is there.
Further, to answer your other question.
If you find yourself in a situation where you need to call a function and use things INSIDE that function to change stuff where you called it, you have only two choices in C.
You can either return the value and assign it to a variable in the calling function like this:
int result = myFunction(someVariable, anotherVariable);
//do stuff with result
Or, use pointers.
I'm not explaining pointers here, that's usually several lectures worth of information, and is one of the more difficult concepts to grasp for introductory programmers. All I can tell you is you need to learn them, but this format is not the right way to go about doing that.
You're passing size to promptData as a copy.
Thus changes to numElem inside promptData will not affect the size variable in your main. Hence size remains uninitialized, i.e. has an undefined value and therefore should not be used as a size for an array.
If you need to initialize an array with a size that's only known at run-time, you need to allocate memory for the array dynamically using malloc, for example:
double* array = malloc(size * sizeof(double));

Trouble storing a struct in an array

I want to create a database sort of, that stores a list of 5000 names and 5000 coresponding salaries into an array, I simply can't find the problem since the console either crashes or the compiler gives me the following error: "cannot convert 'char* ()[30]' to 'char' for argument '1' to 'char*' fgets(char*,int,*FILE)".
EDIT: I changed whatever I could figure out in the code, and I seem to have an issue with
this line in particular:
person* TAB = calloc(N, sizeof(struct));
I can't spot other errors(lack of experience), and I don't know exactly what to use instead of fgets to put in a line.
#include <stdio.h>
#include <stdlib.h>
#define N 5000
typedef struct {
char name[30]
int salary;
} person;
int main()
{
person* TAB = calloc(N, sizeof(struct));
FILE * input;
input = fopen("in.txt","r+");
int nr=0;
int r;
while(nr<5000)
{
fscanf(input,"%s",TAB[nr].name);
fscanf(input,"%d",TAB[nr].salary);
nr++;
}
printf("%s %d",TAB[1].name,TAB[1].salary);
fclose(input);
return 0;
}
You really should avoid putting that much data on the stack, which is what a normal variable like that will generally do. It will occupy around 5000 * (30 + 4 * 5000) = 95 MB of stack space, which might be more than your operating system feels is reasonable.
Anyway, the fix is not to allocate this on the heap; the fix is to change the declaration. I believe there's a logic error, since you allocate space for 5000 salaries per person, which is probably not what you meant.
Also, the name field should be an array of characters, but you've declared it as an array of character pointers, which is what the warnings are all about.
I believe you should have:
struct person
{
char name[30];
int salary;
};
This will drop the memory usage for struct person TAB[N]; down to around 5000 * (30 + 4) or around 166 KB which is way more reasonable. This assumes a 4-byte int which is a pretty common situation.
Finally, your file reading code is not very nicely designed, it will probably not work.
Look into using fgets() to read lines, stopping when it fails (i.e. never calling feof()), and then parsing/tokenizing each line as read. Remember that names can contain whitespace, which will make %s in sscanf() stop.
The name struct member should not be declared as 30 char pointers and the salary is one per name so it should look something like this
typedef struct {
char name[30]
int salary;
} person;
Now in order to have it as an array you are best off allocating on the heap
person* persons = calloc(N, sizeof(struct));
Now you can access the name and salary of one person
persons[3].name
persons[3].salary
...
fgets(persons[nr].name,30,input); // although you may want to remove \n
struct person
{
char* name[30];
I think you mean char name[30]. That is if you want one name of at most 29 bytes.
Later on you do:
fgets(&TAB[nr].name,30,input);
Why are you taking the address? If you make the change above, the TAB[nr].name should be of type char[30], which should degenerate into a char* as desired.

Resources