Returning structure from function - c

Below is the code through which I am returning structure from function. May be the question is very basic but I am not clear why I am writing emp in this line struct emp putinfo (){. I am not clear why I need to write the structure name? Because inside the function I am defining the structure as struct emp t;. What is the specific reason?
#include <stdio.h>
struct emp {
int number;
char name [200];
};
void print (struct emp team){
printf ("Details of employee %d %s", team.number, team.name );
}
struct emp putinfo (){
struct emp t;
printf ("Enter number"); scanf ("%d", &t.number);
printf ("Enter name"); scanf ("%s", &t.name);
return t;
}
int main (){
struct emp test;
test = putinfo ();
print (test);
return 0;
}

struct emp is actually the name with which you address the structure in C. You can typedef it and then you can write only emp.The reason why it stands before putinfo is because this is the returned type by the function.struct emp t just makes a new structure of type emp and assigns it to t.

In C the name of the type you create when you define a structure is struct structure_name C++ allows to use this format or just structure_name
Example:
struct some_struct{};
struct some_struct x; // Variable declaration C, C++ syntax.
some_struct y; // Only C++ syntax.
If you are working with C you must specify the return value of your function using C syntax:
struct some_struct my_function(){}
on the other hand in C++ you can
struct some_struct my_function(){}
or
some_struct my_function(){}

Define your struct and use the type definition instead:
#include <stdio.h>
typedef struct {
int number;
char name [200];
}emp;
void print (emp team){
printf ("Details of employee %d %s", team.number, team.name );
}
emp putinfo (){
emp t;
printf ("Enter number"); scanf ("%d", &t.number);
printf ("Enter name"); scanf ("%d", &t.name);
return t;
}
int main (){
printf("hello\n");
emp test;
test = putinfo ();
print (test);
return 0;
}

You're right in that this is redundant (at a first glance, but see below), but this is how C works, there is no type inference. This is the same for every type (and unrelated to structures):
succ.c
unsigned succ(unsigned n) {
unsigned succ = n + 1;
return succ;
}
Here, you could also say, there's no real reason you have to specify the return type.
So, now the part why this is needed:
1) It's needed at least in a prototype because the compiler may not be able to see the definition, consider
main.c
#include <stdio.h>
unsigned succ(unsigned);
int main(void) {
printf("%u\n", succ(1));
}
where the object file containing the implementation of succ may be already compiled (you could compile via gcc main.c succ.o or the like).
2) Consider
long int_to_long(int n) { return n; }
where an int is converted to a long (and the compiler couldn't have known without a return type). OK, this doesn't hold for structures (they are never implicitly converted), but it's consistent.
And usually, you don't pass structures by value at all, but pass pointers to it, especially if they are large.
Finally, a few notes about your code:
Never, ever, use %s without a length for scanf. It's always wrong (how should scanf know how big the array you provided is?), do e.g.
printf ("Enter name\n"); scanf ("%199s", t.name);
or use fgets instead; in productive code, you almost never want to use scanf, because the error handling is complicated. Also note the newline I added, the message asking for input may not appear until after you've written a newline to stdout (stdout is usually line buffered, and so is usually a terminal, a (better) alternative would be fprintf(stderr, "Enter name: ");, as stderr is unbuffered and this output shouldn't really go to stdout anyway.).
Generally, I would advise you to not write interactive programs until you're familiar with pointers and arrays, dynamic memory allocation, error handling, and file buffering, but pass information from the user via command-line arguments. You currently know too little to write interactive programs properly.
HTH

Related

How to get a int with scanf()

void pedir_diag(int* diag){
scanf("%i", &diag);
}
int main() {
int number;
pedir_diag(&number);
return 0;
}
When I compile introduce an integer and expect that number int variable in the main have the value introduced but is not set
I have this, in my code but i am not able to set diag variable with scanf() function.
diag is already a pointer so no need for the address-of operator (&) in the call to scanf():
void pedir_diag(int *diag)
{
scanf("%d", diag);
}
But to do it that way is kinda stupid. You have no way to check for erroneous input.
Better:
#include <stdbool.h>
bool pedir_diag(int *diag)
{
return scanf("%d", diag) == 1; // *)
}
*) scanf() returns the number of successful conversions, so if the number of successful conversions is 1 we return true.
Usage:
#include <stdio.h>
int main(void)
{
int foo;
if (!pedir_diag(&foo)) {
fputs("Input error :(\n\n", stderr);
}
else {
// have fun with foo
}
}
The best way to use scanf through your entire coding life is by remembering the following rule
scanf("%[direction_of_what_to_scan][special format character]",
Pointer_on_some_memory_location);
What scanf does is that it stores what the input was (with some length restrictions) to a memory address. So, either:
int n1;
scanf("%d",&n); //which means the address of variable n1 in memory
or
int *n2 = &n1;
scanf("%d",n) // &doesn't need to be used cause n2 is now already pointer to an integer
Both will are different implementations of the same thing, they differ to the part of using pointers,for which C is well-known,and even applicable these days.

How to loop through an array declared in the header file?

I have declared my header file with a structure consisting of arrays. It looks like this:
#ifndef HEADER_H_
#define HEADER_H_
typedef struct{
uint32_t State[3];
}h_t;
#endif
The C file that accesses this header file looks as follows:
#include"Header.h"
#include<stdio.h>
#include <stdlib.h>
char* old_states[3];
old_states[0] ="ABC";
old_states[1] ="BAC";
old_states[2] ="AAC";
h_t var;
for(i=0; i<3;i++){
var.State[i] = old_states[i];
printf("\n The state is %s", var.State[i]);
}
I print the states out to check them. THey are:
The state is ABC
The state is BAC
The state is AAC
Now I want to loop through each var.State[n], like var.State[0], var.State[1], var.State[2] individually.
That is loop through var.State[0] ="ABC" so that I could access each of the letters(A,B,C) individually. Can somebody tell me how could I achieve this?
In your code, old_states[n]is of char *, a pointer. OTOH, var.State[i] is of type uint32_t and they are not same.
A pointer type maybe converted to an integer type, but the result is strictly implementation dependent. To take this further, as stated in C11, chapter §6.3.2.3,
If the result cannot be represented in the integer type, the behavior is undefined.
So, basically you should avoid doing this unless you really really know what you're doing.
Then, in case of
printf("\n The state is %s", var.State[i])
%s expects a char * (a pointer to the initial element of an array of character type, to be exact, and in case the precision is not specified, it should be null-terminated), but what you're passing is uint32_t. It is called undefined behaviour again, as per the above point.
Moral of the story: enable compiler warnings and pay heed to them.
Solution:
Preferable, change your structure member type from
uint32_t State[3];
to
char * State[3];
then, assign them as you're doing now and finally, for accessing all individual elements, you can do something like (pseudocode)
for(i=0; i<3;i++)
{
int len = strlen(var.State[i]);
for(j=0; j < len ;j++) printf("%c \t", var.State[i][j]);
printf("\n");
}
As you declared uint32_t State[3]; and printing it with %s specifier that creates problem.
You can declare State[3]; as a 2-D character array like this -
EDIT
char State[3][4];
And to store values -
for(i=0;i<3;i++)
{
memcpy(var.State[i],old_states[i],strlen(old_states[i]);
}
And access each character like this -
var.State[i][j]
To print each character
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%c",var.State[i][j]);
}
printf("\n");
}

Trouble Passing array of Structs using pointers

I'm having problems with a function that I use to write to an element of an array.
I think it might be because I'm not passing the array of struct correctly. I was wondering if someone can point out how to do this correctly. I've been screwing it up more than fixing it.
let's say I have a function menu.c
I declare my struct newPerson person[MAX_PERSONS];
I then run my function addPerson(person, &num);
which is the following
void addPerson(newPerson *pers, int *num){
pers[*num] = (newPerson) {
"Michelle", "Leo", "6136458798", STUDENT,
.data = {.s = {9, 1234.50, 3}}
};
*num = *num + 1;
}
It runs, but won't print out correctly, I'm guessing because it doesn't write where I want it to pers[num]. I tried calling the function this way also addPerson(&person, &num); instead of just addPerson(person, &num); but then I receive this error
warning: passing argument 1 of ‘addPerson’ from incompatible pointer type [enabled by default]
and
note: expected ‘struct newPerson ’ but argument is of type ‘struct newPerson ()[20]’
I've tried changing the function to void addPerson(newPerson *pers[], int *num){ as well but nothing there. Was wondering if anyone can point out what I'm doing wrong here and how I can fix my problem. Any help would be appreciated, thanks!
Forgot to mention that the addPerson function works in some places where I run it.
int menu(int num) {
newPerson person[MAX_PERSONS];
//printf("THE NUMBER START OF MENU IS %d\n", num); test counter
//addPerson(person, &num); <- WRITES AND READS PROPERLY IF DONE HERE
int option;
printf(
"\n\tPlease choose one of the following options to continue (0-9): ");
scanf("%d", &option);
if (option == 1) { //program will ask for name input
addPerson(person, &num); <- HOWEVER IT DOES NOT WRITE OR READ PROPERLY HERE
menu(num);
}
Both functions are called in menu.c
However when I call addPerson in the if statement, it does not write/read properly.
Just solved the problem by declaring the struct as static!
static newPerson person[MAX_PERSONS];
I'm not sure if this is taboo or anything, but it fixed my problem!
By making static you have made the code inefficient as the memory for
the data structure has been set aside regardless of whether it is
needed or not while the program is executing.(With a static data
structure, the size of the structure is fixed.)
Declare the function like
void addPerson(newPerson *pers[],int *num)
call the function like
void addPerson(newPerson *pers, int *num);
OR
void addPerson(newPerson pers[], int *num);
I was able to get it working by declaring the struct as static
static newPerson person[MAX_PERSONS];
Not sure if this is an actual fix or if it's just masking my problem though.

Assigning a character array to a character array in a structure

I am working on a project that requires that I make an array of a certain structure type. The structure looks like this:
typedef struct
{
char array[30];
int num;
}structure
I have declared an array of these structures like this:
structure struct1[5];
I passed this structure array to a function which fills the first four elements with a string and a number. The fifth is left blank. Later in the program, I pass the array again and try to set the string in the structure to a user determined string using gets(). I am getting this error:
438:19: error: incompatible types when assigning to type 'char[30]' from type 'char *'
If I need to provide more clarification, please tell me.
Thanks!
EDIT: Here is what I am doing:
typedef struct
{
char array[30];
int num;
}structure;
void fillStructs(structure[]);
void userEditStructs(structure[]);
main()
{
structure myStructs[5];
fillStructs(myStructs);
userEditStructs(myStructs);
return 0;
}
void fillStructs(structure s[])
{
//code to fill myStructs elements 0-3.
}
void userEditStructs(structure s[])
{
char newArr[30];
int newNum;
printf("Please enter your string:\n\nEntry:\t");
gets(newArr);
printf("Please enter your number:\n\nEntry:\t");
scanf("%i", newNum);
s[5].array = newArr;
s[5].num = newNum;
}
you are doing something like this
char a[20];
a = "bla";
you cant do this.
do strcpy(a,"bla"); instead. ( #include <string.h> )
Without looking at the code you are probably trying to do something like:
struct[4].array = gets(<unknown>);
which won't work, as you can't assign the returned char* from gets to an array as the compiler says. You are also using gets, which is strongly discouraged as it performs no bounds checking. Instead, do the following:
fgets(struct[4].array, sizeof(struct[4].array), stdin);
which will do proper bounds checking.

Programming with functions and structures using C, getting strange output, no errors

I'm learning a bit C and i'm doing an exercise where i use structures and functions to collect employee infos and just print them out.
I'm declaring the functions and the struct in the header since i need them in both of the other files.
//employee.h
int addEmployee(void);
int printEmployee(int i);
struct employeelist
{
char last [20];
char first[20];
int pnumber;
int salary;
};
The "core" file is executing the both functions. The first function asks for the number of employees and gives a value back for the second function where the information is collected and stored. There are no errors and i've checked the code several times.
//employee.c
#include "employee.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int numE;
int i;
int addEmployee(void)
{
struct employeelist employee[5];
int numE;
printf("How many employees do you want to add to the list?: ");
scanf("%d", &numE);
printf("Please type in the last name, the first name,\nthe personal number and the salary of your employees.\n");
for (i=0; i < numE; i++)
{
printf("Last name: ");
scanf("%s", employee[i].last);
printf("First name: ");
scanf("%s", employee[i].first);
printf("Personal number: ");
scanf("%d", &employee[i].pnumber);
printf("Salary: ");
scanf("%d", &employee[i].salary);
}
return numE;
}
int printEmployee(int emp)
{
struct employeelist employee[5];
for (i=0; i < emp; i++)
{
printf("Last name: {%s}\nFirst name: {%s}\nPersonal number: {%d}\nSalary: {%d}\n",employee[i].last,employee[i].first, employee[i].pnumber, employee[i].salary);
}
getchar();
getchar();
return emp;
}
The last file contains the main() function to execute the functions above.
#include "employee.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int emp;
int main ()
{
struct employeelist employee[5];
int emp = addEmployee();
printEmployee(emp);
return 0;
}
Now my problem is that everything works only the output is incorrect. I can't even say what it is. Some kind of random mix of signs, letters and numbers. Since i have no idea where my mistake is, i would be glad about any advise to solve this problem. Thank you.
I have added a screenshot of my output. Maybe it helps.
You're trying to use a local variable, which ceases to exist when the function returns.
int addEmployee(void)
{
struct employeelist employee[5];
/* ... */
}
The variable employee only exists inside the addEmployee() function; and it is a different object every time the function is called.
int printEmployee(int emp)
{
struct employeelist employee[5];
/* ... */
}
This employee has no relation to the one in addEmployee.
But don't do the easy thing now (*); do the right thing: declare the array in the main() function and pass it around.
//employee.h
struct employeelist
{
char last [20];
char first[20];
int pnumber;
int salary;
};
/* add up to `maxemp` employees to the array and
** return number of employees added */
int addEmployee(struct employeelist *, int maxemp);
/* print all employees from index 0 to (nemp - 1) */
int printEmployee(struct employeelist *, int nemp);
Declare an array in main(), and pass it around
#include "employee.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main ()
{
int emp;
struct employeelist employee[5];
int emp = addEmployee(employee, 5);
printEmployee(employee, emp);
return 0;
}
(*) Don't declare a global variable for employees
Edited employee.h and added a main() function
You have a brand new variable in your print function that isn't even initialized. So it contains only garbage and that is printed
The heart of the problem is that you're working with three different arrays of employees instead of the one array that you think you've got. Anything declared within a pair of curly braces in C only 'exists' while the program is executing code inside those braces. You've declared three different arrays of employee structs in three different blocks of code.
To point you in the right direction (irrespective of whether this is homework or self-study, this is a learning exercise so just fixing your code probably isn't what you want) you should think about how you can pass the same employee array to each of your functions in turn. (EDIT: pmg beat me to it.)
Declare the array once, in your main() function as you've already done, and modify your two functions printEmployee() and addEmployee() to take that array as a parameter instead of declaring their own local arrays.
Here is a very simple example using ints showing how parameters and return values work. You'll have to do some reading about pointers to extend this to your case.
int main() {
int number = 2;
int newNumber;
newNumber = timesTwo(number);
printf("number: %d newNumber: %d", number, newNumber);
}
int timesTwo(int param) {
return param * 2;
}
Before you start breaking things out into separate files and working with structs and pointers it is a good idea to practice the concepts of functions, parameters and variables by building simple programs in a single file.
You declare the employee array locally to both functions, so they cannot access each other's data.
The main issue, as others have already said, is that you are declaring a struct employeelist employee[5] in each of your functions. This makes those variables local to their functions and thus inaccessable from one function to the other. So, when printEmployee goes to print, the data it is printing is gibberish.
There are a few things needed to fix this:
Make one declaration of your employee list in your main (which you already have) and then pass that into the functions. You'll need to do the passing by means of the array name so that the functions will treat the array properly.
As a result of the above, you'll need to move the struct declaration to be above the function prototypes and then change the prototypes in employee.h to accomodate the passing of the employeelist.
You'll have to check that the user doesn't try to enter more records than your array has space for. Alternatively, you could just declare a pointer in the main and malloc() the needed memory in the addEmployee function.
A few other suggestions to make things a little easier on yourself:
Call your struct employee (or something like that) and your array employeelist (or something similar).
Use typedef on your struct to shorten & simplify your declarations.
Change your printEmployee to be a void function (i.e. void return type).
Take a look.. Well distribued and simple to read, it just needs a little improvement to become bigger and do the work u want.
typedef struct
{
char last [20];
char first[20];
long int pnumber;
int salary;
}employee;
/* the two functions clearly declared */
int addEmployee(employee const wEmployeeList[]);
void printEmployee( employee const wEmployeeList[], int );
int main()
{
int numberE;
employee employeeList[2];
numberE = addEmployee(employeeList);
printEmployee(employeeList, numberE);
return 0;
}
int addEmployee(employee const wEmployeeList[2]){
int i;
for (i=0; i < 2; i++)
{
printf("Last name: ");
scanf("%s", wEmployeeList[i].last);
printf("First name: ");
scanf("%s", wEmployeeList[i].first);
printf("Personal number: ");
scanf("%ld", &wEmployeeList[i].pnumber);
printf("Salary: ");
scanf("%d", &wEmployeeList[i].salary);
}
return 2;
}
void printEmployee(employee const wEmployeeList[2], int numberEmployee){
int i;
for (i=0; i < numberEmployee; i++)
{
printf("\n\nLast name: %s\nFirst name: %s\nPersonal number: {%ld}\nSalary: {%d}\n \n",wEmployeeList[i].last,wEmployeeList[i].first, wEmployeeList[i].pnumber, wEmployeeList[i].salary);
}
}

Resources