I'm having problems inputting values into this structure template, please help.
I've got to use char* for those attributes. so it doesn't give an error while inputting data but crashes when its time to display.
#include<stdio.h>
#include<malloc.h>
#include<conio.h>
struct Date
{
int day;
char *month;
int year;
}date;
struct sports_team
{
char *name;
char *city;
int no_of_players;
struct Date creation_date;
};
void main()
{
struct sports_team *my_team;
my_team = (struct sports_team*)malloc(sizeof(struct sports_team)*2);
printf("fill information for teams:\n");
for(int i=0;i<2;i++)
{
printf("\nenter team name:");
scanf("%s",&my_team[i].name);
printf("\nenter team city:");
scanf("%s",&my_team[i].city);
printf("\nenter no. of players:");
scanf("%d",&my_team[i].no_of_players);
printf("\nenter creation day:");
scanf("%d",&(my_team[i].creation_date.day));
printf("\nenter creation month:");
scanf("%s",&(my_team[i].creation_date.month));
printf("\nenter creation year:");
scanf("%d",&(my_team[i].creation_date.year));
printf("\n\n");
}
printf("\n information for teams:\n");
for(int i=0;i<2;i++)
{
printf("%s ",my_team[i].name);
printf("%s ",my_team[i].city);
printf("%d ",my_team[i].no_of_players);
printf("%d ",my_team[i].creation_date.day);
printf("%s ",my_team[i].creation_date.month);
printf("%d ",my_team[i].creation_date.year);
printf("\n\n");
}
free(my_team);
}
you're allocating the structures all right but you're forgetting to allocate memory for char * members: you're writing into uninitialized memory when doing scanf (not to mention that you're passing the address of the pointer, not the pointer itself: don't use & when scanning strings).
For simplicity's sake, you could just put fixed buffer lengths in your structures:
struct Date
{
int day;
char month[20];
int year;
}date;
struct sports_team
{
char name[100];
char city[100];
int no_of_players;
struct Date creation_date;
};
and limit size when scanning (don't use & when scanning strings BTW)
scanf("%99s",my_team[i].name);
scanf("%99s",my_team[i].city);
scanf("%19s",my_team[i].creation_date.month);
Use getchar() instead of scanf().
Related
When I run the program and give values to the id, name, surname it gives them all the value of the last student. For instance if the last students name is Anna then all the other names of the array are Anna. With the grades it works well! I tried and without the 'constructor' function and happenden the same thing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Student{ /*struct for student info*/
char *id;
char *name;
char *surname;
int grade;
};
struct Student* Student_new(char* id, char* name, char* surname, int grade);
/*fuction: Student 'constructor'*/
int main(int argc, char *argv[]) {
int no; /*number of students*/
printf("Welcome! \n\nNumber of students: ");
scanf("%d", &no);
struct Student *studentArray[no]; /*arary of struct students*/
int i; /*counter*/
for(i=0; i<no; i++){
char id[10], name[10], surname[10];
int grade;
printf("\n\nStudent(%d)\n", i+1);
printf("id: ");
scanf("%s", id);
printf("name: ");
scanf("%s", name);
printf("surname: ");
scanf("%s", surname);
printf("grade: ");
scanf("%d", &grade);
studentArray[i] = Student_new(id, name, surname, grade); /*using Student
'constructor' to initialize the array*/
}
for(i=0; i<no; i++){
printf("%s %s %s %d \n", studentArray[i]->id, studentArray[i]-
>name, studentArray[i]->surname, studentArray[i]->grade);
}
return 0;
}
struct Student* Student_new(char* id, char* name, char* surname, int grade)
{
struct Student* st = malloc(sizeof(struct Student));
st->id = id;
st->name = name;
st->surname = surname;
st->grade = grade;
return st;
}
PLEASE HELP!!
The issue is that the loop variables go out of scope after each iteration, and you're left with dangling pointers in the Student instances. What you're seeing is the result of undefined behavior.
What's probably happening is that the same char array is being passed into every student instance. Then you modify the same char array, overwriting the previous values.
You'll need to make copies of the strings. Remember to create a function like Student_free where you free the dynamically allocated copies.
struct Student* Student_new(char* id, char* name, char* surname, int grade)
{
struct Student* st = malloc(sizeof(struct Student));
st->id = strndup(id, 10);
st->name = strndup(name, 10);
st->surname = strndup(surname, 10);
st->grade = grade;
return st;
}
You should reserve memory for the string attributes. As a hint, use a struct similar to:
#define MAX_LEN 32
struct Student{ /*struct for student info*/
char id[MAX_LEN];
char name[MAX_LEN];
char surname[MAX_LEN];
int grade;
};
Define MAX_LEN to something that is reasonable for you, and check that the entered values aren't any longer. Also make sure to strcpy the input values to the struct variables.
The student structure only holds pointers to char arrays.
Now the actual space in memory for the strings is allocated in your for cycle an its lifetime is limited by the scope of the for cycle, accessing it afterwards is undefined behaviour. In your case the space where the strings are has not been reused and overridden yet, so coincidentally you are able to get the last value stored (cases like this can also raise segmentation fault).
You should have a look on some basic tutorial about pointers and c memory model. Allocating the arrays in the struct is a good solution (nucleon's answer). Also the scanf function can overflow you should limit the number of retrieved characters to match the size of allocated array.
I created a struct Book with the properties.I let the user to create the structure objects with for-loop.Like Books[i] Books1, Books2 etc...
The problem is that i cant store integer values in the structure.
The code is given below.
#include <stdlib.h>
#include <stdio.h>
struct Book {
int ID[];
char book_name[80];
char author_name[50];
int pblsh_date[];
};
struct Book *Books;
void Create();
int main() {
int count;
printf("How many books do you want to enter? ");
scanf("%d", &count);
Create(count);
//Show
printf("ID\t\tName\tAuthor\tPublish Year\n");
for (int i= 0; i < count; i++)
printf("%d\t%s\t%s\t%d\n", Books[i].ID, Books[i].book_name, Books[i].author_name, Books[i].pblsh_date);
if (Books) {
free(Books);
}
getchar();
return 0;
}
void Create(int count) {
Books = (struct Book*) malloc(count * sizeof(struct Book));
int i;
for (i = 0; i < count; i++) {
printf("%d. Book's ID: ", i+1);
scanf("%d", Books[i].ID);
printf("Book's name: ");
scanf("%s", Books[i].book_name);
printf("Author: ");
scanf("%s", Books[i].author_name);
printf("Publish Year: ");
scanf("%d", Books[i].pblsh_date);
}
}
The definition of the structure that you posted contains two empty arrays: int ID[]; and int pblsh_date[];. Since you did not specify a size and the compiler is not throwing an error, it is not allocating any storage for the array data: the arrays are zero-length and you are overwriting the data that follows them when you scanf into them.
Since you only want a single integer, the correct way to define the structure is
struct Book {
int ID;
char book_name[80];
char author_name[50];
int pblsh_date;
};
The only other change you need to make to your program is the arguments to scanf: scanf("%d", &(Books[i].ID)); and scanf("%d", &(Books[i].pblsh_date));. The reason is that scanf requires the address of the place you want to put the result. While scanf("%s", Books[i].book_name); works as is, you need to add the & operator to int variables. book_name is an array, which in C is treated as a pointer containing the address of the buffer you want to write to. ID is an int, so you need to get its address to know where to write to. Notice how you already did this in main with scanf("%d", &count);.
I have the following code. In the struct definition, I try to ask user to enter employee's first and last name. But when I run this exe, it exit after the title is entered. Any suggestions?
#include<stdio.h>
#include<string.h>
#define NUMEMPS 10
struct Employee {
char *firstname;
char *lastname;
char *title;
int salary;
};
int main()
{
struct Employee* stuff = malloc(NUMEMPS* sizeof *stuff);
int n,i;
for (n=0; n<NUMEMPS;n++)
{
printf("Please enter number %d Employee's Last name:", n);
fflush(stdout);
gets(stuff[n].lastname);
if (strlen(stuff[n].lastname) == 0)
break;
printf("Please enter number %d Employee's first name:", n);
fflush(stdout);
gets(stuff[n].firstname);
printf("Please enter number %d Employee's title:", n);
fflush(stdout);
gets(stuff[n].title);
printf("Please enter number %d Employee's salary:", n);
fflush(stdout);
scanf("%d", &stuff[n].salary);
getchar();
}
for (i = 0;i<n;i++)
{
printf("{%s,%s,%s,%d}\n",
stuff[i].lastname,
stuff[i].firstname,
stuff[i].title,
stuff[i].salary);
}
return 0;
}
The three char* members of the structure are pointers, so no space is allocated to hold any data.
With the current struct you'd have to do three more allocs for the data:
struct Employee* stuff = malloc(NUMEMPS* sizeof *stuff);
stuff->firstname = malloc(101);
stuff->lastname = malloc(101);
stuff->title = malloc(101);
What you probably want is something like:
struct Employee {
char firstname[101];
char lastname[101];
char title[101];
int salary;
};
Also, though as an aside, you must check your malloc calls for a NULL return.
This code:
struct Employee {
char *firstname;
char *lastname;
char *title;
int salary;
};
...
struct Employee* stuff = malloc(NUMEMPS* sizeof *stuff);
only allocates enough room to store a single struct Employee, that is: three pointers and an integer. There's no storage for the character strings pointed to.
Instead, consider malloc()ing each of the constituent character data and assigning to stuff->firstname (et al), or modify the declaration of struct Employee to include character arrays.
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
struct student
{
char name[30];
int roll_no;
char add[40];
char subject[15];
}
struct student p;
printf("Enter the name of student:\t");
scanf("%s",p.name);
printf("Enter the roll no. of student:\t");
scanf("%d",&p.roll_no);
printf("Enter the address of student:\t");
scanf("%s",p.add);
printf("Enter student's subject:\t");
scanf("%s",p.subject);
printf("\nThus the name of student is:%s \nHis/her roll no is :%d \n He/she lives at:%s \t and his subject is:%s",p.name,p.roll_no,p.add,p.subject);
getch();
}
The error message is---
13error: two or more data types in declaration of `p'
i am using code blocks
Put a ; after the structure definition...
Right after scanning the second element, the program crashes. It is not able to go to the scanning of the third element(i.e. grade). Need help, in figuring out what I am wrong wrong.
#include<stdio.h>
#include<stdlib.h>
#define NUM 2
typedef struct STUDENT
{
int ID;
char *name;
char *grade;
};
int main ()
{
int i;
struct STUDENT *s;
s = (struct STUDENT*)malloc(NUM*sizeof(struct STUDENT*));
printf("Enter Student's ID, Name and Grade:\n");
for(i=0;i<NUM;i++)
{
printf("Enter ID:\n");
scanf("%d", &(s+i)->ID);
printf("Enter Student Name:\n");
scanf("%s", (s+i)->name);
printf("Enter Grade:\n");
scanf("%s", (s+i)->grade);
printf("\n");
}
printf("\nInformation of the student's are:\n");
for(i=0;i<NUM;i++)
{
printf("Student ID = %d\n", (s+i)->ID);
printf("Student Name = %s\n", &(s+i)->name);
printf("Student grade = %c\n", &(s+i)->grade);
printf("\n");
}
return 0;
}
You do not allocate memory for grade and name in struct STUDENT. Trying to read input and write it to them produces undefined behavior.
Add the necessary mallocs, for example with a given maximum length STR_MAX:
s[i].name = malloc(STR_MAX);
s[i].grade = malloc(STR_MAX);
See the other answers for further errors.
malloc(NUM*sizeof(struct STUDENT*));
should be
malloc(NUM*sizeof(struct STUDENT));
also, the name and grade are not buffers but pointers. You may need a buffer (char array) or allocate memory for it dynamically.
typedef struct STUDENT
{
int ID;
char *name;
char *grade;
};
Here name and grade character type pointer. so when you malloc structure you also have to malloc name and grade too
struct STUDENT *s; should be declared like this:
STUDENT *s;
No need to cast void * from malloc. Change this line s = (struct STUDENT*)malloc(NUM*sizeof(struct STUDENT*)); to this:
s = malloc(NUM * sizeof(*s));
Instead of this scanf("%d", &(s+i)->ID);, the following may be easier to understand:
scanf("%d", &s[i].ID);
Same here:
printf("Student ID = %d\n", s[i].ID);
Most importantly, what Nabla said.