This program is supposed to capture input from the user into the struct and then print out a histogram of the given information. Everything works fine so far except that when I try to print the histogram all the '*' characters fall under the F grade no matter what the student's grade. What I think is happening is that the student's array index is being passed instead of the actual variable itself, but I'm confused because in the output before the histogram is printed it shows the correct value. Any suggestions?
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 28
#define MAXGRADE 100
struct studentData{
char studentID[MAXSIZE];
char studentName[MAXSIZE];
int examPercent;
} studentRecords[MAXSIZE];
// function prototype for histogram
void displayHist(struct studentData *records, int classSize);
int main()
{
int i, students = -1;
//struct studentData *studentRecords[MAXSIZE];
while(students < 0 || students > MAXSIZE)
{
printf("Please enter the number of students in your class:\n");
scanf("%d", &students);
if(students > MAXSIZE || students <= 0)
{
printf("Try again..\n");
scanf("%d", &students);
}
}
for(i=0;i<students;i++) {
printf("Please enter the student #%d's lastname:\n", i+1);
scanf("%s", &studentRecords[i].studentID);
printf("Please enter the student #%d's ID#:\n", i+1);
scanf("%s", &studentRecords[i].studentName);
printf("Please enter the student's exam percent:\n");
scanf("%d", &studentRecords[i].examPercent);
}
//This is just here to view the input...
for(i=0;i<students;i++) {
printf("Student #%d's name is %s\n", i+1, studentRecords[i].studentName);
printf("student #%d's ID#:%s\n", i+1, studentRecords[i].studentID);
printf("student #%d's grade was %d\n", i+1, studentRecords[i].examPercent);
}
displayHist(&studentRecords[students], students);
return 0;
}
void displayHist(struct studentData *records, int classSize)
{
int i;
printf("A:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent >=90)
{
printf("*");
}
}
printf("\n");
printf("B:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent< 90 && records[i].examPercent >= 80)
{
printf("*");
}
}
printf("\n");
printf("C:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent < 80 && records[i].examPercent >= 70)
{
printf("*");
}
}
printf("\n");
printf("D:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent< 70 && records[i].examPercent >= 60)
{
printf("*");
}
}
printf("\n");
printf("F:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent < 60)
{
printf("*");
}
}
}
displayHist(&studentRecords[students], students);
&studentRecords[students] is an address after your array studentRecords. In displayHists, accesses to records[i] will try to dereference studentRecords[students+i], which is outside the bounds of your array.
A correct call could be:
displayHist(&studentRecords[0], students);
Which is equivalent to:
displayHist(studentRecords, students);
By the way, no need to use & in scanf with char *, because char (*)[] and char * may have different memory representations.
scanf("%s", &studentRecords[i].studentID);
scanf("%s", &studentRecords[i].studentName);
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[28]’ [-Wformat]
When you use address-of, i.e. &, it becomes char **, which is not what scanf expects.
So try using this way.
scanf("%s", &(*studentRecords[i].studentID));
and
displayHist(studentRecords, students);
Related
i want to ask you, here in my code i used case condition for input, but i got a trouble, in my code i want to check is my "NIM" value was inputted to struct or not, if it was inputted, it can't be inputted to struct. Here are my code
#include <stdio.h>
#include <string.h>
struct data {
char nim[10];
};
struct data batas[100];
int a, b, c, d;
int i, j;
char x;
void inputdata()
{
printf("\nInput Data\n");
printf("=======================\n");
printf("NIM : "); scanf("%s", batas[a].nim);
for(i=0; i<a; i++){
if (strcmp(batas[a].nim, batas[i].nim) == 0) {
x = "FLAG";
} else {
x = "FLAGX";
}
}
printf("%s", x);
if (strcmp(x, "FLAGX") == 0) {
a++; // This will input to struct
}
}
void showdata()
{
j=0;
for(i=0; i<a; i++){
j = j + 1;
printf("\nData-%i", j);
printf("\nNIM : %s", batas[i].nim);
}
}
int main() {
int menu;
do {
printf("\n\Choose input = "); scanf("%d", &menu);
switch(menu)
{
case 1 : inputdata(); break;
case 2 : showdata(); break;
}
}while (menu != 3);
return 0;
}
From this i always get an error Segmentation Fault. I appreciate you guys, thank you.
You have already got many suggestion to check your program for warnings and errors.
Check warnings and errors of your program : https://onlinegdb.com/By1VeOK1d
main.c:20:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
main.c:22:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
main.c:25:12: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
main.c:26:14: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [-Wint-conversion]
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘char’
main.c:44:12: warning: unknown escape sequence: '\C'
All of the above warnings will be cleared just by making two changes to your code
line 11 change char x; as char* x;
line 44 change printf("\n\Choose input = "); as printf("\n Choose input = ");
Moving on to your code correctness, your function inputdata() is depending on global variable a and the loop for(i=0; i<a; i++){ is never true because i < a will never be true, since a is global (default value 0).
Which leads to execution of other statements in an undefined way.
you are directly reading your input into structure scanf("%s", batas[a].nim);, instead read into a local variable like char temp[30] , then add it your batas and continue checking for the existence of your string from next input.
#include <stdio.h>
#include <string.h>
struct data {
char nim[10];
};
struct data batas[100];
int a, b, c, d;
int i, j, flag;
void inputdata()
{
flag = 0;
printf("\nInput Data\n");
printf("=======================\n");
printf("NIM : ");
scanf("%s", batas[a].nim);
for(i=0; i<a; i++){
if (strcmp(batas[a].nim, batas[i].nim) == 0) {
flag = 1;
}
}
if (flag == 0) {
a++; // This will input to struct
}
}
void showdata()
{
j=0;
for(i=0; i<a; i++){
j = j + 1;
printf("\nData-%i", j);
printf("\nNIM : %s", batas[i].nim);
}
}
int main()
{
int menu;
do {
printf("\n\Choose input = "); scanf("%d", &menu);
switch(menu)
{
case 1 : inputdata(); break;
case 2 : showdata(); break;
}
}while (menu != 3);
return 0;
}
I made this simple program that asks the user to input the number of columns the matrix called arp is going to have because, that way when the program asks the user to input a number so it can find matches on the numbers stored at the array without comparing all 10 columns allocated on memory with array to pointer type.
The problem here comes when the user inputs into the columns size definition 2. All works fine before the last function of p3() does its job, then it doesn't even return to main to execute the infinite loop defined there. I have tried removing the pointers and didn't work; I also tried removing other parts of the code but still nothing...
Update: Tried removing the function to find elements felmnt() and still the same.
Here is The Buggy Code:
#include <stdio.h>
#include <stdlib.h>
int loop = 1;
void keepalive(void)
{
int ckr = 0;
fflush(stdin);
printf("\n\n ******[s]<< CONTINUE | EXIT >>[n]******\n");
while(printf(" > ") && (ckr = getchar()) != 's' && ckr != 'n') fflush(stdin);
getchar();
if(ckr == 'n') loop = 0;
system("CLS");
}
void felmnt(int *colu, int (*arp)[10])
{
int nius=0, colmts, x, i, ejct;
do
{ // loop to let the user find more elements inside matrix
colmts=0;
printf("\n Insert The Number To Find\n > ");
scanf("%d", &nius);
for(x=0; x<*colu; x++) // search of element inside matrix
{
for(i=0; i<=9; i++)
if(nius == arp[i][x])
colmts++;
}
if(colmts>1) // results printing
{
printf("\n %d Elements Found", colmts);
}else if(colmts)
{
printf("\n 1 Element Found");
}else
{
printf("\n Not Found");
}
printf("\n TRY AGAIN? s/n\n > ");
ejct=getchar();
getchar();
}while(ejct=='s');
}
void mat(int *colu, int (*arp)[10])
{
int ci, cn, tst=0;
for(ci=0; ci<*colu; ci++)
{
for(cn=0; cn<10; cn++)
{
printf("\n Input The Number [%d][%d]\n > ", ci+1, cn+1);
scanf(" %d", &arp[cn][ci]);
}
}
printf(" Numbers Inside Matrix> ");
for(ci = 0; ci<*colu; ci++)
{
for(cn=0; cn<10; cn++) printf(" %d", arp[cn][ci]);
}
}
void p3(void)
{ // >>>>main<<<<
int colu=0;
while(loop)
{
printf("\n Input The Quantity Of Columns To Use\n > ");
scanf("%d", &colu);
int arp[10][colu];
mat(&colu, arp);
felmnt(&colu, arp);
keepalive();
}
}
int main(void)
{
int ck = 0, ndx;
while(1)
{ // infinite loop
p3();
fflush(stdin);
printf("\nPause !!!");
getchar();
}
return 0;
}
I define a string array in main function, and I want to update it inside another function as follows:
#include <stdio.h>
#define SIZE 15
void read_arrays(char *competitors[SIZE], float points[SIZE], int numOfCompetitors)
{
for (int cntr = 0; cntr < numOfCompetitors; cntr++)
{
printf("Enter the name of competitor %d", cntr+1);
scanf("%s", &*competitors[cntr]);
printf("Enter the point of competitor %d", cntr+1);
scanf("%f", &points[cntr]);
}
}
int main()
{
char *competitors[SIZE];
float points[SIZE];
int numOfCompetitors = 0;
while (numOfCompetitors > 15 || numOfCompetitors < 1)
{
printf("Enter the number of competitors: ");
scanf("%d", &numOfCompetitors);
if (numOfCompetitors > 15) printf("Number of competitors cannot be more than 15!\n");
}
read_arrays(&*competitors[SIZE], &points[SIZE], numOfCompetitors);
printf("%f", points[0]);
}
But I get the following error:
cc homework2.c -o homework2
homework2.c: In function ‘main’:
homework2.c:28:14: warning: passing argument 1 of ‘read_arrays’ from incompatible pointer type [-Wincompatible-pointer-types]
read_arrays(&*competitors[SIZE], &points[SIZE], numOfCompetitors);
^
homework2.c:5:6: note: expected ‘char **’ but argument is of type ‘char *’
void read_arrays(char *competitors[SIZE], float points[SIZE], int numOfCompetitors)
I want to assign the values in array of strings with scanf in a loop. How I can manage to do that?
You can just use the name of the variable when you pass it to the function, you also need to specify the size of the char matrix (~ array of strings).
So this: read_arrays(&*competitors[SIZE], &points[SIZE], numOfCompetitors);
Becomes: read_arrays(competitors, points, numOfCompetitors);
Full code:
#include <stdio.h>
#define SIZE 15
void read_arrays(char competitors[SIZE][30], float points[SIZE], int numOfCompetitors)
{
for (int cntr = 0; cntr < numOfCompetitors; cntr++)
{
printf("Enter the name of competitor %d", cntr+1);
// We read up to 29 characters => no overflow as the size is up to 30
scanf("%29s", competitors[cntr]);
printf("Enter the point of competitor %d", cntr+1);
scanf("%f", &points[cntr]);
}
}
int main()
{
char competitors[SIZE][30];
float points[SIZE];
int numOfCompetitors = 0;
while (numOfCompetitors > 15 || numOfCompetitors < 1)
{
printf("Enter the number of competitors: ");
scanf("%d", &numOfCompetitors);
if (numOfCompetitors > 15) printf("Number of competitors cannot be more than 15!\n");
}
read_arrays(competitors, points, numOfCompetitors);
printf("%s", competitors[0]);
printf("%s", competitors[1]);
printf("%f", points[0]);
}
As an alternative to Daniel Illescas you could just allocate space for each competitor that you input. Just be sure to free them later.
#include <stdio.h>
#define SIZE 15
void read_arrays(char *competitors[SIZE], float points[SIZE], int numOfCompetitors)
{
for (int cntr = 0; cntr < numOfCompetitors; cntr++)
{
competitors[cntr] = (char*)calloc(1, 32);
printf("Enter the name of competitor %d", cntr + 1);
scanf("%s", competitors[cntr]);
printf("Enter the point of competitor %d", cntr + 1);
scanf("%f", &points[cntr]);
}
}
int main()
{
char *competitors[SIZE];
float points[SIZE];
int numOfCompetitors = 0;
while (numOfCompetitors > 15 || numOfCompetitors < 1)
{
printf("Enter the number of competitors: ");
scanf("%d", &numOfCompetitors);
if (numOfCompetitors > 15) printf("Number of competitors cannot be more than 15!\n");
}
read_arrays(competitors, points, numOfCompetitors);
printf("%f", points[0]);
}
my program is supposed to implement a dfa for a binary string... dfa is a machine that can be in only one state at a time (when you enter a string the machine should use it and at the last step it should reach to the final state. if so, we say that string is accepted by the machine) ...
this machine works this way:
at first program asks the number of states, if u consider my pic, u see that it has 3 states(q0,q1,q2) so we enter 3. then it asks about the number of inputs. my inputs are 0,1 so I enter 2... then it asks to enter the inputs, we enter 0 then 1! then it asks the number of final states, the final state here is only q1... so we enter it... then u see this: (q0,0) = q it means q0 goes to which state with 0... for example here q0 goes to q0 with 0 ... others are like that. after filling this part, we enter the sring and it would say if string is valid or not
here is the code:
#include<stdio.h>
#include<conio.h>
int ninputs;
int check(char,int ); //function declaration
int dfa[10][10];
char c[10], string[10];
int main()
{
int nstates, nfinals;
int f[10];
int i,j,s=0,final=0;
printf("enter the number of states that your dfa consist of \n");
scanf("%d",&nstates); // 3
printf("enter the number of input symbol that dfa have \n");
scanf("%d",&ninputs); // 2
printf("\nenter input symbols\t");
for(i=0; i<ninputs; i++)
{
printf("\n\n %d input\t", i+1);
printf("%c",c[i]=getch()); // 01
}
printf("\n\nenter number of final states\t");
scanf("%d",&nfinals); // 1
for(i=0;i<nfinals;i++)
{
printf("\n\nFinal state %d : q",i+1);
scanf("%d",&f[i]); // 1
}
printf("-----------------------------------------------------------------------");
printf("\n\ndefine transition rule as (initial state, input symbol ) = final state\n");
for(i=0; i<ninputs; i++)
{
for(j=0; j<nstates; j++)
{
printf("\n(q%d , %c ) = q",j,c[i]);
scanf("%d",&dfa[i][j]);
// q(0,0)=0
// q(1,0)=0
// q(2,0)=2
// q(0,1)=1
// q(1,1)=2
// q(2,1)=1
}
}
do
{
i=0;
printf("\n\nEnter Input String.. ");
scanf("%s",string); // 01
while(string[i]!='\0')
{
if((s=check(string[i++],s))<0)
break;
for(i=0 ;i<nfinals ;i++)
{
if(f[i] ==s )
final=1;
if(final==1)
printf("\n valid string");
else
printf("invalid string");
getch();
printf("\nDo you want to continue.? \n(y/n) ");
}
}
}
while(getch()=='y');
getch();
}
int check(char b,int d)
{
int j;
for(j=0; j<ninputs; j++)
if(b==c[j])
return(dfa[d][j]);
return -1;
}
the problem is that when I enter my string, the program says it's invalid, however it should be accepted by the machine... for example consider the machine in the photo and test this string on it: 01
so what's wrong with the code?
Optimized C code for Accepting String using DFA
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
int a,b,i,j,k,state,ch;
char s[10][10],*st,v[10],ss[10];
printf("Enter the number of state:\n");
scanf("%d",&a);
printf("Enter State :\n");
for(i=0;i<a;i++)
{
fflush(stdin);
scanf("%c",&ss[i]);
}
printf("Enter th no. of var..:\n");
scanf("%d",&b);
printf("Enter variable :\n");
for(i=0;i<b;i++)
{
fflush(stdin);
scanf("%c",&v[i]);
}
printf("Enter table:\n");
for(i=0;i<a;i++)
{
for(j=0;j<b;j++)
{
fflush(stdin);
scanf("%c",&s[i][j]);
}
}
printf("Enter string :\n");
fflush(stdin);
gets(st);
i=0;
state=0;
while(st[i]!='\0')
{
for(j=0;j<b;j++)
{
if(st[i]==v[j])
{
if(s[state][j]=='-')
{
goto check;
}
else
{
for(k=0;k<a;k++)
{
if(s[state][j]==ss[k])
{
printf("State:%c\n",s[state][j]);
state=k;
goto o;
}
}
}
o:
}
}
i++;
}
check:
ch=1;
for(i=0;i<b;i++)
{
if(s[state][i]!='-')
{
ch=0;
}
}
if(ch==1)
{
printf("String is matching..");
}
else
{
printf("String is not matching..");
}
getch();
return 0;
}
Just put an space before %c . And edit some lines of the code.
This code is successfully complied on Code::Blocks 13.12 version.
As it C++ Compiler save the file with .cpp extension.
And Click On the " output image " . You will see how to input & output from
console
<--------Here Is the edited code && It will work fine ---> #
output image
#include<stdio.h>
#include<cstdio>
#include<iostream>
int ninputs,bb;
int check(char,int ); //function declaration
int dfa[10][10];
char c[10], string[10],b;
int main()
{
int nstates, nfinals;
int f[10];
int i,j,s=0,final=0;
printf("enter the number of states that your dfa consist of \n");
scanf("%d",&nstates);
printf("enter the number of input symbol that dfa have \n");
scanf("%d",&ninputs);
printf("\nenter input symbols");
for(i=0; i<ninputs; )
{
bb =i;
printf("\n %d input",bb+1);
// printf(" %c",c[i]=getchar());
scanf(" %c" , &c[i]); //just put an space before %c
i++;
}
printf("\n\nenter number of final states\t");
scanf("%d",&nfinals);
for(i=0;i<nfinals;i++)
{
printf("\n\nFinal state %d : q",i+1);
scanf("%d",&f[i]);
}
printf("-----------------------------------------------------------------------");
printf("\n\ndefine transition rule as (initial state, input symbol ) = final state\n");
for(i=0; i<ninputs; i++)
{
for(j=0; j<nstates; j++)
{
printf("\n(q%d , %c ) = q",j,c[i]);
scanf("%d",&dfa[i][j]);
}
}
do
{
i=0;
printf("\n\nEnter Input String.. ");
scanf("%s",string);
while(string[i]!='\0')
if((s=check(string[i++],s))<0)
break;
for(i=0 ;i<nfinals ;i++)
if(f[i] ==s )
final=1;
if(final==1)
printf("\n valid string");
else
printf("invalid string");
printf("\nDo you want to continue.? \n(y/n) ");
}
while(b =='y');
scanf(" %c", &b); // chnge here
}
int check(char b,int d)
{
int j;
for(j=0; j<ninputs; j++)
if(b==c[j])
return(dfa[d][j]);
return -1;
}
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
main()
{
int state,symbol;
char str[30];
cout<<"Enter the string which you want to check :: "<<endl;
fgets(str,sizeof(str),stdin);
cout<<"Enter the Number of state :: ";cin>>state;
cout<<"Enter the Number of input symbol :: ";cin>>symbol;
cout<<"Enter the states : "<<endl;
char st[state];
for(int i=0;i<state;i++)
{
cout<<"state : "<<i<<" : ";cin>>st[i];
}
cout<<"Enter the input symbol : "<<endl;
char sy[symbol];
for(int i=0;i<symbol;i++)
{
cout<<"symbol : "<<i<<" : ";cin>>sy[i];
}
char table[state][symbol];
cout<<"------Enter next move or state------ if no relation put -"<<endl;
for(int i=0;i<state;i++)
{
for(int j=0;j<symbol;j++)
{
cout<<"("<<st[i]<<", "<<sy[j]<<") = ";cin>>table[i][j];
}
}
char ststate,fnstate;
cout<<"Start state :: ";cin>>ststate;
cout<<"Final state :: ";cin>>fnstate;
cout<<"----------------------------------"<<endl;
int str_len=strlen(str);
int p,q;
int flag=1;
int j=0;
for(j=0;j<str_len-1;j++)
{
cout<<"input state"<<endl;
for(int i=0;i<state;i++)
{
if(st[i]==ststate)
{
p=i;
cout<<p<<endl;
break;
}
else
{
p=-1;
}
}
cout<<"input string"<<endl;
for(int i=0;i<state;i++)
{
if(sy[i]==str[j])
{
q=i;
// cout<<q<<endl;
break;
}
else
{
q=-1;
}
}
if(p!=-1 && q!=-1)
{
cout<<"table output :: "<<table[p][q]<<endl;
ststate=table[p][q];
}
}
cout<<endl;
cout<<"----------------------------------------------------------------------------------";
if((table[p][q]==fnstate) && (j==str_len-1))
{
cout<<"String is recognized"<<endl;
flag=0;
}
if(flag!=0)
{
cout<<"String is not recognized.";
}
cout<<endl;
return 0;
}
This part of the code:
while(string[i]!='\0')
{
if((s=check(string[i++],s))<0)
break;
for(i=0 ;i<nfinals ;i++)
{
uses and changes i in both loops. You need to use something else in one of them.
I need help on two questions, Its not homework but its to study for an exam. I need to have these questions because i was allowed 1 full page of notes for the exam. If you could help me these two simple questions for me that would be great. Here are the questions:
"Write a function called getGrades. The function that repeatedly prompts the user for positive integers until the user enters a negative value to stop. The function should return the average of these grades and the highest grade."
"Write a function called Get_Info that takes a pointer to a student structure, (that has three fields: char array called name, an int id, and a double gpa) as its only argument. The function prompts the user for the required information to fill the structure and stores it in the appropriate fields."
What I have so far, Let me know if they are correct and if i need to add anything.
1.
double getGrades() {
double average;
double i;
For(i=1 ; i<i; i++)
{
printf("Enter Grade1:\n");
scanf("%lf", &i);
}
if (i<0)
{
(double) average == (grade1 + grade2 + grade3) / 3;
return average;
}
}
2.
typedef struct {
int id;
double gpa;
char name[SIZE];
} student;
void Get_Info(student list[], int num) {
int i;
for(i=0; i<num; i++) {
printf("\nName:%s", list[i].name);
printf("\nGPA:%lf", list[i].gpa);
printf("\nID: %d\n", list[i].id);
}
}
On #1: The requirement is that the function accept ints. You are scanning for doubles.
The requirement is "The function should return the average of these grades and the highest grade." You only return one double, when two different outputs are called for.
Your for loop is written as "For" (C is case-sensitive), and is based on the test i<i. When will i ever be less than itself??
Here's my version of it.
double getGrades(int* max)
{
int sum = 0;
int input;
int i = 0;
*max = 0;
printf("Enter Grade #%d:\n", i+1);
scanf("%d", &input);
while (input > 0) {
if (*max < input) {
*max = input;
}
sum = sum + input;
i++;
printf("Enter Grade #%d:\n", i+1);
scanf("%d", &input);
}
return i? ((double)sum / i) : 0;
}
Your #2 is much better than your #1, but still has some errors:
The requirement is that the function takes a pointer to a student struct, NOT an array.
It should then print a series of Prompts, and get a series of answers (just as you did in #1).
This is a sequence of printf/scanf.
And when using scanf, you typically pass the ADDRESS of the variable, using &.
(strings are a exception, however)
Here is my version:
typedef struct {
char name[SIZE];
int id;
double gpa;
} student;
void Get_Info(student* ps) {
printf("Enter Name\n");
scanf("%s", ps->name);
printf("Enter ID:\n");
scanf("%d", &ps->id);
printf("Enter GPA\n");
scanf("%lf", &ps->gpa);
}
Try this. It should seem intuitive enough:
double getGrades() {
double average;
double grade;
double total = 0;
int count = 0;
while (1) {
printf("Enter grade: ");
scanf("%d", &grade);
if (grade < 0) {
if (count == 0) {
average = 0;
break;
}
average = total/count;
break;
}
count++;
total += grade;
}
return average;
}