Empty Struct gets populated with no apparent pattern in C - c

I am currently trying to create a method to populate student with data, while having it inside an array of student, in order to be able to process its data with ease later on.
I have created two structs:
typedef struct{
char email[100];
char name[100];
char age[100];
char score[100];
}student;
typedef struct{
student *array;
}student_Array;
Then, within main(), I would declare them to be populated right after, using the Student Score Data.txt:
|NAME|E-MAIL|AGE|SCORE
|James|James#gmail.com|20 Years Old|20/50
|Charlie|Charls#gmail.com|21 Years Old|23/50
|Parker|prak#gmail.com|22 Years Old|26/50
int main(){
char fileName[100];
printf("Please enter file name:\n");
scanf("%[^\n]",fileName);
char *contents = readFileRaw(fileName); //Student Score Data.txt
student_Array students;
students.array = malloc(sizeof(student) * 100);
if(contents != NULL)
Fill_Contents(contents, students); //Method to fill the structs using the text file.
else
printf("its empty\n");
free(contents)
...
...
}
However, after at some point, I have noticed that specifically one of the parameters, students.array[0].name was populated with a part of the text file when I have not.
Note that all the other parameters of the same index, email, age and score was behaving normally, and so did all of the parameters on greater indexes.
Here is what the terminal printed after it has assigned its values:
STUDENT 0 INFORMATION:
student 0's age is 20 Years Old
student 0's name is Old|23/50
|Parker|prak#gmail.com|35 Years Old|26/50/50James
student 0's email is └James#gmail.com
student 0's score is 20/50
STUDENT 1 INFORMATION:
student 1's age is 21 Years Old
student 1's name is Charlie
student 1's email is Charls#gmail.com
student 1's score is 23/50
STUDENT 2 INFORMATION:
student 2's age is 35 Years Old
student 2's name is Parker
student 2's email is prak#gmail.com
student 2's score is 26/50
At first, I assumed it had to do with the Fill_Contents() method that I had created has some error, but it became clear that it was not the case.
By removing from main() the above mentioned method, it printed this:
STUDENT 0 INFORMATION:
student 0's age is
student 0's name is Old|23/50
|Parker|prak#gmail.com|35 Years Old|26/50/50
student 0's email is └
student 0's score is
STUDENT 1 INFORMATION:
student 1's age is
student 1's name is
student 1's email is
student 1's score is
STUDENT 2 INFORMATION:
student 2's age is
student 2's name is
student 2's email is
student 2's score is
It has now suddenly appeared as if regardless of being assigned or not using the Fill_Contents(), it would have been already populated with Old|23/50|Parker|prak#gmail.com|35 Years Old|26/50/50 for unknown reason.
My only suspect now is at the students.array = malloc(sizeof(student) * 100);, where it could have been something related to the memory, but I have no idea how to move on from here.
I hope this has been clear, and I hope someone could help me with this.
I'm new to c, so apologies if I missed out on something.

Related

How to create a function where it assigns a number to entered information

This is in C.
Im trying to create a function where you enter basic information and it assigns you an account number that can be used throughout.
When running the program it always out puts the same number. I dont need it to store outside of the program but the function and program are supposed to be run multiple times. I need this portion of the code to work because there is a later part where I have to delete the information entered and the way I thought best would be to assign the information to a value like account number and then use that to delete everything.
Sample output: Welcome Test Test to Global Bank. Your account number is 0 your initial balance in your checking is 100 and your initial balance in your savings is 1000.
What im trying to accomplish is have the account number in the sample output be 1 then when I run the NewAccount function again it should output:
Welcome Test2 Test2 to Global Bank. Your account number is 2 your initial balance in your checking is 100 and your initial balance in your savings is 1000.
This is the code. I have tried giving customers, of struct Bank a value of 20 (customers[20]) but that didnt seem to help. This is where im stuck at.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Customer
{
char FirstName[100];
char LastName[100];
int CheckingBalance;
int SavingsBalance;
int MoneyMarketBalance;
unsigned AccountNumber;
};
struct Customer NewCustomer(void)
{
static unsigned TopAccountNumber = 0;
struct Customer customer;
char FirstName[100];
char LastName[100];
int CheckingBalance;
int SavingsBalance;
int MoneyMarketBalance;
unsigned AccountNumber;
TopAccountNumber++;
customer.AccountNumber = TopAccountNumber;
return customer;
}
void NewAccount()
{
struct Customer customer;
printf("\nFirst name\n");
scanf("%s", customer.FirstName);
printf("\nLast name\n");
scanf("%s", customer.LastName);
printf("\nChecking deposit\n");
scanf("%d", &customer.CheckingBalance);
printf("\nSavings deposit\n");
scanf("%d", &customer.SavingsBalance);
printf("\nWelcome %s %s to Global Bank. Your account number is %d your initial balance in your checking is %d and your initial balance in your savings is %d.", customer.FirstName, customer.LastName, customer.AccountNumber, customer.CheckingBalance, customer.SavingsBalance);
}
int main()
{
int choice;
printf("\n1 is the problem function. After you enter your inital values run 1 again and run a second set of values \n to exit press '7'.\n");
while(1){
scanf("%d", &choice);
switch(choice)
{
case 1:
NewAccount();
break;
case 7:
printf("Have a good day and thank you for banking with Global Bank!\n");
exit(0);
}
}
}
A "bank" have customers, but isn't a customer in itself. So the Bank structure is rather badly named. And if one customer can only have a single account-number, then make it a part of the "customer" structure as well.
As for giving each customer a unique account number, one simple way is to keep track of the current highest number using a variable. Then when you create a new customer you increase that variable by one, and assign it to the customers specific account number.
For example:
struct Customer
{
// Other customer data...
unsigned AccountNumber;
};
struct Customer NewCustomer(void)
{
// This is the base for all account numbers
static unsigned TopAccountNumber = 0;
struct Customer customer;
// Initialize other customer data...
++TopAccountNumber; // Increase top account number
customer.AccountNumber = TopAccountNumber;
return customer;
}

How to fix 'structuredfunctions not calling'

So I wrote this code as a part of my assignment like so, we are still learning C language and I am just unable to correct this one. We have to make a code on writing a function to print the names of all the students that joined in a particular year.
It runs the code till switch case, but doesn't work further.
#include<stdio.h>
struct stdnt
{
char stName[100];
char stRNo[100];
char Dept[50];
char crse[50];
int YoJ[4];
}s[2];
void stYr(p)
{
printf("Student Name = %s\t",s[p].stName);
}
void stRNm(q)// q RNm
{
int i;
for(i=0;i<=1;i++)
{if(q == s[i].stRNo)
{
printf("Student Name = %s\t",s[i].stName);
printf("Student Year of Joining = %d\t",s[i].YoJ);
printf("Student Department = %s\t",s[i].Dept);
printf("Student Course = %s\n",s[i].crse);
}
}
}
int main()
{
int i;
int year;
int RNm;
int ch;
printf("Please Enter the details of 2 Students.\n");
for(i=0;i<=1;i++)
{
printf("Enter Name of Student %d:\n",i+1);
scanf("%s",s[i].stName);
printf("Enter Department of Student %d:\n",i+1);
scanf("%s",s[i].Dept);
printf("Enter Year of Joining of Student %d:\n",i+1);
scanf("%d",s[i].YoJ);
printf("Enter Roll Number of Student %d:\n",i+1);
scanf("%s",s[i].stRNo);
printf("Enter Course of Student %d:\n",i+1);
scanf("%s",s[i].crse);
}
printf("Enter 1 to Print the List of Student using Year.\nEnter 2 to Search the details of student using Roll no.\n");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("Enter the Year:\n");
scanf("%d",&year);
for(i=0;i<=1;i++)
{
if(year == s[i].YoJ)
{
stYr(i);
}
}
break;
case 2:
printf("Enter the roll number you want to search:\n");
scanf("%d",&RNm);
stRNm(RNm);
break;
}
return 0;
}
the question is
Create a structure to specify data on student given below : Roll number, Name, Department, Course, Year of Joining.
Assume that there are not more than 450 students (i am trying to code for 2 firstly will make it for 450 once it works)
also `
write a function to print name of all the students who joined in a particular year.
write another function to print the data of a student whose roll number is entered
make switch cases .
OUTPUT i am getting :
Please enter the details of 2 students .
Enter Name of Student 1:
katyal
Enter department :
Mech
Enter Year of joining:
2019
Enter roll number:
1
Enter Course :
C
Enter Name of Student 2:
Pranay
Enter department :
Mech
Enter Year of joining:
2019
Enter roll number:
2
Enter Course :
C
Enter 1 to Print the List of student using year
Enter 2 to print details of student using roll number
1
Enter the year:
2019
Process returned 0<0x0> execution time 30.600s
Press any key to continue.
Expected Output :
after the Year is entered after switch case, i expect the Function `stYr to get called and print the list of student with that Year as their Year of Joining
similarly if roll number is entered i want the details of that student printed.
As you're learning C code I think that you should start off by taking on board a few standard working practices.
It's very evident that either your teacher hasn't really coded in a working environment or they are expecting you to spot the mistakes.
I realise that there may be issues or restrictions due to your compiler, but here are some pointers that will help in future.
Here are some pointers based on your code.
Always initialise variables before use. If a variable can be null and that is not a valid value, check for null before use e.g. `char[] or pointer types.
Use typedef for structure declarations, this will allow the compiler to determine incorrect use through type checking during compilation.
Use long, meaningful variable and function names as an aid to understand the code.
Indentation with brackets e.g. { }, to make code easy to understand.
Refrain from using literal values in code as this can lead to introduction of bugs at a later stage if a value is not changed in all cases through the code.
Function parameters should be definitive in type - this makes code portable between compilers, environments and easier to understand.
In for loops try to only use less than < and greater than > comparisons.
In 'if' statements try to place non-assignable values on the left side as this will raise a compiler warning if you type = instead of ==.
Try and make functions re-entrant i.e. not reliant on global variables to determine their behaviour if possible, void func(void) should ring alarm bells.
Be careful when using signed values such as int use unsigned int in preference UNLESS you know that a variable will be assigned values of less than 0.
Declaring function parameters as const and then using local function variables as copies (if you wish to change their value) will make code easier to debug.
Switch statements should always include a default: to handle undetermined values.
struct stdnt /* REVIEW COMMENT: use typedef */
{
char stName[100]; /* REVIEW COMMENT: non-literal value for 100 */
char stRNo[100]; /* REVIEW COMMENT: Based upon later usage should this be unsigned int rather than char[] type */
char Dept[50];
char crse[50];
int YoJ[4]; /* REVIEW COMMENT: this is an array of int. Either use int or char[4] */
}s[2]; /* REVIEW COMMENT: separate out declaration for clarity and use a meaningful name */
I'd suggest that you change it to this
#define TEXT_LENGTH_LONG 100
#define TEXT_LENGTH_SHORT 50
#define NUMBER_OF_STUDENTS 2
typedef struct
{
char Name[NAME_LENGTH];
unsigned int RollNumber;
char Department[TEXT_LENGTH_SHORT];
char Course[TEXT_LENGTH_SHORT];
unsigned int YearOfJoining;
}student_t;
student_t students[NUMBER_OF_STUDENTS];
This function code has some issues.
void stRNm(q)/* REVIEW COMMENT: non-definitive declaration can cause confusion. Unclear function name and parameter */
{
int i;
for(i=0;i<=1;i++) /* REVIEW COMMENT: use of literal value makes maintenance more difficult and can introduce bugs if the array size is changed but this is missed */
{if(q == s[i].stRNo) /* REVIEW COMMENT: possible type mismatch in comparison - comparing int or char[] ?*/
{
printf("Student Name = %s\t",s[i].stName);
printf("Student Year of Joining = %d\t",s[i].YoJ);
printf("Student Department = %s\t",s[i].Dept);
printf("Student Course = %s\n",s[i].crse);
}
}
}
becomes
void PrintStudentInfo(const unsigned int rollNumOfStudent)/* Declaring rollNumOfStudent as const will give it compiler protection against being assigned to */
{
int i;
for(i=0;i<NUMBER_OF_STUDENTS;i++)
{
if(rollNumOfStudent == students[i].RollNumber)
{
printf("Student Name = %s\t",students[i].Name);
printf("Student Year of Joining = %d\t",students[i].YearOfJoining);
printf("Student Department = %s\t",students[i].Department);
printf("Student Course = %s\n",students[i].Course);
}
}
}
Okay this is just a start.
There are issues in your main function relating to what I've mentioned already that are causing the odd behaviour.
C is a language that is so loosely defined that it is very easy to introduce bugs due to shortcuts taken in coding.
Be pedantic.
Don't let the compiler make the decisions.
Be sure that the data types of variables are what you want rather than what the compiler determines.
Edit
Taking into account my comments about data types.
This line if(year == s[i].YoJ) is performing the following if(int == int[4])

How to match a varible in a struct array, then the position

first post here. Somewhat new to coding aswell.
Right now I'm at halt. What I need to do is get input from the user of an employee id then find it in a struct array variable, and keep asking until a correct one is entered.. all in a do-while loop. Then I need to print the salary of that employee and update it to something new.
I'm having a hard time trying to figure out how to search the struct array for that employee ID, then when that's done, saving what position the struct array in is so I can print THAT employees salary, then update it to something else.
Heres some code to show the struct array
#define SIZE 4
struct employee{
int id[SIZE] ;
int age[SIZE];
double salary[SIZE];
};
/* main program */
int main(void) {
struct employee emp[SIZE] = { 0 };
Here is some to show the code to what I've done
case 3: //Update Employee
printf("Update Employee Salary\n");
printf("======================\n");
int employid;
do{
printf("Enter Employee ID: ");
scanf("%d", &employid);
}while(employid != emp->id[SIZE]);
printf("The current salary is %lf", emp->salary[SIZE]);
break;
I know this is wrong. The While just looks at the current position, and the printf only prints the salary of the current arrays employee aswell.
Any help would be appreciated.
Bonus:
Notice when I'm assigning/working with my struct, I have to put "->" to actually tell my compiler that I'm pointing to that specific variable in the struct. Usually I put "." and have no idea why I need to put ->.. I just found the fix online.
Usually it would be "emp.id[SIZE];"
NOT "emp->id[SIZE];"
Anyone have any ideas?
Thanks all
Considering that your input to the structure is right, there are few things you can do.
The thing is you need to realize that you need a while/for loop to iterate over the employee array.
Second thing is, here you are not comparing it correctly. You are just comparing with the first element.
Now what you can do is
bool found = false;
int foundEmpId = -1;
do{
printf("Enter Employee ID: ");
scanf("%d", &employid);
for(size_t i = 0; i< SIZE; i++)
if( emp[i].id == employid ){
foundEmpId = employid;
found = true;
break;
}
}while(!found);
// do your work.
Now this is simply the O(n) searching.
Apart from that there is one thing you can see in my code. I am using emp[i].id. Here the structure I considered is
struct employee{
int id ;
int age;
double salary;
};
If you think of an employee these are the attributes you need to add over here. What you did was working with different groups of employees.
Here you will work like this
struct employee emps[SIZE];
...
...
// the attributes of employee will be inputted like this
// if( scanf("%d",&emps[i].id) == 1 ) { /* */ }
...
Why did you need emp->id[SIZE] here?
Dissecting the emp->id[SIZE] is equivalent to (*emp).id[SIZE] or more precisly emp[0].id[SIZE].
To summarize the problems/suggestion:-
P The portion of the code that you have shown it shows that you are not comparing with all the employees.
P You have created groups of employees. But you are not iterating or using all the groups. You just worked on first employee group.
S Instead of using the array of employee groups you should simply use array of employees. Or Even if you do use groups of enployess then just one group will suffice.

How to return correct value through this function that has a structure array as argument?

I'm learning Structures in C, and trying to write the solution for this problem-
Create a structure to specify data on students given below: Roll
number, Name, Department, Course, Year of joining .
Assume that there are not more than 5 students in the class. (a) Write a function to
print names of all students who joined in a particular year. (b) Write
a function to print the data of a student whose roll number is given.
My code is given next, with a brief description of various components in the program, and then the source of the problem -
#include<stdio.h>
struct student
{
int roll_no;
char name[20];
char department[30];
char course[20];
int year_joined;
};
void main()
{
struct student s[5];
int i=0,choice;
printf("\n Enter the following information for each student: \n");
printf("\n Roll No., Name, Department, Course, Year of Joining\n");
for(i=0;i<=4;i++)
scanf("%d %s %s %s %d", &s[i].roll_no, &s[i].name, &s[i].department, &s[i].course, &s[i].year_joined);
printf("\n Please choose from the following options :\n");
printf("\n 1. Print names of students who joined in a given year.");
printf("\n 2. Print data of all students whose roll.no is given.");
scanf("%d",&choice);
switch(choice)
{
case 1: display_names(s);
break;
case 2: student_data(s);
break;
default: printf("\n Incorrect choice, please try again.");
}
}
void display_names(struct student p[])
{
int i,count=0;
int year;
printf("\n Enter the year you wish to search student info. for : \n");
scanf("%d",&year);
for(i=0;i<=4;i++)
{
if(p[i].year_joined==year)
{
//printf("%d %s %s %s %d", p[i].roll_no, p[i].name, p[i].department, p[i].course, p[i]. year_joined);
count++;
printf("\n Student Name: %s\n", p[i].name);
}
}
printf("\n Total Number of students who joined in the year %d is %d\n", year,count);
if(count==0)
printf("\n No match found.");
}
void student_data(struct student st[])
{
int i,count=0;
int roll;
printf("\n Enter roll number of the student: \n");
scanf("%d",&roll);
for(i=0;i<=4;i++)
{
if(st[i].roll_no=roll)
{
count++;
printf("\n Student Data: Roll No. Name Department Course Year of Joining \n");
printf("\n %d %s %s %s %d", st[i].roll_no, st[i].name, st[i].department, st[i].course,st[i].year_joined);
break;
}
}
if(count==0)
printf("\n No matching Roll Numbers found\n");
}
Here's a brief description of this program-
Since I'm required to store information about multiple students in the structure, I have created a structure array. The structure struct student is defined at the very beginning, and the array is created inside main- struct student s[5]
The structure is initialized by accepting user input through scanf() inside main(). There are two switch cases for the two functions, asked in the question- display_names(s) and student_data(s)
The display_names(s) function is called in main, and is defined outside it. The function accepts a structure array and asks the user to enter a year. It loops through the initialized array and searches for the input(year of joining) entered by the user. When there's a match, it prints out the names of all students who've joined in that year. Here's a sample output for this function-
*
**Enter the following information for each student:
Roll No., Name, Department, Course, Year of Joining
10 Tim CS MS 2013
20 Shane CS MS 2013
30 John EE ME 2013
40 Mark MECH MS 2013
50 Matt EE ME 2010
Please choose from the following options :
1. Print names of students who joined in a given year.
2. Print data of all students whose roll.no is given.1
Enter the year you wish to search student info. for :
2013
Student Name: Tim
Student Name: Shane
Student Name: John
Student Name: Mark
Total Number of students who joined in the year 2013 is 4**
*
This function works fine.
The problem is in the next function student_data(). Similar to the first function, it accepts a structure array as input. The way I've designed the function- the idea is to loop through the array until it finds a roll number that's equal to the one entered by the user. When there's a match, it would print out the details of that particular student itself. However, as it stands, this function always prints the first entry in the array, and I can't seem to understand why. I've added the break in the if statement, but it doesn't seem to make any difference.
Here's a sample output-
Enter the following information for each student:
Roll No., Name, Department, Course, Year of Joining
10 Tim CS MS 2013
20 Shane CS MS 2013
30 John EE ME 2013
40 Mark MECH MS 2013
50 Matt EE ME 2010
Please choose from the following options :
1. Print names of students who joined in a given year.
2. Print data of all students whose roll.no is given.2
Enter roll number of the student:
40
Student Data: Roll No. Name Department Course Year of Joining
40 Tim CS MS 2013
Can you please say where I'm going wrong in this second function?
Your if statement within student_data() is assigning rather than comparing.
Consider compiling with the -Wall ( or specifically -Wparentheses ) flag:
#include <stdio.h>
int main( void )
{
int a = 10;
if ( a = 11 ) printf( "a equals 11\n" );
return 0;
}
Using -Wall:
$ gcc main.c -Wall
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if ( a = 11 ) printf( "a equals 11\n" );
$

C Programming, Structs and Multidimensional arrays

I am given an exercise that I can't seem to understand. I am almost done with my assignment but I'm stuck on this function.
Limitations:
There can only be 10 unique student ID's.
There are 5 subject area of study.
An a student can only take 2 subjects.
My struct.h look like this:
typedef struct student_info{
int student_id;
int course_id[2];
}student;
In main.c
student info[10];
In func.c
Say I Prompt the user for a Student ID.
printf("Enter Student ID. ");
scanf("%d", &info->student[count_stud]->student_id;
User inputs 123
Then Prompt the user for a course ID.
printf("Enter Course ID. ");
scanf("%d", &info->student->course_id[count_cour];
User inputs 101
My problem lays with printing out a specific student_id and the course that student is taking. Also using a for loop I couldn't find a way to find a duplicate. I can find an id that was last inputted by the user but when I enter an id from 2 previous inputs it passes my if else statements.
Any help is appreciated.
student info[10];
Here, info is array of 10 students so you will have to read it with index.
for(int student_count = 0; student_count < 10; student_count ++)
{
printf("Enter Course ID 1 for student %d. ",student_count+1);
scanf("%d", &info[student_count].course_id[0]);
printf("Enter Course ID 2 for student %d. ",student_count+1);
scanf("%d", &info[student_count].course_id[1]);
}

Resources