I am trying to take input data and print it using structures. when i run this code it is not taking input for lastname. It directly asks to enter input for firstname. Can someone help me with this. Thank you.
address.c
typedef struct
{
char lname[25];
char fname[20];
char address[20];
char phonenumber[20];
}addressbook;
addressbook a;
int main()
{
printf("enter details:\n");
printf("enter lastname:\n");
gets(a.lastname);
printf("enter firstname:\n");
gets(a.firstname);
printf("enter address:\n");
gets(a.address);
printf("enter phone number:\n");
gets(a.phonenumber);
printf("lastname:%s\n",a.lastname);
printf("firstname: %s\n", a.firstname);
printf("address:%s\n", a.address);
printf("phone number:%s\n", a.phonenumber);
}
When I run this it is not waiting to enter the lastname. it directly goes to enter firstname.
That code won't even compile as it stands, producing (in my environment):
pax#pax-desktop:~$ gcc -Wall -Wextra -o qq qq.c
qq.c: In function ‘main’:
qq.c:12:2: warning: implicit declaration of function ‘printf’
qq.c:12:2: warning: incompatible implicit declaration of built-in function ‘printf’
qq.c:14:4: warning: implicit declaration of function ‘gets’
qq.c:14:10: error: ‘addressbook’ has no member named ‘lastname’
qq.c:16:10: error: ‘addressbook’ has no member named ‘firstname’
qq.c:21:28: error: ‘addressbook’ has no member named ‘lastname’
qq.c:22:31: error: ‘addressbook’ has no member named ‘firstname’
qq.c:25:1: warning: control reaches end of non-void function
You should always (at least initially) compile with a high warning level and take note of what the compiler is telling you:
you should include stdio.h if you're going to use printf and gets.
you should use consistent field names in your structure.
you should return something from non-void functions (technically this is not necessary under later versions of the standard but it's still a good idea for portability).
In addition, you may want to consider the following:
int main() is not one of the two canonical forms of the main function. While the standard allows for implementation-defined extra ones, the "correct" one for this particular case would be int main (void).
gets is a dangerous function since there is no way to prevent buffer overflow, making your code insecure. For example, if I entered a thousand characters for my first name, it may well screw up your program by overwriting huge chunks of accounting information on the stack (like return addresses for example). You can find a safer input function here.
Making most of those changes, you would end up with something like:
#include <stdio.h>
typedef struct {
char lastname[25];
char firstname[20];
char address[20];
char phonenumber[20];
}addressbook;
addressbook a;
int main (void) {
printf("enter details:\n");
printf("enter lastname:\n");
gets(a.lastname);
printf("enter firstname:\n");
gets(a.firstname);
printf("enter address:\n");
gets(a.address);
printf("enter phone number:\n");
gets(a.phonenumber);
printf("lastname:%s\n",a.lastname);
printf("firstname: %s\n", a.firstname);
printf("address:%s\n", a.address);
printf("phone number:%s\n", a.phonenumber);
return 0;
}
which compiles and runs okay, although it still has the serious buffer overflow vulnerability. If you want to fix that, you can refer to the link I gave.
Related
I have a problem with a small project, I have to create a structure containing a person's data,I have to do data entry via a function using pointers.
I don't understand why when I try to enter the weight the program ends with this error:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
I made an example of the code that is giving me problems:
typedef struct{
char name[DIM];
char surname[DIM];
int height;
float weight;
}Record;
int main() {
Record subj;
insRecord(&subj);
}
void insRecord(Record *subj){
printf("\nName ");
scanf("%64[^\n]s", subj->name);
cleanBuffer();
printf("\nSurname ");
scanf("%64[^\n]s", subj->surname);
cleanBuffer();
printf("\nEight ");
scanf("%3s", subj->height);
cleanBuffer();
printf("\nWeight ");
scanf("%6s", subj->weight);
cleanBuffer();
}
int cleanBuffer(){
int cont= 0;
char c;
do{
cont++;
c = getchar();
}while(c != '\n');
return cont;
}
(I only wrote the main functions).
Furthermore, compiler is giving warnings on height and weight scanf() statements:
Format specifies type 'char *' but the argument has type 'int' (for height)
Format specifies type 'char *' but the argument has type 'double' (for weight)
Could you tell me how can I solve?
PS the project is divided into several files (3 files).
In main.c I wrote the insRecord() function, in struct.h I wrote the Record structure, in struct.c I wrote cleanBuffer() function.
You are reading a string (%s) and try to store that in a float. If you use the flag %f for weight and %d for height it will probably work better. Remember that you should provide a pointer to the float and int that you want to store the data in, you are not doing that in your example.
Have a look at the scanf documentation:
https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm
Good luck
I'm writing a program to input book information using typedef and function.
Here is my declaration using typedef:
typedef struct {
char name[1000], author[1000], publisher[1000], description[1000], ISBN[15];
} book;
Here is the function used to add book info:
void addBook(int* n, book list[1000]) {
printf("Enter number of book you want to add: ");
fpurge(stdin);
scanf("%d", n);
int i;
for (i = 0; i < *n; i++) {
printf("Book title: ");
fpurge(stdin);
gets(list[i].name);
printf("Book author: ");
fpurge(stdin);
gets(list[i].author);
printf("Publisher: ");
fpurge(stdin);
gets(list[i].publisher);
printf("Description: ");
fpurge(stdin);
gets(list[i].description);
printf("ISBN: ");
fpurge(stdin);
gets(list[i].ISBN);
}
}
And the final is main:
int main(int argc, char** argv) {
int n, list[1000];
addBook(&n, list);
return (EXIT_SUCCESS);
}
So when I tried to run, it worked. However, the compiler showed me two warning:
warning: passing argument 2 of 'addBook' from incompatible pointer type [-Wincompatible-pointer-types]
expected 'book *' but argument is of type 'int'
My question is: Are these warnings considered as errors? If yes, what is the correct solution? If no, why the compiler showed it?
P/s: I use Netbean IDE.
Are these warnings considered as errors? I
In C most every warning if ignored leads to more or less fatal behaviour sooner or later. In may such cases the infamous Undefined Behaviour is invoked, which means that from that moment on anything can happen. The code might work, or not, sometimes only, or just Mondays or ...
So take these warnings serious and fix your code accordingly.
To do so change
int n, list[1000];
to be
int n;
book list[1000];
Are these warnings considered as errors? If yes, what is the correct solution? If no, why the compiler showed it?
You should treat warnings as errors, really. Why? The compiler today might issue a warning for some unsafe operation, but the next version of the compiler might treat it as an error.
A warning would also typically denote you're performing some unsafe or undefined operation - the fact it works just means you got lucky. So: treat warnings as errors.
I suspect the reason it worked was because you happened to allocate a pointer to some memory and you just got lucky that it worked.
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.
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
I am a newbie to C Programming and I am learning to pass a struct as a parameter to a function (as part of my course) by value. I am using gcc ver 4.6.3 on Ubuntu Linux 12.04LTS
The following is the source code which seems logically and syntactically correct (to me) but I get errors when compiling it:
#include<stdio.h>
struct sal {
char name[30];
int no_of_days_worked;
int daily_wage;
};
typedef struct sal Sal;
void main()
{
Sal salary;
int amount_payable;
salary=get_data(salary); //Passing struct as function arguments
printf("\nThe name of the Employee is %s",salary.name);
printf("\nNumber of days worked is %d",salary.no_of_days_worked);
printf("\nThe daily wage of the employees is %d",salary.daily_wage);
amount_payable=wages(salary);
printf("\nThe amount payable to %s is %d",salary.name,amount_payable);
}
Sal get_data(Sal income)
{
printf("\nEnter the name of the Employee: \n");
scanf("%s",&income.name);
printf("\nEnter the number of days worked:\n");
scanf("%d",&income.no_of_days_worked);
printf("\nEnter the employee daily wages:\n");
scanf("%d",&income.daily_wage);
return(income); //Return back a struct data type
}
int wages(Sal x)
{
int total_salary;
total_salary=x.no_of_days_worked*x.daily_wage;
return(total_salary);
}
On compiling the code I get the following errors:
struct_to_function.c: In function ‘main’:
struct_to_function.c:15:7: error: incompatible types when assigning to type ‘Sal’ from type ‘int’
struct_to_function.c: At top level:
struct_to_function.c:22:5: error: conflicting types for ‘get_data’
struct_to_function.c:15:8: note: previous implicit declaration of ‘get_data’ was here
struct_to_function.c: In function ‘get_data’:
struct_to_function.c:25:1: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[30]’ [-Wformat]
I think it has some thing to do with the implementation or execution plan of the gcc compiler whether the compiler is using a stack or registers. Again these are just my amateurish assumptions.
When the C compiler encounters the call to get_data from main, it has no idea what the return type is (since it has seen neither a function declaration nor a function definition), so it assumes int. This gives you the first warning, because salary is incompatible with int in the assignment. The compiler keeps going, now thinking that get_data returns int, and then it complains when it encounters the actual definition of get_data.
You should either add a function prototype before main, or make sure that functions are always defined before being called (by rearranging their order in the source code).
The final warning is because the scanf with a %s specifier is expecting a char*, but you gave it something of type char (*)[30]. Leave off the & when passing an array.
Just add the following before main:
Sal get_data(Sal income);
int wages(Sal x);
You have to pass a pointer to the structure. When you try to pass the structure itself, the C compiler tries to make a copy of it, but it doesn't know how to do that (you would need to use C++ to be able to define that) so it's an error.
You didn't declare the functions before you used them, so the compiler created it's own default definition for you. You have to declare a function before you reference it.
Also, it's bad practice to pass the structure by value and then modify it and pass it back. Better to just pass the pointer to the object you want to modify.
So:
int wages( Sal x );
void get_data( Sal* income );
void main()
{
Sal salary;
int amount_payable;
get_data( &salary ); //Passing struct as function arguments
// print stuff
amount_payable = wages( salary );
// print stuff
}
void get_data( Sal* income )
{
printf( "\nEnter the name of the Employee: \n" );
scanf( "%s", income->name );
printf( "\nEnter the number of days worked:\n" );
scanf( "%d", &(income->no_of_days_worked) );
printf( "\nEnter the employee daily wages:\n" );
scanf( "%d", &(income->daily_wage) );
}
int wages( Sal x )
{
int total_salary;
total_salary = x.no_of_days_worked * x.daily_wage;
return total_salary;
}