Reading a file in C and store data in arrays - c

My code below reads a file in C.It displays the file, the average score, maximum score,and the names of all the students who earned the maximum score. The exam scores(0-100 format to 1 decimal place and use a field width of columns) are stored in an array and the names(name and last name limited to 15 characters) are stored in a 2-dimensional array of characters that is parallel to the scores array. My problems are:
1) The code doesn't read(print) the file properly (I think is related to fscanf and the arrays).
2) My two functions don't print the results.
Any suggestion is appreciated, thanks.
#include "tools.h"
#define MAX 30 // Maximum number of students
int computeMax(double stSco[], int numSt); // Gets the average and highest
// score
void outputBest(double num[], char nameHg[][15], int hgPl, int totStu);
int main()
{
double score[MAX];
char name[MAX][15];
char fileName[80];
int k, count = 0, hgCt;
stream dataFile;
banner();
printf("Type the name of file you want to read\n");
scanf("%79[^/n]", fileName);
dataFile = fopen(fileName, "r");
if (dataFile == NULL)
{
fatal("Cannot open %s for input", fileName);
}
while (!feof(dataFile))
{
fscanf(dataFile, "(%lg,%s)", &score[k], &name[k]);
printf("%6.1f %s\n", score[k], name[k]);
count++; // It counts how many students there are
}
hgCt = computeMax(score, count); // Stores the value sent by the
// function
outputBest(score, name, hgCt, count);
fclose(dataFile);
bye();
return 0;
}
int computeMax(double stSco[], int numSt)
{
int k, maxScore = 0, sum = 0;
double maximum = 0, average = 0;
for (k = 0; k < numSt; k++)
{
sum += stSco[k]; // It sums all scores
if (stSco[k] > maximum)
{
maximum = stSco[k];
maxScore = k; // Stores the index of the maximum score
}
}
average = sum / numSt;
printf("The average score is %d\n", average);
printf("The maximum score is %d\n", maximum);
return maxScore;
}
void outputBest(double num[], char nameHg[][15], int hgPl, int totStu)
{
int k;
for (k = 0; k < totStu; k++)
{
if (num[k] = hgPl)
{ // It finds who has the highest score
printf("%s got the highest score\n", nameHg[k]);
}
}
}

First: scanf("%79[^/n]",fileName); should be scanf("%79[^\n]",fileName);, better to use fgets().
Second typo mistake: misspelled == by = in if() condition
if(num[k]=hgPl){ //It finds who has the highest score
// ^ = wrong
should be:
if(num[k] == hgPl){ //It finds who has the highest score
Edit:
Error in while loop..
fscanf(dataFile, "(%lg,%s)", &score[k], &name[k]);
// ^ ^ ^ remove ^
should be:
fscanf(dataFile, "%lg%14s", &score[k], name[k]);
and increment k in while loop. after printf("%6.1f %s\n", score[k], name[k]);.

Related

Sorting array elements to find the largest and smallest number in C

I'm solving this problem where I need to give some inputs, find the largest and smallest among them. Here is the problem statement
Ivan Vasilyevich came to the market and decided to buy two watermelons: one for himself and another for the wife's mother. It is clear to choose for himself the heaviest watermelon, and for mother-in-law the lightest. But there is one problem: there are many watermelons and he does not know how to choose the lightest and the heaviest one. Help him!
Input
The first line contains the number of watermelons n (n ≤ 30000). The second line contains n numbers, each number is a mass of corresponding watermelon. All weights of watermelons are positive integers and do not exceed 30000.
Output
Print two numbers: the weight of watermelon that Ivan Vasilyevich will buy for his mother-in-law and the weight of watermelon that he will buy himself, or print the message "Ooops!" (without quotes), if someone left without watermelon
Here's my code
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, w[30000], gw, lw;
scanf("%d", &n);
n = abs(n);
for (i = 0; i < n; i++)
{
scanf("%d", &w[i]);
}
if (n >= 2)
{
for (i = 0; i < n; i++)
{
if (w[0] < w[i])
w[0] = w[i];
gw = w[0];
}
for (i = 0; i < n; i++)
{
if (w[0] > w[i])
w[0] = w[i];
lw = w[0];
}
printf("%d %d", lw, gw);
return 0;
}
else
{
printf("Ooops!");
return 0;
}
}
I'm getting wrong answer(96/100). What am I getting wrong?
You do not need to allocate space for an array of 30k integers to find the min and max weights entered.
First, initialize min and max weights to the first integer entered and then update min and max accordingly as you read more weights. Use the variable cur (an integer) to store the last integer (i.e. weight) read.
That way, you do it all in one pass, rather than in multiple loops.
If you use scanf, it is good practice to check it's return value. For reference (from the C99 standard):
The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
In our case, when our scanf call is of the form scanf("%d", &a) where a is some int, we expect the call scanf("%d", &a) to return 1.
While it is good practice to check the return value, it is not absolutely necessary. If this is a program for one of your classes and you have never worked with the return value of scanf, you could remove all the checks for the return value below and the program should function the same. That said, it would show great initiative if you do check for the return value and reference the C standard in your justification for checking it (as the return value provides very useful information).
#include <stdio.h>
#include <stdlib.h>
#define MAX_WAT 30000 /* maximum number of watermelons */
int main(void) {
int n, i, min, max, cur;
/* prompt user for number of watermelons */
printf("Enter number of watermelons: ");
/* read integer, checking return value of scanf as expected */
if (scanf("%d", &n) != 1) {
printf("error in scanf\n");
exit(EXIT_FAILURE);
}
if (n > MAX_WAT) {
printf("Please enter less than %d watermelons.\n", MAX_WAT);
return 0;
}
/* if zero or one watermelons, at least one person leaves without */
if (n <= 1) {
printf("Ooops!\n");
return 0;
}
/* initialize min, max to first integer and update
min, max accordingly as new weights are read */
printf("Enter weights of %d watermelons: ", n);
scanf("%d", &cur);
min = max = cur;
for (i = 1; i < n; i++) {
if (scanf("%d", &cur) != 1) {
printf("error in scanf\n");
exit(EXIT_FAILURE);
}
if (cur < min)
min = cur;
if (cur > max)
max = cur;
}
printf("Ivan Vasilyevich: %d\nMother: %d\n", max, min);
return 0;
}
Example Session 1:
Enter number of watermelons: 5
Enter weights of 5 watermelons: 2 5 1 9 10
Ivan Vasilyevich: 10
Mother: 1
Example Session 2:
Enter number of watermelons: 1
Ooops!
Example Session 3:
Enter number of watermelons: 30001
Please enter less than 30000 watermelons.
do not modify your original array
initialize your gw and lw
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, w[30000], gw, lw;
scanf("%d", &n);
n = abs(n);
for (i = 0; i < n; i++)
{
scanf("%d", &w[i]);
}
if (n >= 2)
{
gw = w[0];
for (i = 0; i < n; i++)
{
if (gw < w[i]) gw = w[i];
}
lw = w[0];
for (i = 0; i < n; i++)
{
if (lw > w[i]) lw = w[i];
}
printf("%d %d", lw, gw);
return 0;
}
else
{
printf("Ooops!");
return 0;
}
}

C Programming - Generating Random Numbers into a new text File and retrieving them to count the occurrences (then do statistics on the side)

My goal is to generate random numbers into a new txt file where I can retrieve the randomly generated values and count the occurrences of the values (e.g. Number 1 has appeared "x" number of times). My expected output should display an output like the example given and all the occurrences should add up to 600. There is an underline on the last bracket in my newfile() function. Thanks in advance.
First 10 lines of txt output file...
2
5
4
2
6
2
5
1
4
2
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int newfile(FILE *fp)
{
char fname[20];
printf("\nEnter the name of the file... ");
scanf("%19s",fname);//File name cannot have spaces
strcat(fname, ".txt");
fp=fopen(fname, "w");
int i, N = 600, newfile[N];
for(i=0;i<N;i++)
{
newfile[i]= ((rand() % 6)+1);
fprintf(fp,"%d\n",newfile[i]);
}
}
int main()
{
int i = 0;
FILE *fp;
do
{
newfile(fp);
i++;
}
while (i<1);
FILE* fpointer;
char filename[20];
int value = 0, result = 0, num[600] = { 0 };
float sum, mean;
printf("\nEnter the name of the file... ");
scanf("%19s",filename);
fpointer = fopen(filename, "r");
if (fpointer == NULL) {
printf("ERROR: CANNOT OPEN FILE!\n");
return -1;
}
result = fscanf(fpointer, "%d", &value);
while (result == 1)
{
{
num[value] = num[value] + 1; // num[value]++
}
result = fscanf(fpointer, "%d", &value);
}
for (int i = 0; i <= 6; i++) {
if (num[i] > 0) {
printf("Number %i has appeared %d times\n", i, num[i]);
}
}
sum = (1*(num[1])+2*(num[2])+3*(num[3])+4*(num[4])+5*(num[5])+6*(num[6]));
mean = sum / 600;
printf("\nThe mean is %f",mean);
fclose(fpointer);
return 0;
}
The main problem in your code is that you forgot to close the file inside newfile function.
So just add fclose(fp); at the end of the function.
Minor issues:
you don't need to pass fp to the function newfile. Just use a local variable.
newfile[N] is not needed at all. Simply do: fprintf(fp,"%d\n", (rand() % 6)+1);
num[600] = { 0 }; is much too large as you only use index 0 .. 6
Before doing num[value] = ... you should check that value is in the expected range, i.e. to avoid writing out of bounds.

How do I print ordinal indicators in a C program? Can't print numbers with 'st', 'nd', 'rd'. (Beginner)

#include <stdio.h>
main()
{
int i, num, sum=0; //declaration
printf("How many numbers do you want to calculate average of?\n");
scanf("%d", &num); //how many numbers are to be calculated
printf("Enter %d numbers\n", num);
int a[num]; //array to store data
for(i=1;i<=num;i++) //loop to take input
{
if(i==1) //for 1st
printf("1st value : ");
else if (i<=2) //2nd
printf("2nd value : ");
else if (i<=3) //3rd
printf("3rd value : ");
else //else print th ordinal
printf("%dth value : ", i);
scanf("%d", &a[i]);
}
for(i=1;i<=num;i++)
sum+=a[i];
float avg;
avg=sum/num;
printf("Average : %f", avg);
return 0;
}
A program to take out the average of n numbers.
Now, this code does what it should, but if the size of the array goes beyond 20, it prints 21th, 22th, 23th and so on, which is wrong. I can't think of how to fix this problem. Any help would be great. I am new to programming, so pardon my ignorance.
There isn't a standard function that does that. You can write one, or use mine:
ordinal.c
#include "ordinal.h"
#include <stdio.h>
static const char *const suffixes[4] = { "th", "st", "nd", "rd" };
enum { NUM_SUFFIXES = sizeof(suffixes) / sizeof(suffixes[0]) };
static unsigned suffix_index(unsigned n)
{
unsigned x;
x = n % 100;
if (x == 11 || x == 12 || x == 13)
x = 0;
else if ((x = x % 10) > 3)
x = 0;
return x;
}
char *fmt_ordinal(char *buffer, size_t buflen, unsigned n)
{
unsigned x = suffix_index(n);
int len = snprintf(buffer, buflen, "%u%s", n, suffixes[x]);
if (len <= 0 || (size_t)len >= buflen)
return 0;
return(buffer);
}
ordinal.h
/* returns buffer or 0 on failure (implausible unless buffer too small) */
extern char *fmt_ordinal(char *buffer, size_t buflen, unsigned n);
Some of that is overkill on its own, but the source file also contains scn_ordinal() which scans ordinal numbers with greater or lesser strictness, and the header declares it.
int main(void)
{
char buffer[15];
/* Test fmt_ordinal() */
for (unsigned i = 0; i < 35; i++)
printf("%2u => %4s\n", i, fmt_ordinal(buffer, sizeof(buffer), i));
return 0;
}
You can mod by 10 to get the last digit. Then based on that you can use "st", "nd", "rd", or "th". You'll also need special cases for 11, 12, and 13.
if ((i % 10 == 1) && (i % 100 != 11))
printf("%dst value : ", i);
else if ((i % 10 == 2) && (i % 100 != 12))
printf("%dnd value : ", i);
else if ((i % 10 == 3) && (i % 100 != 13))
printf("%drd value : ", i);
else
printf("%dth value : ", i);
I played with this a bit and this was my minimal 'lookup' except, sadly, for the expense of the modulo division. I wasn't fussed about values above 99.
if( i > 20 ) i %= 10; // Change 21-99 to 1-10.
if( i > 3 ) i = 0; // Every other one ends with "th"
// 0 1 2 3
suffix = &"th\0st\0nd\0rd"[ i * 3 ]; // Acknowledge 3byte regions.
You can use 'suffix' as a pointer to a normal null terminated string.
It is okay to be a beginner, no need to apologize. You can solve your problem using a combination of a SWITCH statement and the modulus operator (%). The modulus operator takes two numbers (n1 % n2) and returns the remainder when n1 is divided by n2.
You will want to construct an array of ordinals, like this:
char *ordinalList[] = { "st", "nd", "rd", "th" };
This will allow you to simply reference this array to append the correct ordinal to a number. The next step is to create an algorithm to determine which array index should be referenced. To do this, you can make a new function and call it in your "main".
char *determineOrdinal (char **ordinalList, int numValue)
{
if (3 < numValue && numValue < 21)
return ordinals[3];
switch (numValue % 10) {
case 1 : return ordinalList[0];
break;
case 2 : return ordinalList[1];
break;
case 3 : return ordinalList[2];
break;
default: return ordinalList[3];
break;
}
You can pass a number into this function as the numValue argument. Your "main" function might look something like this:
#include <stdio.h>
int main(void)
{
char *ordinalList[] = { "st", "nd", "rd", "th" };
char *currentdOrdinal;
int i, num, sum=0; //declaration
printf("How many numbers do you want to calculate average of?\n");
scanf("%d", &num); //how many numbers are to be calculated
printf("Enter %d numbers\n", num);
int a[num]; //array to store data
for(i=1;i<=num;i++) //loop to take input
{
currentdOrdinal = determineOrdinal (ordinalList, i)
printf("%d%s value : ", i, currentdOrdinal);
scanf("%d", &a[i]);
}
for(i=1;i<=num;i++)
sum+=a[i];
float avg;
avg=sum/num;
printf("Average : %f", avg);
return 0;
}
I think that code should work for you. I hope this helps.

uninitialized variable in function

for the function below i have to sort an array of employees by age in descending order and need the size but cant put it in the function variables, my teacher told me to compute the size by doing this in main but for the loop with j in it it tells me elementSize may be used unitialized in this function. In main it says the int elementSize = " " elementSize is an unused variable.
int elementSize = sizeof(employeeList)/sizeof(Employee);//getting the size of the list
main
#include "lab10.h"
int main() {
Employee employeeList[10000];
readfile(employeeList);
clock_t start,end;
double cpu_time_used;
start = clock();
int elementSize = sizeof(employeeList)/sizeof(Employee);//getting the size of the list
bubbleSort(employeeList);//call bubble sort function to sort list in descending order
printList(employeeList, 25);
end = clock();
cpu_time_used = (double)(end-start)/CLOCKS_PER_SEC*1000;
printf("Time used to compute sorting was %f ms.\n",cpu_time_used);
int bin30=binSearch(employeeList, 0, 9999, 30);//binary search for people of the age of 30
if(bin30== -1){
printf("employees not found!\n");//if employee of age 30 arent found
} else {
printf("%s %s %d %d\n", employeeList[bin30].fname, employeeList[bin30].lname, employeeList[bin30].age, employeeList[bin30].salary); //print out employees info
printf("element present at index %d", bin30);
printf("time used is %f ms\n\n",cpu_time_used);//record time
}
int bin130=binSearch(employeeList, 0, 9999, 130);//binary search for people of the age of 30
if(bin130== -1){
printf("employees not found!\n");//if employee of age 130 arent found
} else {
printf("%s %s %d %d\n", employeeList[bin130].fname, employeeList[bin130].lname, employeeList[bin130].age, employeeList[bin130].salary); //print out employees info
printf("element present at index %d", bin130);
printf("time used is %f ms\n\n",cpu_time_used);//record time
}
return 0;
}
void bubbleSort(Employee employeeList[]) {
int swap;
int i=0;
int j=0;
for(i=0; elementSize > i; i++) {//for loop to sort
for(j=0; elementSize > j ;j++) {
if(employeeList[j+1].age > employeeList[j].age) {//comparing the two values
swap = employeeList[j].age;//swapping the temp variable with the employee
employeeList[j].age= employeeList[j+1].age;//setting the lower employeee to [j]
employeeList[j+1].age = swap;//setting the higher employee to [j+1]
}//end of if statement
}//end of second for loop
}//end of first for loop
}
#include "lab10.h"
//This function reads from a file and creates an array of Employee structure containing their information.
void readfile(Employee employeeList[]){
FILE *fp;
fp = fopen("employeeData.csv", "r");
int i = 0;
if (fp) {
while (i<10000){
fscanf(fp, "%[^,],%[^,],%d,%d\n",employeeList[i].fname,employeeList[i].lname,&employeeList[i].age,&employeeList[i].salary);
i++;
}
}
fclose(fp);
}
void printList(Employee employeeList[], int size)
{
int i=0;
for(i=0; i<size; i++)//going through the first 25 elements of the array
{
printf("%d ", employeeList[i].age);//printing off the elements
}
}
int binSearch(Employee employeeList[], int first, int last, int age)
{
if(first > last){
return -1;//base case
}
int mid= (first + last)/2;//finding middle of the array
if(age > employeeList[mid].age)
return binSearch(employeeList, mid+1, last, age);//searching for high in
binary search through recursion
else if(age < employeeList[mid].age)
return binSearch(employeeList, first, mid-1, age);//searching for low in binary search through recursion
else
return mid;//return the expected value
}
You actually have two variables named elementSize in this code, one global and one local to bubbleSort. The local variable is shadowing the global variable, meaning that the global is not visible. Only the local is visible, and that local was never initialized.
Remove the local elementSize variable and the global one will become visible and will be used.

Calculating Size of the Array

I'm trying to calculate the size of the file . The process I've followed is to read the file and store it in an array and calculate its size. However,I really don't know ... I tried n number of ways..I've to pass this size as an attribute to the frequency function.along with the name of the array.
#include <stdio.h>
#include<conio.h>
void frequency (int theArray [ ], int ??????, int x)
{
int count = 0;
int u;
for (u = 0; u < ??????; u++)
{
if ( theArray[u]==x)
{
count = count + 1 ;
/*printf("\n%d",theArray[u]);*/
}
else
{
count = count ;
}
}
printf ("\nThe frequency of %d in your array is %d ",x,count);
}
void main()
{
FILE*file = fopen("num.txt","r");
int integers[100];
int i=0;
int r = 0;
int num;
int theArray[100];
int there[100];
int n;
int g;
int x;
while(fscanf(file,"%d",&num)>0)
{
integers[i]=num;
printf("\n%d",(integers[i]));
there[r] = integers[i];
i++;
}
//printf("%d",there[r]);
//printf("\n%d",file);
//fclose(file);
printf ("\n OK, Thanks! Now What Number Do You Want To Search For Frequency In Your Array? ");
scanf("\n%d", &x);/*Stores Number To Search For Frequency*/
frequency(integers,????????,x);
getch();
fclose(file);
}
?????? is the size of the integer array from where i read the file and stored it.
I could not find a way to calculate the size of the array into which i copied my file. My idea is to calculate the frequency of a number in that file and calculate the probability of it's occurrence and thereby calculating entropy..Suggestions please!
I don't know why you are initializing so many variables and some of them with awkward names like ??????.
Your main problem is that the call to function should be
frequency(integers, i, x);
Your code with the awkward irrelevant parts removed will look like
#include <stdio.h>
#include<conio.h>
void frequency (int theArray [ ], int number, int x)
{
int count = 0;
int u;
for (u = 0; u < number; u++)
{
if ( theArray[u]==x)
count++;
}
printf ("\nThe frequency of %d in your array is %d ",x,count);
}
void main()
{
FILE*file = fopen("num.txt","r");
int integers[100];
int i=0;
int num;
int x;
while(fscanf(file,"%d",&num)>0)
{
integers[i]=num;
printf("\n%d",integers[i]);
i++;
}
printf ("\n OK, Thanks! Now What Number Do You Want To Search For Frequency In Your Array? ");
scanf(" %d", &x);/*Stores Number To Search For Frequency*/
frequency(integers,i,x);
getch();
fclose(file);
}
There are a lot of parts of this code that don't make sense, but I assume it is your debugging trying to figure out what is wrong. The answer to your specific question is:
For each value read from the file you set integers[i] to the value and then increment i. Thus i is the count of items in integers. You then pass integers to frequency(), so i should be passed to the second parameter as the count.
Note that if there are more than 100 values in the file, you will over index integers and cause unpredictable behavior.
To calculate length of array:
int len= sizeof(arr)/sizeof(arr[0]);
It will give length of array without looping.

Resources