Output of values of a struct via a function with a pointer as a parameter - c

I have two structures. A pointer is assigned to one.
Now I would like to output data previously entered via scanf via a function (outputAddress) with a pointer as a parameter.
It works with the variables via the pointer. But how do I do that with the values from the other structure? How can I output this in the function?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct structPerson
{
char name[30];
char forename[50];
int age;
};
struct structAddress
{
int zip;
char location[35];
char street[40];
int hNumber;
struct structPerson *ptrPerson;
};
void outputAddress(struct structPerson *ptrPerson)
{
printf("\n\nOutput Address: \n");
printf("ptrPerson->name: %s", ptrPerson->name);
printf("\nptrPerson->forename: %s", ptrPerson->forename);
return;
}
int main()
{
struct structPerson person1;
struct structAddress address1;
address1.ptrPerson = &person1;
printf("Location: ");
scanf("%s", &address1.location);
printf("Zip: ");
scanf("%d", &address1.zip);
printf("\nName: ");
scanf("%s", &address1.ptrPerson->name);
printf("Forename: ");
scanf("%s", &address1.ptrPerson->forename);
printf("\nOutput: %d %s %s\n", address1.zip, address1.location, address1.ptrPerson->name);
// strcpy( address1.location, "");
// printf("structAddress1: %d %s\n", address1.zip, address1.location);
outputAddress(&person1);
return 0;
}

In your data model structAddress is associated with a person via the personPtr field. As a result, Address is a main data struct. If I understand your intention correctly, you want to print info about the person and then his/her address.
For this you need to do a couple of changes. Firstly, you should pass the Address struct to the print function, because it has all information available, including the pointer to the person. Secondly, you should access your person information using the pointer: ptrAddress->ptrPerson-><field>. Here is an example.
void outputAddress(struct structAddress *ptrAddress)
{
printf("\n\nOutput Address: \n");
// use ptrAddress->ptrPreson to accesss person information
printf("ptrPerson->name: %s", ptrAddress->ptrPerson->name);
printf("\nptrPerson->forename: %s", ptrAddress->ptrPerson->forename);
// use ptrAddress-> to access address fields.
printf("\nptrAddress->zip: %d", ptrAddress->zip);
...
return;
}
int main() {
...
outputAddress(&address1); // << use address1 here.
...
}

Your datamodel is probably broken anyway. The address struct has a pointer to a person, but it often makes more sense to have it the other way around.

Related

Function not starting after user input being returned from another function

That's the code in C:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char street;
int number;
char postalcode;
} Person;
void print(Person p) {
printf("Street: %s\n", p.street);
printf("Number: %d\n", p.number);
printf("Postal code: %s\n", p.postalcode);
}
Person signUp() {
Person person;
printf("In which street do you live on?: \n");
scanf("%s", &person.street);
printf("What is your number?: \n");
scanf("%d", &person.number);
printf("what is your postal code?: \n");
scanf("%s", &person.postalcode);
return person;
}
int main(void) {
Person person;
person = signUp();
print(person);
return 0;
}
I tried to make the "signUp" function return the user inputs to another function called "print", so it would print the values from the previous function. The "signUp" function works just fine, but the "print" function never starts.
You reading and writing strings with %s but your variables are a single char (which would be the format string %c).
When reading a string with scanf() always use a maximum field width. I am using a str() macro here to not repeat myself. Note: usually we prefer using sizeof() but you need sizeof(p->street)-1 and the order of evaluation of macros gets in the way.
There is nothing wrong with passing in a struct by value and returning them by value, however, this implies copies so we usually pass these in via a pointer instead.
#include <stdio.h>
#include <stdlib.h>
#define POSTALCODE_LEN 5
#define STREET_LEN 20
#define str(s) str2(s)
#define str2(s) #s
typedef struct {
char street[STREET_LEN+1];
int number;
char postalcode[POSTALCODE_LEN+1];
} Person;
void print(const Person *p) {
printf("Street: %s\n", p->street);
printf("Number: %d\n", p->number);
printf("Postal code: %s\n", p->postalcode);
}
void signUp(Person *person) {
printf("In which street do you live on?: \n");
scanf("%" str(STREET_LEN) "s", person->street);
printf("What is your number?: \n");
scanf("%d", &person->number);
printf("what is your postal code?: \n");
scanf("%" str(POSTALCODE_LEN) "s", person->postalcode);
}
int main(void) {
Person person;
signUp(&person);
print(&person);
}
I realize that the typedef saves you from writing struct Person but the downside is that it imports "Person" into the same name space as variable so you cannot do Person Person but have to use a lowercase person. If you need to talk to someone about your code it becomes more tedious "lowercase person" or "uppercase person" to differentiate. Personally (pun), I would use use a short variable name to get around it, i.e. Person p.
I also find snake case easier to read than camel case (sign_up() vs signUp()), and I find the namespace rules easier to remember (constants are upper case, rest is lowercase; with camel case it's methods starts with lower case and then you upper case each words except ... etc).

How to assign fields of a struct from scanning stdin?

I want the program to extract data from the user through the console, by scanning stdin with the scanf() and fgets() and assign the values to named structs, to eventually print them out.
Right the following code is not working. The problem is the code does not recognize the scanned input and the array corona and fails to assign it into that array at index "0".
Here's the code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char name[100];
char phone[100];
} Person;
typedef struct {
char location[100];
char time[100];
} Event;
typedef struct {
Person person;
Event event;
} Corona;
int main() {
/*help variables*/
char* name2;
char* number2;
char* location2;
char* date2;
Corona corona[28]; //creating list with 28 objects just because. it could be 5 or x too.
printf("Name");
fgets(name2, 50, stdin); //user input for name
printf("Nummer/location/date");
scanf("%s %s %s", number2, location2, date2); //user input for phone number, location and date
corona[0]= *(Corona*)malloc(sizeof (Corona)); //allocating memory for array
corona[0]={{("%s",name2),("%s", number2)}, {("%s", location2),("%s", date2)}};
/*printing out the information of array "corona" with index 0"*/
printf("Name: %s\n", corona[0].person.name);
printf("Phone: %s\n", corona[0].person.phone);
printf("Location: %s\n", corona[0].event.location);
printf("Time: %s\n", corona[0].event.time);
return 0;
}
lets fix one part of this and see if you can fix the rest
printf("Nummer/location/date");
scanf("%s %s %s", corona[0].person.phone,
corona[0].event.location,
corona[0].event.time);
no need for any mallocs, fancy casts or whatever that assignment line is tryong to do
ie these lines
corona[0]= *(Corona*)malloc(sizeof (Corona)); //allocating memory for array
corona[0]={{("%s",name2),("%s", number2)}, {("%s", location2),("%s", date2)}};

Is this a correct usage of struct?

#include <stdio.h>
int main()
{
struct database
{
char name[10];
int number;
int roll;
};
struct database s1,s2;
printf("enter name, number , roll: ");
scanf("%c%d%d",&s1.name,&s1.number,&s1.roll);
scanf("%c%d%d",&s2.name,&s2.number,&s2.roll);
printf("Entered value is :");
printf("%c%d%d",s1.name,s1.number,s1.roll);
printf("%c%d%d",s2.name,s2.number,s2.roll);
}
I've been trying to get output but I don't know if this correct Or should I access them individually? Help would be very much appreciated! thanks :)
If you need the specific struct only within the function body, then your declaration will suffice. But, note that if you want a struct to be used throughout the program, then it needs to be defined like this:
struct database {
...
};
int main(void) {
struct database s1, s2;
...
}
Also, you're trying to accept a single char value:
scanf("%c%d%d", &name, ...);
// --^^--
Here, you are expected to get a char from the user:
scanf("%9s%d%d", name, ...);
Note: The %9s is specifically given to prevent input buffer overflow.
A nicely structured program would look like (notice comments):
#include <stdio.h>
// Don't use magical numbers for constants in the program
// The use macros for this will suffice and look a ton cleaner
#define MAX_LENGTH 64
#define FMT_LENGTH "%63s"
// Our structure
struct database {
char name[MAX_LENGTH];
int number;
int roll;
};
int main(void) {
// You are here only creating single instances of struct
struct database s1, s2;
printf("Enter name, number and roll: ");
// Always check if the values are correctly assigned to their respective
// variables, if not, print error and exit (in this context)
if (scanf(FMT_LENGTH " %d %d", s1.name, &s1.number, &s1.roll) != 3) {
printf("error: One of the values are incorrectly assigned.\n");
return 1; // Exit Failure
}
// Same with s2
printf("Name: %s | Number: %d | Roll: %d\n", s1.name, s1.number, s1.roll);
return 0;
}

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;
}

Array of structs in c: giving all the strings same values (with the int it works well). What sould I do?

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.

Resources