How to accept character array input into a structure in C? - c

I've got this structure, a simple one that holds student name and marks. When I'm trying to read user input into the name(char array), I get a warning indicating something on the lines of :
format %s expects char *, but has char*[20]
I know this is because char arrays cannot be assigned in C, so strcpy has to be used. This question on SO has a good reasoning. However,how do I fix the warning in my program? Don't think I can use strcpy here.
#include <stdio.h>
typedef struct _student
{
char name[20];
unsigned int marks;
} student;
void read_list(student list[], int SIZE);
void print_list(student list[], int SIZE);
int main()
{
const int SIZE=3;
student list[SIZE];
//function to enter student info.
read_list(list, SIZE);
//function to print student info
print_list(list, SIZE);
return 0;
}
void read_list(student list[], int SIZE)
{
int i;
char nm[20];
for (i=0;i<SIZE;i++)
{
printf("\n Please enter name for student %d\n", i);
scanf("%s",&list[i].name);
printf("\n Please enter marks for student %d\n", i);
scanf("%u", &list[i].marks);
}
}
void print_list(student list[], int SIZE)
{
int i;
printf("\t STUDENT NAME STUDENT MARKS\t \n");
for(i=0;i<SIZE;i++)
{
printf("\t %s \t %u\n", list[i].name, list[i].marks);
}
}
The program does give a correct output, but the warning remains.

Try this code:
for (i=0;i<SIZE;i++)
{
printf("\n Please enter name for student %d\n", i);
scanf("%s",list[i].name);
printf("\n Please enter marks for student %d\n", i);
scanf("%u", &list[i].marks);
}
This is because & used in scanf statement is to get the address.
In your case you use array name i.e. name and array name itself is providing the address. Remember array name gives the base address of an array.

change scanf("%s",&list[i].name); to scanf("%s",list[i].name);. Delete &. Because basically array name represents base address. No need to mention address of array for scanning the string.

Remove the & in the scanf that scan in a string using %s to eliminate the warning. So change
scanf("%s",&list[i].name);
to
scanf("%s",list[i].name);
This is because the name of the char array decays to a pointer to its first element

line 33:
scanf("%s",&list[i].name);//wrong
scanf("%s",list[i].name);//right
The name of an array is synonym for the location of the initial element , thus in your code, variable 'name' is the address of name[0]. You don't need to use & on 'name' to get the address of the array.Just use 'name' itself.

Related

taking input using gets with arrow operator not working? What's the Error?

What's the Error in this ?
I tried taking input using arrow operator.
#include <stdio.h>
typedef struct{
char name[100];
int salary;
}emp;
void inp(emp *e){
printf("enter name : ");
gets(e->name);
printf("enter salary : ");
scanf("%d", e->salary);
}
int main() {
emp *e1,*e2;
inp(e1);
inp(e2);
printf("%s , %d\n", e1->name,e1->salary);
printf("%s , %d\n", e2->name,e2->salary);
return 0;
}
I tried putting & and even giving inp function as emp but it doesn't work.
It just asking me 1st employee name. dat's it!
Not even printing Enter salary.
What changes should I make?
Your struc have been created wrong. So i changed your code like this to make it clear. I also did use getchar() function so you can call fget() function multiplie times. I guess it does work like you wish.
#include <stdio.h>
struct Emp{
char name[100];
int salary;
};
void func(struct Emp *e){
printf("enter name : ");
fgets(e->name, sizeof(e->name), stdin);
printf("enter salary : ");
scanf("%d", &e->salary);
getchar();
}
int main() {
struct Emp e1,e2;
func(&e1);
func(&e2);
printf("\n%s , %d", e1.name,e1.salary);
printf("\n%s , %d", e2.name,e2.salary);
return 0;
}
emp *e1,*e2;
creates two pointers that point to nothing... They are just uninitialized pointers. They are not pointing to any valid memory. So when you dereference them using -> your program is likely to crash.
You need to allocate memory using, e.g. malloc
Like
e1 = malloc(sizeof *e1);
you should choose another better name for your function first, inp is already a function name in c, see this: https://cboard.cprogramming.com/c-programming/21255-ansi-c-function-inp-outp-inp-inpw.html

How to correctly pass structures to functions

So the question I'm working on has me creating a structure with 5 elements: id number, name, department, course, and year. I have to write a function that prints the names of people with certain years and a function that prints all data based on id number input.
When I type in 2020 as an input I get a segmentation fault. What could be causing this?
#include <stdio.h>
struct stud
{
int id;
char name[50];
char dep[50];
char course[50];
int year;
};
void printbyyear(struct stud *student,size_t sz, int a);
void printspecific(struct stud *b,size_t sz, int a);
int main()
{
int yr,num,b;
struct stud students[]={
{1,"Jon","math","calc",2019},
{2,"Tim","Language arts","calc",2020},
};
printf("Input year to search for:");
scanf("%d",&yr);
printbyyear(students, sizeof(students),yr);
printf("Input ID # to search for:");
scanf("%d",&num);
printspecific(students, sizeof(students),num);
return 0;
}
void printbyyear(struct stud *b,size_t sz, int a)
{
int i;
for(i=0;i<sz;i++)
{
if (b[i].year==a)
{
printf("%d %c %c %c %d",b[i].id,b[i].name,b[i].dep,b[i].course,b[i].year);
}
}
}
void printspecific(struct stud *b,size_t sz, int a)
{
printf("%d %c %c %c %d",b->id,b->name,b->dep,b->course,b->year);
return 0;
}```
There are many mistakes in your programs.
printbyyear(struct stud,yr);
that is not how you call a function with struct variable, change it as printbyyear(b1,yr); or printbyyear(b2,yr);
you are not using array of structs , so you don't need to use loops at all for your code.
if (b.year == a)
{
printf("%d %s %s %s %d",b.id,b.name,b.dep,b.course,b.year);
}
finally if you want to store multiple records, then use array of struct's like below.
struct stud students[]= {
{2,"Tim","Language arts","calc",2020},
{1,"Jon","math","calc",2019}
};
and call it as below ( sizeof(students)/sizeof(students[0]) ) gives the number of elements you have in your structure)
printbyyear(students, sizeof(students)/sizeof(students[0]), yr);
now you can use loops for printing because you passed an array
void printbyyear(struct stud *student, size_t sz, int y)
{
int i;
for(i=0;i<sz;i++)
{
if (student[i].year == y)
{
printf("%d %s %s %s %d",student[i].id,student[i].name,student[i].dep,student[i].course,student[i].year);
}
}
}
and you declaration of function should be as below
void printbyyear(struct stud *b,size_t size, int a);
I guess that here
if (b[i]stud.year==a)
You are trying to access b1, b2 and any other possible student. To do that you need an array of type struct stud
struct stud b[5];
Now your if condition makes sense. The function call should be:
printbyyear(b,yr);
And the declaration
void printbyyear(struct stud *b, int a)
Also since you initialize only two students, i.e. only two elements of your array, the for loop should be for(i=1;i<=2;i++) with a 2 not a 5.
Accessing uninitialised elements or accessing an array out of bounds will result in an undefined behaviour.
Correct is an ambiguous term, so I will just say this method is one that I prefer:
Passing the address of an object of significant size is advantageous in that the address of that object is going to be smaller than the object itself.
So given for example your struct (typedefed for readability) I would make the following modifications (i.e. to pass by reference to the address of the object.)
Read in-line comments and note corrections in code:
typedef struct
{
int id;
char name[50];
char dep[50];
char course[50];
int year;
}stud_s;
//modify to accept pointer, and add size of array argument
void printbyyear(stud_s *s, int yr, size_t size);
int main()
{
int yr,num;
stud_s b1[] = { {1,"Jon","math","calc",2019},
{2,"Tim","Language arts","calc",2020},
{3,"Jen","the arts","calc",2021},
{4,"Bob","painting arts","calc",2022},
{5,"jed","numeric arts","calc",2023}
};
size_t size = sizeof(b1)/sizeof(b1[0]);
printf("Input year to search for:");
scanf("%d",&yr);
printbyyear(b1,yr, size);// b1 is a pointer to array of struct here.
printf("Input ID # to search for:");
scanf("%d",&num);
return 0;
}
void printbyyear(stud_s *b, int a, size_t size)
{
int i=0;
//for(i=1;i<=5;i++)//results in out of bounds access to array
for(i=0;i<size;i++) //change magic number for actual size of array
{
if (b[i].year==a)
{
//fix format specifiers
printf("%d %s %s %s %d\n",b[i].id,b[i].name,b[i].dep,b[i].course,b[i].year);
//printf("%d %c %c %c %d",b[i].id,b[i].name,b[i].dep,b[i].course,b[i].year);
i++;
}
}
}

Stack crashed when pushed value to a struct

Hey guys im learning c and im currently working on stack, structure and pointer. Im using visual studio to do my the program and whenever i enter my input the program will crash. I'm able to scope down that the error is coming from the product name. I am also quite confused since it includes pointer character. Anyone can point out my mistakes? thank you
HERE ARE MY CODES
#include<stdio.h>
#include<string.h>
#define MAX 10
int top = -1;
struct Product {
int prodId;
char *prodName;
};
struct Product arrP[MAX];
struct Product pop();
void push(int id, char *name);
int isFull();
int isEmpty();
struct Product pop()
{
struct Product temp;
temp = arrP[top];
top--;
return temp;
}
void push(int id, char *name)
{
top++;
arrP[top].prodId = id;
strcpy(arrP[top].prodName,name);
}
int isFull()
{
if (top == MAX)
return 1;
else
return 0;
}
int isEmpty()
{
if (top == -1)
return 1;
else
return 0;
}
int main()
{
int myID;
char *myName;
//Push the value
printf("Enter the Product id: ");
scanf("%d", &myID);
printf("Enter the Product Name: ");
scanf("%s", &myName);
push(myID, &myName);
printf("%d %s", arrP[top].prodId ,arrP[top].prodName);
}
There are few simple bugs which you can avoid my listening to compiler warning while compiling with -Wall flag.
Case 1:- variable myId suppose to be a integer variable, not a pointer variable. If you want it to be pointer variable then you should allocate memory for it first.
int *myID;
printf("Enter the Product id: ");
scanf("%d", &myID);
Replace with
int myID;
printf("Enter the Product id: ");
scanf("%d", &myID);
Case 2:- variable myName supposed to be array of characters as you want to store product name into it.
char myName;
printf("Enter the Product Name: ");
scanf("%s", &myName);
Replace with
char myName[50];
printf("Enter the Product Name: ");
scanf("%s", myName);
While calling push() function just pass the myName. For e.g
push(myID, myName);
Also this statement
strcpy(arrP[top].prodName,name);
causes problem as prodName is pointer member in of structure, you should allocate memory dynamically for this and then do copy.
arrP[top].prodName = malloc(SIZE);
strcpy(arrP[top].prodName,name);
When you are getting the input using %s in character type variable, the memory adjacent to the address of the char variable gets overwritten thus can cause program crash. if you want to enter a string, you can try it by defining an array of characters (as char my name[MAX], MAX can be a size suitable to you).

Passing a structure to a function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So I am having a problem when compiling this program, I just can't get it to work, I mean if I put the inputstudent() code inside the main(), it is much easier but I have to place the code in a function, inputstudent() and call in from the main(). I know it sounds very easy but I can't get it.
#include <stdio.h>
#include <stdlib.h>
struct student
{
char surname[50];
int age;
char oname[50];
char address[50];
};
void displaystudent();
void inputstudent();
int main(){
struct student s;
inputstudent(s);
displaystudent(s);
return 0;
}
void inputstudent(struct student s){
printf("Enter the surname: ");
scanf("%s",s.surname);
printf("Enter the other name: ");
scanf("%s",s.oname);
printf("Enter the age: ");
scanf("%d",&s.age);
printf("Enter the address: ");
scanf("%s",s.address);
}
void displaystudent(struct student s)
{
printf("Surname: %s \n",s.surname);
printf("Oname: %s \n",s.oname);
printf("Age: %d \n",s.age);
printf("Address: %s",s.address);
}
In C parameters are passed by value, so any modifications made to a parameter inside the function will be local modifications.
Lets have a look at following code snippet which is basically a very simple version of what you're trying to do:
void GetNumber(int number)
{
printf("Type a number:\n");
scanf("%d", &number); // modifies the local variable `number`?
}
...
int n = 0;
GetNumber(n);
Now what is the value of n right after the call to GetNumber?
Well it's not the number the user has typed, but it's still 0, that is the value n contained prior to the call to GetNumber.
What you need is this:
void GetNumber(int *pnumber)
{
printf("Type a number:\n");
scanf("%d", pnumber); // modifies the value pointed by the pointer pnumber
}
...
int n = 0;
GetNumber(&n); // &n is the memory address of the variable n
You need to read the chapter dealing with pointers in your C textbook.
Other less important problem
Your prototypes
void displaystudent();
void inputstudent();
don't match the corresponding functions.
You are passing your struct by value, that's why the function is not modifying it. You should change your function that is intended to modify the struct to take a struct pointer as argument:
#include <stdio.h>
#include <stdlib.h>
struct student {
char surname[50];
int age;
char oname[50];
char address[50];
};
void displaystudent(struct student s);
void inputstudent(struct student *s);
int main() {
struct student s;
inputstudent(&s);
displaystudent(s);
return 0;
}
void inputstudent(struct student *s) {
printf("Enter the surname: ");
scanf("%s", s->surname);
printf("Enter the other name: ");
scanf("%s", s->oname);
printf("Enter the age: ");
scanf("%d", &s->age);
printf("Enter the address: ");
scanf("%s", s->address);
}
void displaystudent(struct student s) {
printf("Surname: %s \n", s.surname);
printf("Oname: %s \n", s.oname);
printf("Age: %d \n", s.age);
printf("Address: %s", s.address);
}
As mentioned by Michael Walz, use pointers in order to modify structure in function calls. Moreover your function signature and definition does not match that's why compiler is complaining:
#include <stdio.h>
#include <stdlib.h>
struct student {
char surname[50];
int age;
char oname[50];
char address[50];
};
void displaystudent(struct student* pStudent);
void inputstudent(struct student* pStudent);
int main() {
struct student aStudent;
inputstudent(&aStudent);
displaystudent(&aStudent);
return 0;
}
void inputstudent(struct student* pStudent){
printf("Enter the surname: ");
scanf("%s", pStudent->surname);
printf("Enter the other name: ");
scanf("%s", pStudent->oname);
printf("Enter the age: ");
scanf("%d", &pStudent->age);
printf("Enter the address: ");
scanf("%s", pStudent->address);
}
void displaystudent(struct student* pStudent)
{
printf("Surname: %s \n", pStudent->surname);
printf("Oname: %s \n", pStudent->oname);
printf("Age: %d \n", pStudent->age);
printf("Address: %s", pStudent->address);
}
You seem to want the changes that you make to the structure variable s inside inputstudent() to be reflected back to the original variable. In that case you need to pass the address of the variable to the function instead of its value.
If you pass the value of s to the function instead of its address, a new copy of s would be made inside inputstudent() and the values would be read into this copy while the s in main() remains unchanged.
To solve this you give inputstudent() a pointer to the s in main() and make inputstudent() use this address while reading the data. In this way the changes made for the variable in inputstudent() will be reflected back to the s in main().
Call the function like
inputstudent(&s);
And to access members of a structure variable using a pointer to it, you use the -> operator instead of the . operator.
void inputstudent(struct student *s){
printf("Enter the surname: ");
scanf("%s",s->surname);
printf("Enter the other name: ");
scanf("%s",s->oname);
printf("Enter the age: ");
scanf("%d",&s->age);
printf("Enter the address: ");
scanf("%s",s->address);
}
Also, an address possibly involves white spaces in which scanf() won't do. You could use fgets() for that.
There are basically two causes for your problem.
Function declarations don't have any parameters.
The structure is passed by value instead of reference to inputstudent function.
You can solve both of them by changing the function prototypes in both declaration and definition to
void displaystudent(struct student s);
void inputstudent(struct student &s);
You can't use struct student s as parameter in inputstudent(). It is just a value copy.
You should use pointer as parameter.
As:
void inputstudent(struct student* s)
{...}
int main(){
struct student s;
inputstudent(&s);
displaystudent(s);
return 0;
}

Pointer to an array of structures

I'm currently trying to write a program for a student database assignment. After manually setting 3 elements of the structure array, the next 3 students' details are inputted by the user.
I am trying to write a function that finds the oldest age of the 6 students and returns it as a student_t entry at index max. I'm struggling with how to actually give the function the pointer that is pointing to the first element of the array stdt[6] and then using the pointer within the function. I also have no idea how I would go about returning to main the entry that has the highest age. If I'm trying to say that the value of an element of array of structures is equal to some other integer (max), doesn't that mean that max is now some other block of memory with an integer value and not linked to the array? So I'm not sure how I would return the entry that has the highest age after the function determines the max age.
This is all I've written so far:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char *name;
char *surname;
char *UUN;
char *department;
char gender;
int age;
}student_t;
student_t findOldest(student_t *studentarr, int len){
int i;
int x;
int max;
max=0;
for(i=0;i<len;i++){
(p+i).age=x;
if(x>max){
x=max;
}
}
}
int main() {
int i;
student_t stdt[6]={{"John","Bishop","s1234","Inf",'m',18},{"Lady","Cook","s2345","Eng",'f',21},{"James","Jackson","s33456","Eng",'m',17}};
student_t *p=&stdt[0];
for(i=3;i<6;i++) {
printf("First name: \n");
scanf("%s",stdt[i].name);
printf("Last name: \n");
scanf("%s",stdt[i].surname);
printf("UUN: \n");
scanf("%s",stdt[i].UUN);
printf("Department: \n");
scanf("%s",stdt[i].department);
printf("Gender (m/f): \n");
scanf("%c",stdt[i].gender);
printf("Age: \n");
scanf("%d",stdt[i].age);
}
findOldest(p,6);
return 0;
}
This should work.
student_t findOldest(student_t *p, int len){
int i;
student_t max = *(p+0);
for(i=1;i<len;i++)
{if((*(p+i)).age > max.age)
max = *(p+i);
}
return max;
}
You want to return the student so keep the student in your max variable not the age. And to refer to pointers either use
(p+i)->age > max.age
or use
(*(p+i)).age > max.age
But there are other problems with the code.

Resources