C Insert int and doubles inside structure - c

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

Related

Dynamically allocating an array of struct inside a function

I cannot understand what's wrong with my c implementation of: dynamically allocating an array of struct inside a function to use with in other functions.
The problem is my .exe stops working after reading the first struct(which is read correctly).
The struct:
struct student
{
char name1[30], name2[30];
float grade;
};
The function:
void read(int *n, struct student **a)
{
if(scanf(" %d", n) == 1)
{
int i;
*a=(struct student*)malloc((*n)*sizeof(struct student*));
for(i=0; i<*n; i++)
scanf("%29s %29s %f",(*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);
//it stops working right after this line is executed
}
}
Main:
int main()
{
int n;
struct student *a;
read(&n, &a);
return 0;
}
Warrnings:
format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[30]' [-Wformat=]|
format '%s' expects argument of type 'char *', but argument 3 has type 'char (*)[30]' [-Wformat=]|
Using a+i instead of a[i] doesn't change anything. I am aware &(*a) means a, but i wanted to make everything as clear as possible. I feel like there's something obviously wrong about my dynamic allocation that i'm missing. I read so many questions here, but nothing appears to solve my problem. Thanks for your time!
EDIT 1: i changed the code to the suggestions:
scanf("%29s %29s %f", a[i].name1, a[i].name2, a[i].grade);
and now i get the error below instead.
Error:
error: request for member 'name1' in something not a structure or union
EDIT 2: so, the line:
scanf("%29s %29s %f",*a[i].name1, *a[i].name2, *a[i].grade);
gives the error:
request for member 'name1' in something not a structure or union
and the line:
scanf("%29s %29s %f",(*a)[i].name1, (*a)[i].name2, (*a)[i].grade);
crashes.
EDIT 3:
scanf("%29s %29s %f", (*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);
works.
Here
*a=(struct student*)malloc((*n)*sizeof(struct student*));
^^^^^
you allocate space for *n pointers to struct student but it seems that you really want to allocate space for *n struct student.
It seems you want:
*a=malloc((*n)*sizeof(struct student));
Also notice that *a[i] is the same as *(a[i]) but you probably want (*a)[i]. So you need something like:
scanf("%29s %29s %f", (*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);
Notice that you need & in front of (*a)[i].grade but not the other two places because the two two other are arrays.
As mention by #unwind in a comment: The scanf is wrong
This
scanf("%d",&(*n));
should be
scanf("%d", n);
and then you should also check the return value, like
if (scanf("%d", n) != 1)
{
// Add error handling here
....
}

Program crashes when reading first data point

I want to see what student have the best mark in the class.
So I make this ,but i don't know where I am wrong
struct Date {
char name[31];
float mark;
};
struct Date * Read(unsigned int n,struct Date *d){
int i;
for(i=0;i<n;i++){
getchar();
fgets(d[i].name, 31, stdin);
scanf("%f",d[i].mark);
}
return d;
}
int main(){
unsigned int n;
struct Date *d;
scanf("%u",&n);
d = (struct Date*) malloc(n*sizeof(struct Date));
d=Read(n,d);
free(date);
return 0;
}
after i read the mark the program crash.
Can someone help me and explain what to change?
Thanks a lot.
The crash is most likely due to this:
scanf("%f",d[i].mark);
You should pass the address as argument to read a float value. It should be:
scanf("%f", &d[i].mark);
Technically, this is undefined behaviour..
Compile with all warnings enabled. gcc warns even without any specific options:
warning: format %f expects argument of type âfloat *â, but argument 2 has type double [-Wformat=]
scanf("%f",d[i].mark);

Returning structure from function

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

Scanf Seg Fault

I'm working on my assignment for my C course, and I'm trying to take in the user's input and store it in a variable to use for later in my code. Here's what my main function looks like,
int main() {
// Variables here
char* inputLine[10];
do {
printf("Insert number....");
scanf("%s\n", inputLine);
// More stuff here
}
return 0;
}
This code gives me a bunch of warnings, warning: format specifies type 'char *' but the argument has type 'char **' [-Wformat], and if I change the variable declaration to,
char* inputLine = NULL;
When I execute my code I get a seg fault, can someone explain to me what I am doing wrong, and the differences of what happens in the memory when I'm initializing this variable?
char* inputLine[10];
--> is an array of ten pointers to char
printf's format %s expects argument of type char *, but you're providing it as type char **
Just use
char inputLine[10];
To avoid possible buffer overflow you should use
scanf("%9s", inputLine); //Notice the size with %s
9 only because C string are null terminated ('\0') so one extra byte for it goes at end
char inputLine[10];
do {
printf("Insert number....");
scanf("%9s\n", inputLine);
// More stuff here
} while( //some condition);
However if you edit your code and remove * you get answer, but normal array deprecated, nowdays, programmers use vector, normal array in C not safe :
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<string> inputLine;
You can define with every data type:
vector<int> myvar;
Or you can define multidimensional vector:
vector< vector <int> > myvar;

problem with gets()

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.

Resources