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

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]));
}

Related

C Program to calculate sgpa using structures

(QW) Write a well documented modular C program to compute SGPA of 2 students of particular semester containing 3 courses, suitably using structures.
Getting garbage value as output scanning of elements goes perfectly but when it comes to printing it displays random number as output, Is the sgpa calculator part of the code correct?
//reaplced courses with 3 and no of students with 2
#include<stdio.h>
struct studentlist
{
int Rno;
char name[20];
int course_marks[8];
}S[2];
int main()
{
int sgpa[2];
printf("ENTER DETAILS\n");
for(int i=0;i<2;i++)
{
printf("enter details of student %d\n",i);
scanf("%d %s",&S[i].Rno,S[i].name);
for(int j=0;j<3;j++)
{
printf("enter marks coursenumber %d \n",j);
scanf("%d",S[i].course_marks[j]);
}
}
//printing details
for(int i=0;i<2;i++)
{
printf("details of student %d are \n",i);
printf("%d %s",S[i].Rno,S[i].name);
for(int j=0;j<3;j++)
{
printf("coursewise marks for studenet %d are\n",j);
printf("%d\n",S[i].course_marks[j]);
}
}
printf(" \n\n ");
//sgpa calculation
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
sgpa[j]=0;
sgpa[j]+=S[i].course_marks;
}
}
//printing
for(int i=0;i<2;i++)
{
printf("%d",sgpa[i]);
}
}
Your usage of S[j].course_marks is wrong.
It is an array and it will be converted to a pointer in expressions here.
It seems the lines
scanf("%d",S[j].course_marks);
printf("%d\n",S[i].course_marks);
sgpa[j]+=S[i].course_marks;
should be
scanf("%d",&S[i].course_marks[j]);
printf("%d\n",S[i].course_marks[j]);
sgpa[j]+=S[i].course_marks[j];
Also the loop
for(int j=0;j<3;j++)
{
sgpa[j]=0;
sgpa[j]+=S[i].course_marks;
}
is bad because it accesses spga[2] while spga has only 2 elements spga[0] and spga[1].
Also it looks weird even if it weren't out-of-range access and
sgpa[j]=0;
sgpa[j]+=S[i].course_marks;
is equivalent to
sgpa[j]=S[i].course_marks;
You should rethink the algorithm here.

How do I get input for an array from a user in C programming?

I am new to C and I've run into a bit of a problem when it comes to user input for an array.
Here is the code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n, i;
int score [n];
printf("Number of scores: ");
scanf("%d", &n);
for(i=0; i<n; i++){
printf("score: ");
scanf("%d", &score[i]);
}
return 0;
}
It does not matter what value I set for n. It always prompts the user 4 times.
As mentioned in comments, you must change this:
/* bad */
int score [n];
printf("Number of scores: ");
scanf("%d", &n);
into this
/* good */
printf("Number of scores: ");
scanf("%d", &n);
int score [n];
This since C executes code from top to bottom like when you are reading a book. It will not "double back" a few rows above and fill in n once it has been entered by the user. At the point where you declare int score [n], n must already be known.
If your using an array with unknown size during compilation, I would suggest using memory allocation. So the user determines the array size while running the program.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n, i;
int *score;
printf("Number of scores: ");
scanf("%d", &n);
score = (int *)malloc(sizeof(int)*n);
for(i=0; i<n; i++){
printf("score: ");
scanf("%d", &score[i]);
}
free(score)
return 0;
}
The malloc function allocates memory with the size of n and returns a pointer to the allocated memory.

Program stops working after entering the value for more than 6 users

I have a school project which asks me to write a code using struct and functions, regarding sales in Greek cities. You are prompted to enter the values of 'em. The program works just fine if I enter that there's 6 salesmen, but a number larger than that makes it stop after entering all the values.. An example would be:
Number of salesmen: 7
(
Enter the his id:
Enter his surname:
Enter the number of sales:
Enter the area code:
) x7 times.
Then, when you enter the last value, it would just stop. Not exit, not stop responding/crash, literally just stop, and you would be unable to type anything more, only option would be to exit.
Thing is, there's no error or warning in both the build messages and the log, which has me quite confused.
My guess is that the error is in the function "calcSales" but I wanted to post the whole code just in case you need more info on it.
Could you take a look at the code and tell me if you find anything wrong? Thank you.
#include <stdio.h>
#include "genlib.h"
#include <simpio.h>
#include <string.h>
#define N 20
#define M 4
struct{
int id;
char surname[16];
long sales;
int area;
} salesmen[N];
void info(int *count);
void calcSales(int *count);
int main(){
int count;
printf("Give me the number of salesmen:\n");
count=GetInteger();
info(&count);
calcSales(&count);
}
void info(int *count){
for (int i=0; i<*count; i++){
printf("\nInfo for salesman number %d:\n", i+1);
printf("\nGive me his id: ");
salesmen[i].id=GetInteger();
printf("\nGive me his surname: ");
gets(salesmen[i].surname);
printf("\nGive me the number of sales: ");
salesmen[i].sales=GetLong();
printf("\n 1=Thessaloniki, 2= Athens, 3= Volos, 4= Hrakleio \n");
printf("\nLastly, give me the number of his area: ");
salesmen[i].area=GetInteger();
if (salesmen[i].area>4){
printf("\nThe number you are trying to enter doesn't match to an area.\n");
break;
}
}
}
void calcSales(int *count){
long tSales[4];
for (int i=0; i<*count; i++){
tSales[i]=0;
}
for (int i=0; i<*count; i++){
if(salesmen[i].area==1){
tSales[0]+=salesmen[i].sales;
}
if(salesmen[i].area==2){
tSales[1]+=salesmen[i].sales;
}
if(salesmen[i].area==3){
tSales[2]+=salesmen[i].sales;
}
if(salesmen[i].area==4){
tSales[3]+=salesmen[i].sales;
}
}
for (int i=0; i<4; i++){
printf("\nSales for area number %d: %ld\n",i+1, tSales[i]);
}
}
Your guess is correct. The mistake in calcSales function.
Exactly, the following part:
long tSales[4];
for (int i=0; i<*count; i++) {
tSales[i]=0;
}
The *count has value of 20. Which means the loop goes from i = 0 until i = 19.
When you access tSales[i] for i = 4 and above. You're invoking an undefined behavior. It's a memory that you didn't reserve for tSales. I suggest using the following:
long tSales[4];
for (int i=0; i<4; i++) {
tSales[i]=0;
}
Or better:
long tSales[4];
for (int i=0; i<sizeof(tSales)/sizeof(tSales[0]); i++) { // number of elements is the total size of array divided by the size of one element.
tSales[i]=0;
}
Or even better, you don't need a loop at all:
long tSales[4] = {0};
Besides your problem:
For the code you're providing, you don't need to pass a pointer to the functions.
You can make the code look as follows:
#include <stdio.h>
#include "genlib.h"
#include <simpio.h>
#include <string.h>
#define N 20
#define M 4
struct{
int id;
char surname[16];
long sales;
int area;
} salesmen[N];
void info(int count);
void calcSales(int count);
int main(){
printf("Give me the number of salesmen:\n");
int count=GetInteger(); // I've made declaration and assignment in same line. That seems cleaner to me.
info(count);
calcSales(count);
}
void info(int count){
for (int i=0; i<count; i++){
printf("\nInfo for salesman number %d:\n", i+1);
printf("\nGive me his id: ");
salesmen[i].id=GetInteger();
printf("\nGive me his surname: ");
gets(salesmen[i].surname);
printf("\nGive me the number of sales: ");
salesmen[i].sales=GetLong();
printf("\n 1=Thessaloniki, 2= Athens, 3= Volos, 4= Hrakleio \n");
printf("\nLastly, give me the number of his area: ");
salesmen[i].area=GetInteger();
if (salesmen[i].area>4 || salesmen[i].area < 1){ // Added an extra condition.
printf("\nThe number you are trying to enter doesn't match to an area.\n");
break;
}
}
}
void calcSales(int count){
long tSales[4] = {0};
for (int i=0; i<count; i++){
tSales[salesmen[i].area - 1]+=salesmen[i].sales; // No need for if conditions.
}
for (int i=0; i<4; i++){
printf("\nSales for area number %d: %ld\n",i+1, tSales[i]);
}
}

Having problems with 2D char arrays

So I've got an assignment where my program asks the brand (10 letters), model (10 letters), age (1986 - 2019) and cost (positive real number) of 10 cars and then wants the program to check which car is the oldest and to print out it's brand and model. I don't have a problem with the first part but with the second part.
The code is:
//First part
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C 10
#define M 11
int main(void)
{
char brand[C][M];
char model[C][M];
int year[C];
float cost[C];
int i, len1, len2, min;
for(i=0; i<C; i++){
printf("Car %d\n", i+1);
do{
printf("Brand: ");
scanf("%s", brand[i]);
len1 = strlen(brand[i]);
} while(len1<0 || len1>10);
do{
printf("Model: ");
scanf("%s", model[i]);
len2 = strlen(model[i]);
} while(len2<0 || len2>10);
do{
printf("Year: ");
scanf("%d", &year[i]);
} while(year[i]<1986 || year[i]>2019);
do{
printf("Cost: ");
scanf("%d", &cost[i]);
} while(cost[i]<=0);
}
//Second part
year[0] = min;
for(i=0; i<10; i++)
if(year[i] < min){
min = year[i];
printf("\nThe oldest car is %s %s\n", brand[i], model[i]);
}
For some reason it either prints out gibberish in the place of brand[i] or if I lose the columns of the if statement prints out all the car brands and their models, where I only want the oldest one.
Aside from scanf not being recommended there are some problems with this code, first when you read the brand and model you do:
do{
printf("Brand: ");
scanf("%s", brand[i]);
len1 = strlen(brand[i]);
} while(len1<0 || len1>10);
The problem here is that you first write the string to brand[i] and then check if it's too long, but you have already written it into the array so if the string is longer than your space you already have a buffer overflow. Limit the size you can read with scanf using scanf("%10s, brand[i]) or better yet use fgets(brand[i], sizeof(brand[i]), stdin).
Next in the second part you use min without initializing it, and you overwrite the content of year[0] with it. You probably wanted something like:
min = 2020; // or a number that will be bigger than all your cars anyway
int older = 0;
i = 0;
for(i=0; i<C; i++){ // Use C here, you have it might as well use it instead of magic numbers
if(year[i] < min){
older = i;
min = year[i];
}
}
printf("\nThe oldest car is %s %s\n", brand[older], model[older]);
but bare in mind that this solution will print multiple cars if they are the oldest ones and have the same year

Small c programming help needed

I have this problem I've been trying to get this done for last 7 hours, but I'm not getting anywhere. I have tried many options but I seem to fail all time. I'd be delighted if someone helped me out with this so I could see where I'm going wrong. I have made small attempt but the further I go to worst I get. I'd be happy if someone gave me some guidance please. Here is what the program should be like.
I have to enter integer numbers only if it's a floating number than it should display an error and that I need to try again. The minimum amount of numbers are 10.
Once all the numbers are entered it should display what the percentage of the numbers are even numbers.
At any time i can exit the program by typing "exit"
int i;
for(i=1; i<=10; ++i)
printf("Enter 10 integers: ");
scanf("%d",&i);
printf("Enter the next integer or type exit to end the program: %d",i);
system("PAUSE");
return (printf);
Since you asked for guidance rather than a full working solution, here goes.
First you currently have
for(i=1; i<=10; ++i)
printf("Enter 10 integers: ");
scanf("%d",&i);
The for will just loop around the next line, unless you use braces, i.e. it will print "Enter..." 10 times:
for(i=1; i<=10; ++i)
printf("Enter 10 integers: ");
scanf("%d",&i);
It may help to get used to putting everything you want to loop (even a one-liner) in braces:
for(i=1; i<=10; ++i)
{
printf("Enter 10 integers: ");
scanf("%d",&i);
//...
}
Often people (with good reason) start at 0 in C:
for(i=0; i<10; ++i)
{
printf("Enter 10 integers: ");
scanf("%d",&i);
//...
}
If you structure your code like that it may help to pull out a get_valid_input function
for(i=0; i<10; ++i)
{
printf("Enter 10 integers: ");
get_valid_input(); //what do you intend to do with this?
//...
}
with
int get_valid_input()
{
int i;
scanf("%d",&i); //how do they type "exit"?
//..
}
This needs thought though - should it return an int?
You could then store them somewhere.
But you could keep track of percentage of even numbers as you go.
Also, at any time you can press "exit" (type in the string or press a key?) so you need to be able to indicate that.
Don't forget to print the result, once you have worked it out. (Left as an exercise for the reader)
int i, v, n=0, even;
int array[10] = {0};
char buff1[32], buff2[32];
printf("Enter 10 integers: \n");
for(i=1; i<=10; ++i){
printf("Enter the next integer or type exit to end the program %d:\n", i);
fgets(buff1, sizeof buff1, stdin);
strcpy(buff2, strtok(buff1, " \t\n"));//trim
if(strcmp(buff2, "exit")==0)
break;
if(1!=sscanf(buff2, "%d%s", &v, buff1)){
printf("invalid input\n");
--i;
continue;
}
array[n++] = v;
}
for(even=i=0;i<n;++i){
printf("%d ", array[i]);
if((array[i] & 1) == 0)
++even;
}
printf("\n");
if(n)
printf("Even proportions : %.1f%%\n", 100.0*even / n);
system("PAUSE");
return 0;

Resources