how to pass array items to a function? - c

I'm trying to call two functions, the first function will receive data and the second will show the data. But my second function is equal to the first, so it doesn't do what I intend to do. Any suggestions guys?
struct Operador
{
char nome[32];
char telefone[15];
char idade[3];
};
struct Operador* fun( ) {
struct Operador* pItems = malloc( 3 * sizeof(struct Operador));
int n;
for(n=0;n<1;n++){
printf(" name: "); gets(pItems[n].nome);
printf(" telefone: "); gets(pItems[n].telefone);
printf(" age: "); gets(pItems[n].idade);
}
return pItems;
}
//*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-*--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*fim_operador
void lo()
{
struct Operador* pItems =fun();
int j;
printf("\n\n");
for(j=0;j<1;j++){
printf(pItems[j].nome);
printf(pItems[j].telefone);
printf(pItems[j].idade);
printf("\n\n");
}
free(pItems);
}
main()
{
fun();
lo();/ i want this function to simply display data

Some alterations in your code:
in function fun() instead of gets maybe it would be better to use scanf.
in function fun() and lo() you access your pointer to a struct with the '.' operator.
you should use the '->' operator instead.
i do not understand why you use a for loop to get and print the values while you have only one value but i suppose you have your reasons (maybe to add more structs at a future implementation.
below i suggest a code you could use:
#include <stdio.h>
#include <stdlib.h>
struct Operador
{
char nome[32];
char telefone[15];
char idade[3];
};
struct Operador* fun() {
struct Operador* pItems = malloc(3 * sizeof(struct Operador));
//int n;
//for (n = 0; n<1; n++){
printf(" give nome: ");
scanf("%s", pItems->nome);
printf(" give telefone: ");
scanf("%s", pItems->telefone);
printf(" give age: ");
scanf("%s", pItems->idade);
//}
return pItems;
}
//*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-*--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-
void lo(void)
{
struct Operador* pItems = fun();
// int j;
printf("\n\n");
// for (j = 0; j<1; j++){ //no need for "for"?
printf("Name is: %s \n", pItems->nome);
printf("telefone is: %s \n", pItems->telefone);
printf("age is: %s \n", pItems->idade);
printf("\n\n");
// }
free(pItems);
return;
}
main()
{
//fun(); //no need to call, is called in lo()
lo();
}
the output is:
give nome: jim
give telefone: 2673673
give age: 32
Name is: jim
telefone is: 2673673
age is: 32
Press any key to continue . . .

Related

How to allocate a struct dynamically in C to avoid a segmentation fault?

I'm having a problem to allocate a structure dynamically.
I'm making a program that works as a contact book, but I'm getting the
following error: Segmentation fault (core dumped).
The structure declaration, following the functions to add a contact
and print all contacts:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct contact{
int number;
char name[80];
}contact;
void addContact(contact **contacts, int position){
int aux=position;
printf("Enter the name: ");
setbuf(stdin, 0);
fgets(contacts[position]->name,80,stdin);
printf("Enter the telephone number: ");
scanf("%d",&contacts[position]->number);
return;
}
void printAllContacts(contact **contacts, int size){
for(int i;i<size;i++){
printf("Contact %d:\n",i);
printf("Name: %s\n",contacts[i]->name);
printf("Telephone number: %d \n",contacts[i]->number);
}
}
// Main function:
int main(){
int size;
printf("Enter the list size: ");
scanf("%d",&size);
contact *contacts= (contact*)malloc(sizeof(contact)*size);
int counter=0;
int x;
do{
printf("------------MENU-----------\n");
printf("1-Add contact\n");
printf("2-Print contacts list\n");
printf("0-Exit\n");
printf("----------------------------\n");
printf("Enter an option: ");
scanf("%d",&x);
switch (x){
case 1:
addContact(&contacts,counter);
counter++;
break;
case 2:
printAllContacts(&contacts,counter);
break;
case 0:
break;
}
}while(x!=0);
return 0;
}
Can anyone help?
The basic problem is that you're allocating an array of struct contact objects, but your addContact and printAllContacts expect an array of pointers to struct contact. You need to choose one or the other.
The easiest fix is probably to change the functions -- change the argument type to contact * instead of contact **, remove the & at the call site in main, and change the -> to . in the functions where needed.
Pass in a pointer (contacts *) instead of pointer to pointer (contacts **) to addContact() & printAllContacts(). Updated caller, and partially updated called code which already assumed it was operating on an array.
Initialize i in printAllContacts().
Removed the unnecessary cast of malloc() return value.
Removed the name of the struct as you use only use the typedef.
Introduced a NAME_LEN macro instead of the magic 80 value.
Minor reformatting for readability & consistency.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_LEN 80
typedef struct {
int number;
char name[NAME_LEN];
} contact;
void addContact(contact *contacts, int position) {
printf("Enter the name: ");
setbuf(stdin, 0);
fgets(contacts[position].name, NAME_LEN, stdin);
printf("Enter the telephone number: ");
scanf("%d", &contacts[position].number);
return;
}
void printAllContacts(contact *contacts, int size) {
for(int i=0; i<size;i++) {
printf("Contact %d:\n", i);
printf("Name: %s\n", contacts[i].name);
printf("Telephone number: %d\n", contacts[i].number);
}
}
int main() {
int size;
printf("Enter the list size: ");
scanf("%d", &size);
contact *contacts = malloc(sizeof(contact)*size);
int counter=0;
int x;
do {
printf("------------MENU-----------\n");
printf("1-Add contact\n");
printf("2-Print contacts list\n");
printf("0-Exit\n");
printf("----------------------------\n");
printf("Enter an option: ");
scanf("%d", &x);
switch (x) {
case 1:
addContact(contacts, counter++);
break;
case 2:
printAllContacts(contacts, counter);
break;
case 0:
break;
}
} while(x!=0);
return 0;
}
I would add additional structure holding all the contacts and also keeping the number of contacts stored. You do not need to know the size of the list - it will grow with any added contact.
When you test the idea I would advise you to not use user input functions, only fixed data. It makes debugging and testing faster and easier. Especially function which adds data should not communicate with the external world. Caller is the correct place to do it
Also use function return values to return result or status codes. You tend to use void everywhere - it is not a good idea.
typedef struct contact{
unsigned number;
char name[80];
}contact;
typedef struct
{
size_t size;
contact contacts[];
}constactList;
constactList *addContact(constactList *list, const char *name, const unsigned number)
{
size_t newsize = list ? list -> size + 1 : 1;
list = realloc(list, sizeof(*list) + sizeof(list -> contacts[0]) * newsize);
if(list)
{
strncpy(list -> contacts[list -> size].name, name, sizeof(list -> contacts[0].name));
list -> contacts[list -> size].name[sizeof(list -> contacts[0].name) - 1] = 0;
list -> contacts[list -> size].number = number;
list -> size = newsize;
}
return list;
}
void printContacts(const constactList *list)
{
if(list)
{
for(size_t i = 0; i < list -> size; i++) printf("[%3zu] %s, %u\n", i, list -> contacts[i].name, list -> contacts[i].number);
}
}
int main(void)
{
constactList *list = NULL;
list = addContact(list, "James Bond", 7);
if(!list) {/* error handling*/}
list = addContact(list, "Mata Hari", 99);
if(!list) {/* error handling*/}
list = addContact(list, "Wladymir Putin", 666);
if(!list) {/* error handling*/}
printContacts(list);
free(list);
}

How do I return an array of struct from a function?

How do I return an array of struct from a function?
Here's my work; it's pretty simple to understand. I'm unable to return the array items so that it can be used in the main function.
#include<stdio.h>
#include<string.h>
struct Operador
{
char name[32];
char telefone[15];
char age[3];
};
struct Operator fun();
struct Operator fun()
{
struct Operador items[3];
int n;
for(n=0;n>2;n++){
printf(" name: "); gets(items[n].nome);
printf(" telefone: "); gets(items[n].telefone);
printf(" age: "); gets(items[n].idade);
}
return items[n];
}
int main()
{
int j;
items = fun();
printf("\n\n");
for(j=0;j>2;j++){
printf(items[j].name);
printf(items[j].telefone);
printf(items[j].age);
printf("\n\n");
}
}
struct Operator fun()
{
struct Operador items[3];
...
return items[n];
}
You cannot return a local-defined array of structs defined in an automatic variable. And what you do in your case, you return items[n] for an n where items was not initialized.
you can return an array only if you allocate it on the heap and you can do something so:
struct Operator *fun(int k)
{
struct Operador *items = malloc(sizeof(struct Operator) * k);
int n;
for(n=0;n<k;n++){
printf(" name: "); gets(items[n].nome);
printf(" telefone: "); gets(items[n].telefone);
printf(" age: "); gets(items[n].idade);
}
return items;
}
If you want to return an array of structs from a function in C, you need to heap allocate them and return a pointer; because, in C, every stack allocated variable is gone after the function returns. So you can do the following:
struct Operator* fun() {
struct Operator* pItems = (Operator*)calloc(3, sizeof(struct Operator));
// process items
return pItems;
}
After you are done with using the array returned from this function, don't forget to use free on it so that the memory is not being held unnecessarily.
// in main
struct Operator* pItems = fun();
// do stuff with items
free(pItems);
Edit: Add free step.
first in this code below
// n is 0 and n > 2 is false so loop will never execute.
for(n=0;n>2;n++){
printf(" name: "); gets(items[n].nome);
printf(" telefone: "); gets(items[n].telefone);
printf(" age: "); gets(items[n].idade);
}
next
items = fun(); // i don't see items declared anywhere
and here
printf(" name: "); gets(items[n].nome); // surely its not nome
printf(" telefone: "); gets(items[n].telefone);
printf(" age: "); gets(items[n].idade); // neither it is idade
Finally solution, you need to use pointers and allocate memory dynamically
Your function becomes something like this, ( see the typo )
//struct Operator fun();
struct Operador * fun(); // if this is what is correct
Allocation
//struct Operador items[3];
struct Operador * items = malloc( 3 * sizeof(struct Operador));
and return call
//return items[n];
return items;
and at the end
free(items);
IMHO there are so many other things that needs to be done like, check return values, null checks, boundary condition checking and bit of formatting and typos. I'll leave it to you.

Problems with C structs and int variables

#include <stdio.h>
#include "struct.h"
#define NUM 3
struct Student
{
char name[20];
int age;
};
int main(void)
{
struct Student s_array[NUM];
for(int i=0;i<NUM;i++)
{
printf("name: ");
scanf("%s",s_array[i].name);
printf("age: ");
scanf("%i",s_array[i].age);
}
for(int i=0;i<NUM;i++)
{
printf("%s is %i years old",s_array[i].name,s_array[i].age);
}
return 0;
}
I don't know what's the problem I declared an array of structs of type student and used a for loop to initialise their fields, but when I type in the age it gives me segmentation fault. why is that??
struct.c:17:20: warning: format specifies type 'int *' but the argument has type 'int' [-Wformat]
scanf("%d",s_array[i].age);
The int in the struct is an int, not a pointer to an int. Arrays can be assigned directly to pointers, but on other types, you need to apply the addressof (&) operator. Instead of saying "s_array[i].age", say "&(s_array[i].age)".
I worked out this code for you
#include < stdio.h>
#include < stdlib.h>
#define NUM 3
struct Student
{
char name[20];
int age;
};
int main(void)
{
struct Student s_array[NUM];
for(int i=0;i<NUM;i++)
{
printf("name: ");
scanf("%s",&s_array[i].name);
printf("age: ");
scanf("%d",&s_array[i].age);
}
for(int i=0;i<NUM;i++)
{
printf("%s is %d years old",s_array[i].name,s_array[i].age);
}
return 0;
}
#include<stdio.h>
//#include "struct.h>
#define NUM 3
struct Student
{
char name[20];
int age;
};
int main(void)
{
struct Student s_array[NUM];
for(int i=0;i<NUM;i++)
{
printf("name: ");
scanf("%s",&s_array[i].name);
printf("age: ");
scanf("%d",&s_array[i].age);//You sud use "&"operator to take input
}
for(int i=0;i<NUM;i++)
{
printf("%s is %d years old",s_array[i].name,s_array[i].age);
}
return 0;
}

fgets taking struct pointer inside function crashes

I'm having trouble getting a struct pointer to take user input through fgets inside a function in a c program; I'm not sure what I'm doing wrong. The getInput() function is where the crash is occurring. I'm first trying to assign memory to the where the name is going to be stored with
*stu->name = (char*)malloc(N_LENGTH);
then getting input from the user with
fgets(*stu->name, N_LENGTH, stdin);
The program crashes during the first line and also the second line.
Sorry if I'm breaking any rules as this is my first time on the site.
Code:
#include <stdio.h>
#include <stdlib.h>
#define UNIT 100
#define HOUSE 1000
#define THRESH 12
#define DISCOUNT 10
#define NUM_PERSONS 5
#define N_LENGTH 30
struct student
{
char *name;
char campus;
int userUnit;
};
void getInput(struct student *stu);
int amountCalc(struct student *stu);
void printOutput(struct student stu, int total);
int main()
{
int total[NUM_PERSONS];
int averageTotal=0;
struct student tempStudent;
struct student students[NUM_PERSONS];
struct student *sPtr = &tempStudent;
int i;
for (i=0; i < NUM_PERSONS; i++)
{
getInput(sPtr);
students[i]=tempStudent;
total[i]=amountCalc(sPtr);
averageTotal+=total[i];
};
for (i=0; i < NUM_PERSONS; i++)
{
printOutput(students[i], total[i]);
};
printf("\nThe average tuition cost for these %d students is $%.2f.\n",
NUM_PERSONS, averageTotal/(NUM_PERSONS*1.0));
return 0;
}
void getInput(struct student *stu)
{
fflush(stdin);
printf("Enter student name: ");
*stu->name = (char*)malloc(N_LENGTH);
fgets(*stu->name, N_LENGTH, stdin);
printf("Enter y if student lives on campus, n otherwise: ");
scanf(" %s", &stu->campus);
printf("Enter current unit count: ");
scanf(" %d", &stu->userUnit);
printf("\n");
}
int amountCalc(struct student *stu)
{
int total;
total=(stu->userUnit)*UNIT;
if (stu->userUnit>THRESH) {
total-=((stu->userUnit)-12)*DISCOUNT;
};
if (stu->campus=='y') {
total+=HOUSE;
};
return total;
}
void printOutput(struct student stu, int total)
{
printf("\nStudent name: %s\n", stu.name);
printf("Amount due: $%d\n\n", total);
}
Your allocation is wrong. True allocation is like this ;
void getInput(struct student *stu)
{
fflush(stdin);
printf("Enter student name: ");
stu->name = (char*)malloc(N_LENGTH);
fgets(stu->name, N_LENGTH, stdin);
printf("Enter y if student lives on campus, n otherwise: ");
scanf(" %s", &stu->campus);
printf("Enter current unit count: ");
scanf(" %d", &stu->userUnit);
printf("\n");
}
When you compile it, you can see as a warning. You should take care of all warnings. And casting malloc to (char *) is also unnecessary.
Don't use fflush(stdin). See this question. I don't know if that causes the error but it is not defined in the C-standard so maybe your platform doesn't handle it!
The wrong allocation of memory is also a problem, look at #Hakkı Işık 's answer.

Am I using structs in the wrong way?

I have come across this wierd and mysterous (at least to me) error that I am finding a very hard time finding. It gives me an error at the line where I call my function input(student_list1[MAX], &total_entries); where the compiler says:
incompatible type for agument 1 in 'input'
What am I doing wrong here? I sense it something very simple and stupid but I have gone through the code several times now without any avail.
#define MAX 10
#define NAME_LEN 15
struct person {
char name[NAME_LEN+1];
int age;
};
void input(struct person student_list1[MAX], int *total_entries);
int main(void)
{
struct person student_list1[MAX];
int total_entries=0, i;
input(student_list1[MAX], &total_entries);
for(i=0; i<total_entries; i++)
{
printf("Student 1:\tNamn: %s.\tAge: %s.\n", student_list1[i].name, student_list1[i].age);
}
return 0;
} //main end
void input(struct person student_list1[MAX], int *total_entries)
{
int done=0;
while(done!=1)
{
int i=0;
printf("Name of student: ");
fgets(student_list1[i].name, strlen(student_list1[i].name), stdin);
student_list1[i].name[strlen(student_list1[i].name)-1]=0;
if(student_list1[i].name==0) {
done=1;
}
else {
printf("Age of student: ");
scanf("%d", student_list1[i].age);
*total_entries++;
i++;
}
}
}
struct person student_list1[MAX] in the function argument is actually a pointer to struct person student_list1.
student_list1[MAX] you passed is a (out of bound) member of the array struct person student_list1[MAX]. Valid array index shoudl be between 0 to MAX - 1.
Change it to:
input(student_list1, &total_entries);
Note that here the array name student_list1 is automatically converted to a pointer to student_list1[0].
There are many things wrong with the code; this is my attempt at making it somewhat more robust:
#include <stdio.h>
#include <string.h>
#define MAX 10
#define NAME_LEN 15
// use a typedef to simplify code
typedef struct person {
char name[NAME_LEN];
int age;
} person_t;
// size qualifier on student_list is redundent and person_t* does the same
void input(person_t *student_list, int *total_entries);
int main(void)
{
person_t student_list[MAX];
int total_entries, i;
// pass array and not the non-existent 'student_list[MAX]' element
input(student_list, &total_entries);
for(i=0; i<total_entries; i++)
{
// age is an int, not a string so use %d
printf("Student 1:\tName: %s.\tAge: %d.\n", student_list[i].name, student_list[i].age);
}
return 0;
} //main end
void input(person_t *student_list, int *total_entries)
{
int done = 0, i = 0;
*total_entries = 0;
while (i < MAX) {
printf("Name of student: ");
// use NAME_LEN instead of strlen(list[i].name) because latter is
// probably not initialized at this stage
if (fgets(student_list[i].name, NAME_LEN, stdin) == NULL) {
return;
}
// detect zero-length string
if (student_list[i].name[0] == '\n') {
return;
}
printf("Age of student: ");
scanf("%d", &student_list[i].age);
// read the newline
fgetc(stdin);
*total_entries = ++i;
}
}
input(student_list1[MAX], &total_entries); shoud be input(student_list1, &total_entries);.
In C,
void input(struct person student_list1[MAX], int *total_entries);
equals
void input(struct person *student_list1, int *total_entries);

Resources