Can't read array of structure in C - c

I am trying to read members of an object like in the code below.
The issue is that the code can't read the second member (car[i].model) in the array and the third one (car[i].price), only the first one (car[i].manufacturer).
#include <stdio.h>
#include <conio.h>
struct machine
{
int price;
char manufacturer[30];
char model[30];
};
int main()
{
int i = 0, n;
printf("Introduce number of cars: ");
scanf_s("%d", &n);
struct machine car[100];
for (i = 0; i < n; i++)
{
printf("Data of the car nr. %d:\n", i+1);
printf("Manufacturer: ");
scanf_s("%s", car[i].manufacturer);
printf("Model: ");
scanf_s("%s", car[i].model); printf("\n");
printf("Price: ");
scanf_s("%d", &car[i].price); printf("\n");
}
for (i = 0; i < n; i++)
{
printf("Data of the car nr. %d:\n", i + 1);
printf("Manufacturer: %s\n", car[i].manufacturer);
printf("Manufacturer: %s\n", car[i].manufacturer);
printf("Model: %s\n", car[i].model);
printf("Price %d\n", car[i].price);
}
_getch();
}

scanf_s requires the buffer size to be specified for input parameters with format %s. The buffer size includes the terminating null. Adapt your code like this:
struct machine
{
int price;
char manufacturer[30];
char model[30];
};
struct machine car[100];
....
scanf_s("%s", car[i].manufacturer, 30 );
// ^^ buffer size
....
scanf_s("%s", car[i].model, 30 );
// ^^ buffer size
....
scanf_s("%d", &car[i].price); // no buffer size

Related

take full name and birthday as input to struct in C

I have to write program that takes from the user, his full name, number, and his birthday and put them in structure.
then I have to sort the inputs by birthday and display them to the screen.
the problem is when I enter the first Full Name the program crash and doesn't get any full name further.
this what I have approach to so far...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct ZNAK{
char full_Name[100];
int number;
int bday[3];
};
int Compare(const void *s1, const void *s2){
struct ZNAK *e1 = (struct ZNAK *)s1;
struct ZNAK *e2 = (struct ZNAK *)s2;
int res = memcmp(e1->bday, e2->bday, 3);
if(res < 1){
return e1->bday - e2->bday;
}
}
int main(){
struct ZNAK arr[4];
for(int i=0; i<4; i++){
printf("\nenter Full Name: ");
fgets(arr[i].full_Name, 100, stdin);
printf("\nEnter Phone Number: ");
scanf("%d", &arr[i].number);
printf("Enter Birth Day: ");
scanf("%d %d %d", &arr[i].bday[0], &arr[i].bday[1], &arr[i].bday[2]);
}
qsort(arr, 4, sizeof(struct ZNAK), Compare);
char last_name[50];
printf("enter the last name: ");
scanf("%s", last_name);
for (int x=0; x<4; x++){
printf("First Name: %s\n", arr[x].full_Name);
printf("Phone Number: %d\n", arr[x].number);
printf("Birth Day: %d %d %d\n", arr[x].bday[0],arr[x].bday[1],arr[x].bday[2] );
}
}

Why can't I print all the character types of variables in array?

#include <stdio.h>
#include <conio.h>
int main() {
char name[20];
int age[20], i, size;
printf("Enter number of students: ");
scanf("%d", &size);
for (i = 0; i < size; i++)
{
printf("\nEnter Student # %d name: ", i+1 );
scanf("%s", &name[i]);
printf("\nEnter Student # %d age: ", i+1 );
scanf ("\n%d", &age[i]);
}
printf("---");
printf("\n Student Information");
for (i = 0; i < size; i++)
{
printf("\nStudent # %d :\n", i+1);
printf("Name: %c", name[i]); //how do i print the array here?
printf("\nAge: %d", age[i]);
}
return 0;
}
For some reason, I can't display the whole characters that are inputted, and instead, my program produces nothing. What's causing this and how can I fix it?
starboy_b already answered your question, but I want to highlight security issues in your code:
Keep in mind that using scanf to get input like you do is introducing dangerous vulnerabilities to your program.
Why? :
scanf does not know how much allocated space your variables have and does not prevent the user from entering more characters than your buffer can contain. This lead to buffer overflow and can be used to run attacker code.
Your better off e.g. using readline or fgets to get input from user.
#include <stdio.h>
#include <conio.h>
int main() {
char name[20][100];
int age[20], i, size;
printf("Enter number of students: ");
scanf("%d", &size);
for (i = 0; i < size; i++)
{
printf("\nEnter Student # %d name: ", i+1 );
scanf("%s", &name[i]);
printf("\nEnter Student # %d age: ", i+1 );
scanf ("\n%d", &age[i]);
}
printf("---");
printf("\n Student Information");
for (i = 0; i < size; i++)
{
printf("\nStudent # %d :\n", i+1);
printf("Name: %s", name[i]); //how do i print the array here?
printf("\nAge: %d", age[i]);
}
return 0;

Structures and arrays in C

I must create a program focusing on the use of structures.
The program will ask the user to enter the number of students for whom he will later add specific information (name, surname, average grade).
For some reason, when I start the the program, I enter the number of students i want, after that I enter the info of the first student and then the program terminates.
Here's what I've tried.
#include <stdio.h>
#include <stdlib.h>
struct student
{
char *name;
char *surname;
float *average;
};
void inputs(struct student *a, int size);
int main()
{
int size;
printf("Enter the number of students: ");
scanf("%d", &size);
struct student *data;
data = (struct student *)malloc(size*sizeof(struct student));
if(data==NULL) {
printf("Cannot allocate memory. The program will now terminate.");
return -1;
}
inputs (data, size);
return 0;
}
void inputs(struct student *a, int size)
{
int j=0;
int i;
for(i=0; i<size; i++) {
printf("Enter the name of the student number %d: ", j+1);
scanf("%s", a->name);
printf("Enter the surname of the student number %d: ", j+1);
scanf("%s", a->surname);
printf("Enter the average grade of the student number %d: ", j+1);
scanf("%f", a->average);
j++;
a++;
}
}
This code works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
char name[30];
char surname[30];
float average;
};
void inputs(struct student *a, int size);
int main()
{
int size;
int i=0; // we need i
char string[100];
printf("Enter the number of students: ");
// scanf can be tricky lets use fgets
fgets( string , 99 , stdin );
size= atoi(string);
struct student **data; // array of struct
// get memory for the pointers to pointer
data=(struct student **) calloc( size , sizeof(char *));
// now each struct need space
for( i=0 ; i<size ; i++)
{
data[i] = malloc(sizeof(struct student));
if(data[i]==NULL) {
printf("Cannot allocate memory. The program will now terminate.");
return -1;
}// end if
}// end for loop
// input each student
for( i=0 ; i<size ; i++)
inputs (data[i], i );
return 0;
}
void inputs(struct student *a, int num)
{
int j=0;
char string[100];
// scanf can be tricky lets use fgets
printf("Enter the name of the student number %d: ", num+1);
fgets(a->name, 29, stdin);
printf("Enter the surname of the student number %d: ", num+1);
fgets( a->surname , 29, stdin);
printf("Enter the average grade of the student number %d: ", num+1);
fgets( string , 99, stdin);
a->average=atof(string);
}

Segmentaiton fault when function is called to input a double into a member of a array, previous input works

For a class assignment in C, I was tasked with writing a program that creates a struct with 4 members, first name, last name, hours, and payrate, after its created, it inputs the user to input the 4 members 3 times, so we have 3 employees. when the program is run, I can input the first and last and hours of the first employee but when it comes to input for the payrate this causes a segmentation fault. Here is my code
#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
struct employee
{
char first[30];
char last[30];
double hours;
double payrate;
};
typedef struct employee emp;
int main(void)
{
system("clear");
emp emp[SIZE];
int counter;
for (counter = 0; counter < 3; counter++)
{
input(&emp[counter]);
}
for (counter = 0; counter < 3; counter++)
{
output(emp[counter]);
}
printf("%10s %10s %10s %10s", "First", "Last", "Hours", "Rate");
puts("------------------------");
for (counter = 0; counter < SIZE; counter++)
{
printf("%s %s %d %d \n", emp[30].first, emp[30].last, emp[10].hours, emp[10].payrate);
}
return 0;
}
void output(struct employee emp)
{
printf("First: %s \n", emp.first);
printf("Last: %s \n", emp.last);
printf("Hours: %d \n", emp.hours);
printf("Payrate: %d \n", emp.payrate);
puts("********************************");
}
void input(emp * ptr)
{
printf("Enter first name: ");
scanf("%s", ptr->first);
printf("Enter last name: ");
scanf("%s", ptr->last);
printf("Enter hours worked: ");
scanf("%d", ptr->hours);
printf("Enter payrate: ");
scanf("%d", ptr->payrate);
puts("********************************");
}
Edit#1 I edited some code and it works until the part of the table, it now works but gives out a 0.0000 in the first two colums of the table, here the edited code.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
struct employee
{
char first[30];
char last[30];
double hours;
double payrate;
};
typedef struct employee emp;
int main(void)
{
system("clear");
emp emp[SIZE];
int counter;
for (counter = 0; counter < SIZE; counter++)
{
input(&emp[counter]);
}
for (counter = 0; counter < SIZE; counter++)
{
output(emp[counter]);
}
printf("%10s %10s %10s %10s", "First", "Last", "Hours", "Rate");
puts("\n ------------------------");
for (counter = 0; counter < SIZE; counter++)
{
printf("%s %s %lf %lf \n", emp[30].first, emp[30].last, emp[10].hours, emp[10].payrate);
}
return 0;
}
void output(struct employee emp)
{
printf("First: %s \n", emp.first);
printf("Last: %s \n", emp.last);
printf("Hours: %f \n", emp.hours);
printf("Payrate: %f \n", emp.payrate);
puts("********************************");
}
void input(emp * ptr)
{
printf("Enter first name: ");
scanf("%s", ptr->first);
printf("Enter last name: ");
scanf("%s", ptr->last);
printf("Enter hours worked: ");
scanf("%lf", &ptr->hours);
printf("Enter payrate: ");
scanf("%lf", &ptr->payrate);
puts("********************************");
}
The first problem is that the second argument to scanf should be a pointer. In the case of your strings, they are arrays and basically treated as pointers anyway so they work fine. You need to use the & operator to give it the address of the doubles. The next problem is that the conversion specifier "%d" is for signed integer conversion. For a double, use "%lf" since a double is a long float.
Example:
scanf("%lf", &ptr->hours);

I'm trying to create a program with a loop that prompts the user to enter data in the array elements

I'm trying to create a program with a loop that prompts the user to enter data in the array elements. And when the user no longer can enter data, print to screen the data entered in a last in, first out order.
And this is my attempt...
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age info)
{
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main()
{
int size = 0, i = 0, j = 0;
struct Name_Age * array_ptr = (struct Name_Age*)malloc((size + 1)* sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
scanf("%d\n", size);
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s\n", myInfo.Name);
printf("Enter Age: \n");
scanf("%d\n", myInfo.Age);
}
printMe(myInfo);
return 0;
};
First, scanf("%d", &size) replace scanf("%d\n", size), put &size instead of size as argument(You need an address), and put the malloc things after this line of code, because you need an exact size value before malloc. Same thing with all the scanf stuffs.
As you want to print out all your input names and ages in order, I changed your code like this:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *infoList, int size)
{
int i;
for (i = size-1; i >= 0; --i)
{
printf("Name: %s\n", infoList[i].Name);
printf("Age: %d\n", infoList[i].Age);
printf("\n");
}
}
int main()
{
int size, i;
printf("Enter size of array: ");
scanf("%d", &size);
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size* sizeof(struct Name_Age));
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);
}
printMe(array_ptr, size);
return 0;
}
Try to test and compare with your code, questions are welcome.
You can use fgets to read strings and cast the string to digits with atoi. The storage is not complete, but with my changes you can read to structs and specify the size of the loop (TODO: Save a list of structs so that you actually can print a list of structs that you have specified.)
#include <stdio.h>
#include <stdlib.h>
struct Name_Age {
char Name[10];
int Age;
};
void printMe(struct Name_Age info) {
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main() {
int size = 0, i = 0, j = 0;
struct Name_Age *array_ptr = malloc((size + 1) * sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
char tmp[10];
fgets(tmp, 10,stdin);
size = atoi(tmp);
for (i = 0; i < size; ++i) {
printf("Enter Name: ");
fgets(myInfo.Name, 10,stdin);
printf("Enter Age: ");
fgets(tmp, 10,stdin);
myInfo.Age = atoi(tmp);
}
printMe(myInfo);
return 0;
};
Test
$ ./a.out
Enter size of array: 2
Enter Name: Superman
Enter Age: 25
Enter Name: Batman
Enter Age: 27
Name: Batman
Age: 27
See also this question about fgets fgets how to read int
Obviously using fgets() is a much better approach, but making the fewest amount of changes as possible to your code and still achieving your result is the following:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *info);
int main(void)
{
int size, i;
struct Name_Age *array_ptr;
printf("Enter size of array: ");
scanf("%d", &size);
array_ptr = malloc(size * sizeof *array_ptr);
for (i = 0; i < size; ++i)
{
printf("Enter Name: ");
scanf(" %s", array_ptr[i].Name);
printf("Enter Age: ");
scanf("%d", &array_ptr[i].Age);
printf("\n");
}
for (i = 0; i < size; ++i)
printMe(&array_ptr[i]);
return 0;
}
void printMe(struct Name_Age *info)
{
printf("Name: %s\n", info->Name);
printf("Age: %d\n", info->Age);
}
Note that passing the struct by pointer to the function should be faster, note that you don't need the myInfo struct; you can just directly modify the elements of the array. Note the space before %s in the scanf() line, this is to discard any whitespace (including \n), this is done automatically for %d so it is only necessary for your strings (technically not the first iteration of the loop, but it doesn't fail if no whitespace is found). If you have any questions about why I made the changes I did, please feel free to comment on this answer!
example of fix
//struct Name_Age myInfo = *array_ptr;//Not necessary
printf("Enter size of array: ");
scanf("%d", &size);//remove `\n`, add `&`
//To ensure after the size has been determined
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size * sizeof(struct Name_Age));//Cast is not necessary in C
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);//remove `\n`
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);//need `&`
}
for (i = 0; i < size; ++i)
printMe(array_ptr[i]);

Resources