Wrong int values using struct and arrays [duplicate] - c

This question already has answers here:
What will happen if '&' is not put in a 'scanf' statement?
(6 answers)
Closed 4 years ago.
Hello I have a problem with integer. This is my code:
#include <stdio.h>
#include <stdlib.h>
struct data
{
char name[50];
int grade[1];
};
int main()
{
struct data persons[30];
int n = 3;
int i;
for(i=0;i<n;i++)
{
printf("Type person name nr: [%d] ",i+1);
scanf("%s",persons[i].name);
printf("Type grade: (from 1 to 6) ");
scanf("%d",persons[i].grade);
}
for(i=0;i<n;i++)
{
printf("Name [%d]: %s\n",i+1,persons[i].name);
printf("Grade [%d]: %d\n",i+1,persons[i].grade);
}
return 0;
}
And when I type some names and grades the output isn't correct:
This is my output

You are using an array for a single grade, when a standard int is enough.
struct data
{
char name[50];
int grade;
};
And then you also need to pass the reference of the int to scanf using an &.
scanf("%d", &persons[i].grade);

The corrected version of your program:
#include <stdio.h>
#include <stdlib.h>
struct data {
char name[50];
int grade; // In you case, to store one integer value just use int varibale because it seems more logical.
};
int main() {
struct data persons[30];
int n = 3;
int i;
for (i = 0; i < n; i++) {
printf("Type person name nr: [%d] ", i + 1);
scanf("%s", persons[i].name);
printf("Type grade: (from 1 to 6) ");
scanf("%d", &persons[i].grade); // To fill member of structure you may use '&' sign because scanf gets address.
}
for (i = 0; i < n; i++) {
printf("Name [%d]: %s\n", i + 1, persons[i].name);
printf("Grade [%d]: %d\n", i + 1, persons[i].grade);
}
return 0;
}
Also, keep in mind that compiler not always tell you that something is going to be wrong, in most cases using special flags (some of them I mentioned in the comment) for compiler can give you more information.
It's worth to note that current IDEs highlight obvious errors and really speed up your development process.

It's because grade is an array, so you need to do .grade[0]when writing or reading data to / from it, like so:
scanf("%d",persons[i].grade[0]);
...
printf("Grade [%d]: %d\n",i+1,persons[i].grade[0]);

you have to replace
printf("Grade [%d]: %d\n",i+1,persons[i].grade);
by
printf("Grade [%d]: %d\n",i+1,persons[i].grade[0]);
in the scanf you do scanf("%d",persons[i].grade); so because grade is a vector you give its address, but in the printf you have to specify the index else you print the address of the vector
However to use a vector is useless because it contains only one element, better to directly use an int for grade, and of course in that case you have to give &persons[i].grade for the scanf and persons[i].grade for
the printf
Execution :
Type person name nr: [1] a
Type grade: (from 1 to 6) 1
Type person name nr: [2] b
Type grade: (from 1 to 6) 2
Type person name nr: [3] c
Type grade: (from 1 to 6) 3
Name [1]: a
Grade [1]: 1
Name [2]: b
Grade [2]: 2
Name [3]: c
Grade [3]: 3

Related

Why does this array of structures overwrite char * but not int? [duplicate]

This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 1 year ago.
I have written a program which makes use of array of structures in order to maintain a sort of "database" program with different options that can be used to manipulate the "database".
The program has 4 modes of operation, if the user enters:
'i' data can be inserted into the "database".
's' searches the "database" for a part with a part number of a item.
'u' updates something in the database based on the part number of a item.
'p' prints the whole "database".
Here is the code which is made of 3 files:
database.h:
#ifndef DATABASE
#define DATABASE
struct db
{
int part_number;
char *part_name;
int part_quantity;
};
extern struct db database[50];
extern void insert(int i);
extern int search(int i);
extern int update(int i);
extern int print(int i);
#endif
database.c
#include <string.h>
#include <stdio.h>
#include "database.h"
struct db database[50];
void insert(int i)
{
char name_of_part[21], c;
printf("%p\n", &database[i].part_name);
printf("\n");
printf("Enter a part number: ");
scanf("%d", &database[i].part_number);
while((c = getchar()) != '\n' && c != EOF); // flush stdin
printf("Enter a part name: ");
fgets(name_of_part, 20, stdin);
printf("Enter quantity of part: ");
scanf("%d", &database[i].part_quantity);
database[i].part_name = name_of_part;
printf("\n");
}
int search(int i)
{
int input;
printf("\n");
printf("Enter a part number: ");
scanf("%d", &input);
for (int j = 0; j <= i; j++)
{
if (database[j].part_number == input)
{
printf("Part name: %s\n", database[j].part_name);
printf("Quantity on hand: %d\n", database[j].part_quantity);
return 0;
}
}
printf("Part not found.\n");
}
int update(int i)
{
int input, quantity;
printf("\n");
printf("Enter part number: ");
scanf("%d", &input);
for (int j = 0; j <= i; j++)
{
if (database[j].part_number == input)
{
printf("Enter part quantity: ");
scanf("%d", &quantity);
database[j].part_quantity = quantity;
return 0;
}
}
printf("Part number not found.");
}
int print(int i)
{
for (int j = 0; j < i; j++)
{
printf("Part number: %d\n Part name: %s\n Part quantity: %d\n", database[j].part_number, database[j].part_name,database[j].part_quantity);
}
}
main.c
#include <stdio.h>
#include <string.h>
#include "database.h"
int main()
{
int i = 0;
char code;
while (1)
{
printf("Enter a function code: ");
scanf(" %c", &code);
switch (code)
{
case 'i':
insert(i);
i += 1;
break;
case 's':
search(i);
break;
case 'u':
update(i);
break;
case 'p':
print(i);
break;
}
}
return 0;
}
The problem i have is that when i insert into the "database", the name in each structure gets overwritten. for example:
Enter a function code: i
Enter a part number: 111
Enter a part name: 111
Enter quantity of part: 111
Enter a function code: i
Enter a part number: 222
Enter a part name: 222
Enter quantity of part: 222
Enter a function code: p
Part number: 111
Part name: 222
Part quantity: 111
Part number: 222
Part name: 222
Part quantity: 222
Enter a function code:
As you can see first i insert something new in the "database", take note of the "Part name" which is "111".
Next i insert something else into the database
this time the "Part name" is "222".
Lastly i print the whole "database" what i am confused about is why the part name has now overlapped. but why is this? all the other members such as the part_number and part_quantity remain intact in both insert operations so why does char *part_name stay the same ? and how do i fix this ?
You have the part_name member declared as a char * and you assign to it the address of a local array in the insert function. When the function returns, that array goes out of scope and the stored pointer becomes invalid. Subsequently trying to use that pointer triggers undefined behavior.
Change part_name to be an array:
struct db
{
int part_number;
char part_name[21];
int part_quantity;
};
And write directly to that:
printf("Enter a part name: ");
fgets(database[i].part_name, 21, stdin);
The line
database[i].part_name = name_of_part;
is bad. This is assigning a pointer to the non-static local variable. The variable ends its life on returning from the function and dereferencing pointers pointing to that is illegal.
Instaed of this, you have to copy the string. If you system supports strdup(), it can be done like this:
database[i].part_name = strdup(name_of_part);
If strdup() is not supported or you want to stick to the standard, you dan do like this:
database[i].part_name = malloc(strlen(name_of_part) + 1); /* +1 for ther terminating null-character */
if (database[i].part_name != NULL)
{
strcpy(database[i].part_name, name_of_part);
}
Add #include <stdlib.h> to use malloc().

Introduce a number of students from keyboard and theirs marks

I need to introduce a no. of students , theirs name, surname and marks(3 marks). The average of the marks must be made, and then those who have passed must be displayed in the reverse order of their insertion.The problem is that, for example, i have 3 students i need to introduce 4 times in the structure to show me the result, and i need to have one after another, not with spaces or something else. Someone who can help me? Thanks!
#include <stdio.h>
#include <stdlib.h>
struct students
{
char name[100];
char surname[100];
float a,b,c;
};
int main()
{
int n,i,j;
scanf("%d",&n);
struct students s[n];
for(i=1;i<=n;i++)
{
scanf("\n%s %s %f %f %f\n",s[i].name,s[i].surname,&s[i].a,&s[i].b,&s[i].c);
}
for(j=n;j>=1;j--)
{
float m;
m=(s[j].a+s[j].b+s[j].c)/3;
if(s[j].a >= 5 && s[j].b >= 5 && s[j].c >= 5 && m >= 6)
{
printf("%s %s %.2f\n", s[j].name, s[j].surname, m);
}
}
return 0;
}
The problem is that you have an array of structures and you are indexing them wrongly.
Given you have n = 3, then you have an array of 3 structures indexed 0, 1 and 2.
First you need to change your structure reading for loop to this
for(i=0;i<n;i++) {
scanf("\n%s %s %f %f %f\n",s[i].name,s[i].surname,&s[i].a,&s[i].b,&s[i].c); }
For your next for loop, you need to change it to this
for(j=n - 1;j>=0;j--)
Hope this helps

Not an Expected Result Loop of a Structure in c [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I am working on a simple C program which is to create a loop of a structure.
So I have a structure of a Students with name, age, and grade.
So the output will be something like this:
Enter name of student 1:
Enter age of student 1:
Enter Grade of student 1:
Enter name of student 2:
Enter age of student 2:
Enter Grade of student 2:
But after I input the grade of Student 1, it skipped The name of student 2 so I got this instead:
Enter name of student 1:
Enter age of student 1:
Enter Grade of student 1:
Enter name of student 2: Enter age of student 2:
And I am using DevC++, here is my code:
#include <stdio.h>
struct student {
char name[50]; // declare name using array
int age;
int grade;
};
int main ()
{
struct student info[3]; //declare 3 students [3]
int i;
for(i=1;i<=3;i++) { // this is for the looping, student 1, student 2, student 3
printf("Enter name for student %d : ",i);
scanf("%s",info[i].name); // called struct using "." (dot)
printf("Enter age for sudent %d : ",i);
scanf("%d",&info[i].age);
printf("Enter grade for student %d : ",i);
scanf("%d",&info[i].grade);
}
return 0;
}
Can someone find what is wrong with my code? or please help a suggestion to solve this problem to get the expected result.
Multiple suggestions of your code:
When using scanf to input data, always check its return value to make sure sufficient data is input correctly, for example, when you input B for the int grade field, it returns zero instead of one:
int r = scanf("%d", &info[i].grade);
printf("%d\n", r); // 0
Also as said in the comments, when you input strings try use fgets, because it is more secure and will not stop at spaces. scanf does not check for buffer overflow.
Also, in your for loop, you are accessing out of bounds of the array info, you have to start from 0.
Try the following:
int main ()
{
struct student info[3]; //declare 3 students [3]
int i;
int r;
for(i=0; i < 3; i++) {
printf("Enter name for student %d : ",i);
fgets(info[i].name, 50, stdin);
printf("Enter age for sudent %d : ",i);
r = scanf("%d", &info[i].age);
if (r < 1) {
printf("input error, exiting\n");
return 1;
}
printf("Enter grade for student %d : ",i);
r = scanf("%d", &info[i].grade);
if (r < 1) {
printf("input error, retry\n");
return 1;
}
}
return 0;
}
I Tried your code and it work succesfully, I tried to compare it with what you have done.
And The result is you declare scanf("%d",&info[i].grade);
which is received an integer input. but when I see your picture your Input was a Character
So Just Change Your Input with an Integer on Enter grade for student i
To expand on the answer by Serafin: (Good catch, BTW!)
When you input a non-number into your scanf call,
printf("Enter grade for student %d : ",i);
scanf will fail to read the input (see comment by hyde, thanks)
scanf will skip all inputs that don't match the input pattern provided until it hits newline. Anything that was not matched read remains in the input buffer. Therefore, the subsequent call to scanf receives the old content from the previous input, which does get matched in this case.
grade is int but you type a char ('B', It's like 8 :D), I modity three line:
#include <stdio.h>
struct student {
char name[50]; // declare name using array
int age;
char grade; // int -> char
};
int main ()
{
struct student info[3]; //declare 3 students [3]
int i;
for(i=1;i<=3;i++) { // this is for the looping, student 1, student 2, student 3
printf("Enter name for student %d : ",i);
scanf("%s",info[i].name); // called struct using "." (dot)
printf("Enter age for sudent %d : ",i);
scanf("%d",&info[i].age);
getchar(); // reade '\n' after type age
printf("Enter grade for student %d : ",i);
scanf("%c",&info[i].grade); // %d -> %c
}
return 0;
}

C: Array of Structs (Input into int array within array of structs)

Hi I have to create a database that stores students number, name and also stores an array of course marks (1-N) in C Programming Language.
Everything worked until I started coding for the array of course marks. Then every time I compiled the code it kept crashing as soon as it asked to input the course marks.
Can you please tell me where I'm going wrong in my programming for this task? I have attached it to this message.
The program worked for inputting the name, student number, however I could not get the program to input array of marks. I have asked how many course marks to be entered and then used a for loop within the "void insert(void)" function to keep inputting the course marks into the array *marks. I am referring specifically to lines 24 to 30 in my programming code.
Always at this point the program kept crashing and I could not proceed further to enter more names or print the stored student details.
I think there is a problem with this part:
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n");
scanf("%d", &(list[num_students].marks[num_marks]));
}
Anyway here is the full code:
#include <stdio.h>
#include <string.h>
struct student{
int number;
char name[10];
int marks[5];
};
struct student list[10];
int num_students = 0;
int num_marks = 0;
int *p;
void insert(void)
{
int student_number;
int i;
printf("Enter number: \n");
scanf("%d", &list[num_students].number);
printf("Enter NAME: \n");
scanf("%s", &list[num_students].name);
printf("Enter NO of courses: \n");
scanf("%d", num_marks);
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[num_marks]));
}
num_students++; // HOW DO WE INPUT ARRAY MARKS??? MARK1: , MARK2: , MARK3 ,
}
void printtest(void)
{
int i;
for (i=0; i < num_students; i++)
{
printf("Name: \n");
puts(list[i].name);
printf("Number: %d \n", list[i].number);
printf("Mark: %d /100 \n", list[i].marks);
printf("\n");
}
}
int main(void)
{
int code;
int opt1;
int courses, i, k, j, counter;
for (;;){
printf("Enter operation code: \n");
printf("(1) ADD NEW STUDENT DETAILS: \n");
printf("(2) DISPLAY REPORT OF ALL STUDENTS: \n");
scanf(" %d", &code);
switch (code){
case 1 :
insert();
break;
case 2 :
printtest();
break;
default:
printf("Illegal code\n");
printf("\n");
}
}
}
Apart from what others pointed out, I'd like to draw your attention towards the following:
void insert(void)
{
int student_number;
int i;
printf("Enter number: \n");
scanf("%d", &list[num_students].number);
printf("Enter NAME: \n");
scanf("%s", &list[num_students].name);
printf("Enter NO of courses: \n");
scanf("%d", num_marks);
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[num_marks]));
}
num_students++;
}
void printtest(void)
{
int i;
for (i=0; i < num_students; i++)
{
printf("Name: \n");
puts(list[i].name);
printf("Number: %d \n", list[i].number);
printf("Mark: %d /100 \n", list[i].marks);
printf("\n");
}
}
There are three problematic statements:
scanf("%s", &list[num_students].name); This is why beginners should use compilers with all warnings enabled.
printf("Mark: %d /100 \n", list[i].marks); What did you declare marks as in the first place?
scanf("%d", num_marks); Seems like you put & operator where not needed and ignore where needed. Read your textbook before asking a question next time.
Seems like you're having a tough time understanding the concept of arrays and pointers. Read your text book thoroughly before venturing into the world of pointers. If you don't use them correctly, even compiler can't help you.
Also, even if I don't expect your program to have a robust input mechanism, at least array bounds checking is expected. Learn good habits from the beginning. They'll save a lot of your time while debugging later.
Seems to be an error in:
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[num_marks]));
}
The crash is probably because num_marks as index indexes beyond the array. Change to:
for (i= 0; i < num_marks; i++)
{
printf("Enter Course Mark: \n" );
scanf("%d", &(list[num_students].marks[i]));
}

Expression must have class type error

I'm working on a homework assignment and I've hit a brick wall. I think I have all of the code that I need, I just need to get the program to compile. The object of the assignment is
Create a structure to hold student names and averages. The structure should contain a first name, last name and an integer grade average.
Then:
Write a program that will do the following:
1.) Create an array of pointers to these student structures.
2.) Prompt the user for names and averages.
3.) After you get the student’s information use malloc to provide the memory to store the information.
4.) Place the address of the student, returned by malloc, into the pointer array.
5.) AFTER the user indicates there are no more students:
Search the data entered and find the highest and lowest grade
average.
a)Print the name and grade for the highest grade
b)Print the name and grade for the lowest grade
c)Print the average of all grades entered
Here is my code:
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#define SIZE 25
int enterStudents (int ePointArray[SIZE]);
void searchData (int *sPointArray, int *sHigh, int *sLow);
int calculateAvg (int, int *avgPointArray);
void printData (int, int *pHigh, int *pLow);
struct student
{
char firstName[20];
char lastName[20];
int average;
};
int main()
{
int pointArray[SIZE], high[3], low[3];
int i = 0, studentCounter, avgGrade;
for (i = 0; i < SIZE; i++)
pointArray[i] = 0;
studentCounter = enterStudents(pointArray);
searchData(pointArray, high, low);
avgGrade = calculateAvg(studentCounter, pointArray);
printData(avgGrade, high, low);
return 0;
}
int enterStudents (int ePointArray[SIZE])
{
char tempFname[20], tempLname[20], yesNo[2] = "y";
int tempAvg, counter = 0;
int *studPtr;
struct student aStud={"\0", "\0", 0};
while( counter < SIZE && strcmp(yesNo, "y")==0)
{
printf(" Enter first name: ");
scanf("%s", tempFname);
printf(" Enter last name: ");
scanf("%s", tempLname);
printf(" Enter grade average:");
scanf("%d", tempAvg);
strcpy(aStud.firstName, tempFname);
strcpy(aStud.lastName, tempLname);
aStud.average = tempAvg;
studPtr = malloc(sizeof(struct student));
ePointArray[counter] = *studPtr;
counter++;
printf("/n");
printf(" Do you have more students? yes or no:");
scanf("%s", yesNo);
}
return counter;
}
void searchData (int sPointArray[SIZE], int sHigh[3], int sLow[3])
{
int searchCounter = 0;
while( searchCounter = 0)
{
if( *sPointArray[searchCounter].average > *sPointArray[searchCounter+1].average)
{
sHigh[0] = &sPointArray[searchCounter].firstName;
sHigh[1] = &sPointArray[searchCounter].lastName;
sHigh[2] = &sPointArray[searchCounter].average;
}
if( *sPointArray[searchCounter].average < *sPointArray[searchCounter+1].average)
{
sLow[0] = &sPointArray[searchCounter].firstName;
sLow[1] = &sPointArray[searchCounter].lastName;
sLow[3] = &sPointArray[searchCounter].average;
}
searchCounter++;
}
}
int calculateAvg( int totalStudents, int avgPointArray[SIZE])
{
int sum = 0;
int avgCounter;
double overallAvg;
for( avgCounter = 0; avgCounter < totalStudents; avgCounter++)
sum = sum + *avgPointArray[avgCounter].average;
overallAvg = sum/totalStudents;
return overallAvg;
}
void printData (int pAverage, int pHigh[3], int pLow[3])
{
printf(" Highest Grade: %s %s %d", pHigh[0], pHigh[1], pHigh[3]);
printf("/n");
printf(" Lowest Grade: %s %s %d", pLow[0], pLow[2], pLow[3]);
printf("/n");
printf(" Average Grade: %d",pAverage);
}
The main chunk of problems come from the searchData function. In the if statements, every occurrence of *sPointArray and &sPointArray is underlined in red and the error reads
"Error: expression must have class type"
The same thing also happens in the calculateAvg function with *avgPointArray in the for loop. I know that the error is a fairly common problem for noobie C programmers (i.e myself) and that it generally has to do with writing the code as a function instead of a statement or something like that, but I can't for the life of me find where I have went wrong. Any help would be highly appreciated. I've been working at this for so long my vision is blurring.
Also, for anyone who solves this in like two seconds and wants proof that I'm a true idiot, there is an error in the enterStudents function where it says StudPtr = malloc(sizeof...). The error shows under the assignment symbol and says
"Error: a value of type "void*" cannot be assigned to an entity of type "int*".
I understand this concept in theory, but some advice for how to fix it would be highly appreciated.
Thank you in advance for any help.
You declare the sPointArray as an array of integers, but use it as an array of structures.

Resources