[I write the program in C language]
I would like to read a txt file containing StudentName, Score, and Remarks
The pattern of the txt file looks like this:
1,Adam Lambert,60,C
2,Josh Roberts,100,A
3,Catherine Zetta,80,B
I would like to store each data, respectively into an array
So I would have 3 arrays (to store StudentName, Scores, and Grades)
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <math.h>
char* studName[99];
char* grade[99];
char* grades[100][10];
char buff[1024];
int scores[100];
int score;
int index;
int size;
int index = 0;
int sum = 0;
double average = 0;
int main()
{
FILE *file;
file = fopen("notepad.txt", "r");
if(file == NULL){
printf("Data does not Exist");
}
else {
while(((fgets(buff,1024,file))!=NULL))
{
size = strlen(buff);
buff[size] = 0;
sscanf(buff, "%d, %[^,],%d, %[^,]", &index, studName,&score, grade);
printf("Student Name: %s\n", studName);
printf("Score: %d\n", score);
printf("Remark: %s\n", grade);
scores[index-1] = score;
grades[index-1][10] = grade;
sum+=score;
index++;
}
}
fclose(file);
average = sum/index;
printf("\nThe total score of student is: %d\n", sum);
printf("\nThe sum of student is: %d\n", index);
printf("\nThe average of students' score is: %2f\n", average);
for(int i = 0; i<3; i++){
printf("Score: %d\n", scores[i]);
printf("\nThe Remark is: %s\n", grades[i][10]);
}
getch();
return 0;
}
The code above had successfully stored the scores in int array. I had not really good in C, so I do not know how to store the char array for StudentName and Grades.
The abovde code gives the result of Grades stored is only the last grade on the txt file (in this case is 'B').
Would you please tell me what do I have to fix in order to achieve my goal?
My goal basically will be pretty much like this:
StudentName array contains {"Adam Lambert", "Josh Roberts", "Catherine Zetta"}
Scores array contains {60,100,80}
Grades array contains {"C", "A", "B"}
Thank you very much.
Change studName and grade from "char *" to "char". You want a buffer, not an array of pointers.
At the top add:
char * StudentName[100];
When setting "scores" and "grades" add:
StudentName[index-1] = strdup(studName);
Also change the "10" in the following line, the array only dimensions 0-9.
grades[index-1][10] = grade;
Try this:
float len=sizeof(string);
Just gives you the static size of the array string which is an array of 20 pointers and each pointer is 4 bytes, 20 * 4 bytes = 80 that's why it's always 80.
while (fgets(string[i], BUFSIZE, fp)) {
i++;
len+=strlen(string[i]);
string[i] = (char *)malloc(BUFSIZE);
}
If your recore size is fixed then u can use this:
Where fr is a file pointer
fscanf(fr, "Index: %d StuName: %s Score: %d Grade: %s ", &index, sname, &score, grade);
Related
I am trying to store data for Value, Weight and Cost from a file containing a table which contains three columns of numbers for Value, Weight and Cost. The table may vary in length (9 or 21 rows) depending on the file chosen by the user.
I am having trouble trying to store the data from this file to use in a brute force function to solve the problem.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int nr_rows;
int i = 1;
int j = 2;
int k = 3;
int l,m,n = 0;
int budget_cost;
int weight_lim;
char file_name[50];
float c[nr_rows][3];
char stringA[20] = "objectsA.txt";
char stringB[20] = "objectsB.txt";
printf("Enter the filename containing item listing: ");
scanf("%s", &file_name);
if(strcmp(file_name,stringA)==0)
{
nr_rows = 9;
}
else if(strcmp(file_name,stringB)==0)
{
nr_rows = 21;
}
printf("The number of rows is %d", nr_rows);
float value[nr_rows], weight[nr_rows], price[nr_rows];
FILE *fpointer;
fpointer = fopen(file_name, "r");
if(!fpointer)
{
printf("The file %s could not be opened.", file_name);
return 1;
}
j=0;
while(j<nr_rows)
{
i=0; // Skip the first line
while(i<3)
{
fscanf(fpointer, "%f", &c[j][i]);
//printf("%.0f\n", c[j][i]);
if(i=1) /* Change this if statement so that 1 ,4 ,7 ,10
etc. activates*/
{
c[j][i] = v[l];
l++;
printf("%f", v[l]);
}
else if(i=2)/* Change this if statement so that 2,5,8 etc.
activates*/
{
c[j][i] = w[m];
m++;
}
else if(i=3)/* Change this if statement so that 3,6,9 etc.
activates*/
{
c[j][i] = p[n];
n++;
}
i++;
}
j++;
}
fclose(fpointer);
//1. Read carefully your file name by doing:
scanf("%s", file_name); // instead of scanf("%s", &file_name);
//2. Declare c[nr_rows][3] only after reading "nr_rows"
//3. The main "while" loop could look like this
while(j < nr_rows)
{
fscanf(fpointer, "%f %f %f", &c[j][0], &c[j][1], &c[j][2]);
}
// Then,
fclose(fpointer);
I enter two names in this case 'Jack' and 'Sara' and when i want to printout
'Jack' and 'Sara', This only prints out the last name which is sara im just wonderig how can i solve this problem even i wanna use more names here is the code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char name[20];
int i;
printf("\n\n");
for(i = 1; i <= 2; i++)
{
printf("Person.%d FristName: ", i);
scanf(" %s", name);
}
printf("\n\nHi %s \n", name);
printf("Hi %s \n", name);
return 0;
}
And here is the Output:
Hi Sara
Hi Sara
I'm trying to practice using Quick Sort in C. My program is a simple array of structs that takes in command line args (name1 age 1 name2 age2...etc) and outputs said ages in descending order.
It works correctly ONLY if the last age inputted is the largest. Other than that I either get no output or Seg Fault 11. Does anyone have any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NameLen 80
void print_struct();
struct people
{
char name [NameLen + 1];
int age;
}; //defining a structure//
typedef struct people PERSON;
void quicksort(struct people list[],int,int);
int main(int argc, const char * argv[])
{
int i,j;
j = 0;
int l = ((argc/2)-1);
struct people list[l]; //maximum size of array of structs
if (argc %2 == 0) //if the number of arguments is an even number
{
printf("Invalid Arguments!\n");
printf("Usage : ./hw5 name1 age1 name2 age2 ... "); //print error message and correct program usage
exit(0);
}
printf("You have entered %d persons(s) into the program \n",(argc/2));
for (i=1; i < argc; i+=2)
{
strcpy(list[j].name, argv[i]);
list[j].age = atoi(argv[i+1]);
if(list[j].age == 0)
{
printf("...Invalid age <=0. Try again.\n");
exit(0);
}
j++;
}
printf("Unsorted Names: \n");
print_struct(&list,argc);
printf ("Sorted by Age: \n");
quicksort(list,0 ,j);
for(i=0;i<j;i++){
printf("Name : %s| Age : %d\n", list[i].name, list[i].age);}//possible error here?
//Quicksort Function
Perhaps the problem is the value of j. Is j the length of list? Or the length of list - 1?
It seems like this would be what you would want:
j = length of list
printf ("Sorted by Age: \n");
quicksort(list,0 ,j-1);
for(i=0;i<j;i++){
printf("Name : %s| Age : %d\n", list[i].name, list[i].age);}
The quicksort function is fine. The issue is that you're calling it wrong:
quicksort(list,0 ,j);
The values you're passing in for first and last represent the index of the first and last elements. As evident from how you use j to loop through the elements, j is the number of elements. That means that the last element has index j-1.
So you're passing a value for last that is one element past the end of the array. When you then try to read/write this bogus element, you invoke undefined behavior which in your case (fortunately) leads to a segfault.
Pass in the actual index of the last element (i.e. one less than the size) and it runs successfully.
quicksort(list,0 ,j - 1);
Your loops are incorrect:
while(list[i].age<=list[pivot].age&&i<last)
i++;
It is possible for this loop to end with i == last, which is bad because you attempt to swap the value, which would be out of scope of the array.
while(list[j].age>list[pivot].age)
j--;
Here, since j starts as last, you start right off with reading outside of the array.
One possible remedy is to move j backwards first, then test (do-while style). Then, increment i, testing against the decremented j.
do --j; while(list[j].age>list[pivot].age);
do ++i; while(list[i].age<=list[pivot].age&&i<j);
I made the code a little bit simple (changed the array of chars to just a char to make it more simple as possible).
My thoughts are that when you call:
quicksort(list,0 ,j);
What you should call is:
quicksort(list,0 ,j-1);
Because the last parameter must be the array lenght minus 1, the last position.
I got no seg fault, when running your code, or the one I modified, if it is possible, double check the strings you are using as input.
Here is "my" vesion of the code.
Hope it helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NameLen 80
void print_struct();
struct people
{
char name;
int age;
}; //defining a structure//
typedef struct people PERSON;
void quicksort(struct people list[],int,int);
int main(int argc, const char * argv[])
{
int i,j;
j = 10;
struct people list[10]; //maximum size of array of structs
for (i=0; i < 10; i++)
{
list[i].name = 'a';
list[i].age = 10-i;
}
printf("Unsorted Names: \n");
for(i=0;i<j;i++){
printf("Name : %c| Age : %d\n", list[i].name, list[i].age);}//possible error here?
printf ("Sorted by Age: \n");
quicksort(list,0 ,j-1);
for(i=0;i<j;i++){
printf("Name : %c| Age : %d\n", list[i].name, list[i].age);}//possible error here?
}
void quicksort(struct people list[],int first,int last)
{
struct people temp;
int i,j,pivot;
if(first<last){
pivot=first;
i=first;
j=last;
while(i<j)
{
while(list[i].age<=list[pivot].age&&i<last)
i++;
while(list[j].age>list[pivot].age)
j--;
if(i<j){
temp=list[i];
list[i]=list[j];
list[j]=temp;
}
}
temp=list[pivot];
list[pivot]=list[j];
list[j]=temp;
quicksort(list,first,j-1);
quicksort(list,j+1,last);
}
}
after applying all the comments, this is the resulting code, which cleanly compiles, but will not link due to the two missing functions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_LEN (80)
struct people
{
char name [NAME_LEN + 1];
int age;
}; //defining a structure//
typedef struct people PERSON;
// print_struct( ptrToList, numElements )
void print_struct( PERSON *, int );
// quicksort( ptrToList, firstOffset, numElements )
void quicksort(struct people list[],int,int);
int main(int argc, const char * argv[])
{
//int i,j;
//j = 0;
//int l = ((argc/2)-1);
int l = argc/2;
struct people list[l]; //maximum size of array of structs
if (argc %2 == 0) //if the number of arguments is an even number
{
//printf("Invalid Arguments!\n");
fprintf( stderr, "Invalid Arguments!\n" );
//printf("Usage : ./hw5 name1 age1 name2 age2 ... "); //print error message and correct program usage
fprintf( stderr, "Usage : %s name1 age1 name2 age2 ... ", argv[0]);
// exit(0);
exit( EXIT_FAILURE );
}
//printf("You have entered %d persons(s) into the program \n",(argc/2));
printf("You have entered %d persons(s) into the program \n", l);
//for (int i=1; i < argc; i+=2)
for (int i=1, j=0; j < l; i+=2, j++)
{
//strcpy(list[j].name, argv[i]);
memset( list[i].name, '\0', NAME_LEN+1);
strncpy( list[j].name, argv[i], NAME_LEN );
list[j].age = atoi(argv[i+1]);
if(list[j].age == 0)
{
fprintf( stderr, "...Invalid age <=0. Try again.\n");
//exit(0);
exit( EXIT_FAILURE );
}
//j++;
}
printf("Unsorted Names: \n");
//print_struct(&list,argc);
print_struct( list, l );
//printf ("Sorted by Age: \n");
//quicksort(list,0 ,j);
quicksort( list, 0, l );
printf ("Sorted by Age: \n");
// //for(i=0;i<j;i++)
//for( int i=0; i<l; i++ )
//{
// printf("Name : %s| Age : %d\n", list[i].name, list[i].age);
//}//possible error here?
//}
print_struct( list, l);
} // end function: main
//Quicksort Function
if i have file contain students scores
for example this file
{
students scores :
100
90
83
70
}
how i can read just the values of scores with out reading "students scores :"???
mu code is already ok
but the problem in reading values
this is my code
#include <stdio.h>
int main (void)
{
FILE *infile;
double score, sum=0, average;
int count=0, input_status;
infile = fopen("scores.txt", "r");
input_status = fscanf(infile, "%lf", &score);
while (input_status != EOF)
{
printf("%.2f\n ", score);
sum += score;
count++;
input_status = fscanf(infile, "%lf", &score);
}
average = sum / count;
printf("\nSum of the scores is %f\n", sum);
printf("Average score is %.2f\n", average);
fclose(infile);
getch();
}
Problems I see:
input_status = fscanf(infile, "%lf", &score);
while (input_status != EOF)
is not right. The returned value of fscanf will be 0 if the read was not successful and 1 if it was successful.
More importantly, you need to add code that skips everything upto the point where you expect to see the numbers.
char line[100];
while ( fgets(line, 100, infile) != NULL )
{
// If the line containing "students scores :"
// is found, break from the while loop.
if (strstr(line, "students scores :") != NULL )
{
break;
}
}
Then, change start of the lines that read the data into:
input_status = fscanf(infile, "%lf", &score);
while (input_status == 1 )
Here's a fairly easy way to parse the file.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main (void)
{
FILE *infile;
char lineBuf[255+1];
double score, sum=0, average;
int count=0;
int fieldsParsed;
infile = fopen("scores.txt", "r");
/** Read a line from the file. **/
while(fgets(lineBuf, sizeof(lineBuf), infile))
{
/** Is the first character of the line a digit? **/
if(!isdigit(*lineBuf))
continue; /* It is not a digit. Go get the next line. */
/** Convert the number string (in lineBuf) to an integer (score). **/
score=atof(lineBuf);
printf("fields[%d] %.2f\n ", fieldsParsed, score);
sum += score;
count++;
}
average = sum / count;
printf("\nSum of the scores is %f\n", sum);
printf("Average score is %.2f\n", average);
fclose(infile);
// getch(); Non-portable
return(0);
}
Use fseek() to skip past the leading bytes to the numbers.
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.