Structure arrays in c - c

I am to read from a .ssv file and create a student database which contains: Name, ID, Exam1, Exam2, Project1, Project2, Average and Grade(letter). The average is not in the file, hence it having to be calculated. I am unsure of my average calculation and my structure declaration. Any other fixes would be welcomed.
#include <stdio.h>
typedef struct {
char name[26];
int I_D[25];
int exam[3];
int project[3]
float average[3];
char grade[3];
} STUDENT;
void printStuAry(int size, STUDENT stuAry[]);
int main(int argc, char* argv[])
{
if (argc != 2) {
printf("ERROR\n");
return 1;
}
STUDENT stuAry[5];
FILE* f = fopen(argv[1], "r");
if (f == NULL) {
printf("Error opening file %s.\n", argv[1]);
return 1;
}
char line[65];
int ind = 0;
while (fgets(line, sizeof(line), f) != NULL) {
sscanf(line, "%25[^;] ; %d %d %d %d %d %c",
stuAry[ind].name,
&stuAry[ind].I_D,
&stuAry[ind].exam[0],
&stuAry[ind].exam[1],
&stuAry[ind].project[0],
&stuAry[ind].project[1]
&stuAry[ind].grade);
float stuAry.average = stuAry.exam[0] + stuAry.exam[1] + stuAry.project[0] + stuAry.project[1]/4;
ind++;
}
printStuAry(5, stuAry);
if (fclose(f) == EOF) {
printf("Error closing file %s.\n", argv[1]);
return 1;
}
return 0;
}
void printStuAry(int size, STUDENT stuAry[])
{
for (int i=0; i<size; i++) {
printf("Student \"%s\" score %d, %d and %d and %d on midterms, "
"and %c on the final.\n",
stuAry[i].name, stuAry[i].exam[0],
stuAry[i].exam[1], stuAry[i].project[0],
stuAry[i].project[1], stuAry[i].average,
stuAry[i].final);
}
}

I will not rewrite the code for you, just indicate your errors.
int I_D[25];
why an array for the id, just an integer
int exam[3];
int project[3]
Since you have only 2 exams and 2 projects, the sizes should be 2.
missing ;
float average[3];
char grade[3];
should not be arrays...
while (fgets(line, sizeof(line), f) != NULL) {
sscanf(line, "%25[^;] ; %d %d %d %d %d %c", etc...
The correct way to read a well-formatted file is like this:
while(7 == fscanf(f, "%25[^;] ; %d %d %d %d %d %c", etc..))
float stuAry.average = stuAry.exam[0] + stuAry.exam[1] + stuAry.project[0] + stuAry.project[1]/4;
parenthesize the sum
divide by 4.0 to avoid integer division and get a float division with a float result
index the array by [ind] to work on the current student.
stuAry[ind].average = (stuAry[ind].exam[0] + stuAry[ind].exam[1] + stuAry[ind].project[0] + stuAry[ind].project[1])/4.0;
There are may be other errors but this should get you some good start

Related

Output Text from File in Reverse Order in C

I was trying to make a code on C, which reads the file.txt, outputs it into console, and then counts rows, words etc, and after all is exporting the content of file.txt to file2.txt but in reverse order.
The text need to go from this:
I
Love
You
to this:
ouY
evoL
I
What I have in my text.file:
enter image description here
What i get with my code now:
enter image description here
Here is my code that's need improvement, because it prints the code how i need but with blank rows, which is not needed. And it needs to be exporting into another file also:
fseek(fptr,0,SEEK_END);
pos=ftell(fptr);
i=0;
while(i<pos)
{
i++;
fseek(fptr,-i,SEEK_END);
ch=fgetc(fptr);
printf("%c",ch);
}
there's full code:
#include <stdio.h>
int main ()
{
FILE *fptr;
int i, n, j, pos;
char str[100];
char fname[20]="mfile.txt";
char newch[500];
int wrd=1,charctr=1,rows=1;
char str1;
char ch;
int no_lines = 1;
int COUNT = 0;
fptr = fopen(fname,"r");
if(fptr == NULL)
{
printf(" \n");
printf("File does not exist or can not be opened.");
}
else
{
ch=fgetc(fptr);
printf(" \n");
printf("The content of the file %s are: \n", fname);
printf(" \n");
while(ch != EOF)
{
printf("%c",ch);
if(ch==' '||ch=='\n')
{
wrd++;
}
else
{
charctr++;
}
if(ch=='\n')
{
rows++;
}
ch=fgetc(fptr);
}
int wrd1 = wrd - 1;
float charctr1 = charctr - 1;
float rows1 = rows;
float averageSymbol = charctr1 / rows1;
printf(" \n");
printf("\nwrd = %d, charctr = %d", wrd, charctr-1);
printf("\nThe number of rows in the file %s are : %d\n", fname,rows);
printf("\nThe average amount of symbols in a row is %f\n", averageSymbol);
printf(" \n");
}
fseek(fptr,0,SEEK_END);
pos=ftell(fptr);
i=0;
while(i<pos)
{
i++;
fseek(fptr,-i,SEEK_END);
ch=fgetc(fptr);
printf("%c",ch);
}
fclose(fptr);
return 0;
}
Ok so if I understand correctly you want to get rid of some of the empty lines which show up in your code and then you want to also write the output of the program (the reversed text) into another file? I am assuming that you want the sentences to be also in the original order.
#include <stdio.h>
int main ()
{
FILE *fptr;
FILE *fptr2;
int i, n, j, pos;
char str[100];
char fname[20]="mfile.txt";
char fname2[20]="outputfile.txt";
char newch[500];
int wrd=1,charctr=1,rows=1;
char str1;
char ch;
int no_lines = 1;
int COUNT = 0;
fptr2 = fopen(fname2, "w+");
fptr = fopen(fname,"r");
if(fptr == NULL)
{
printf(" \n");
printf("File does not exist or can not be opened.");
}
else
{
ch=fgetc(fptr);
printf("The content of the file %s are: \n", fname);
while(ch != EOF)
{
printf("%c",ch);
if(ch==' '||ch=='\n')
{
wrd++;
}
else
{
charctr++;
}
if(ch=='\n')
{
rows++;
}
ch=fgetc(fptr);
}
int wrd1 = wrd - 1;
float charctr1 = charctr - 1;
float rows1 = rows;
float averageSymbol = charctr1 / rows1;
printf("\nwrd = %d, charctr = %d", wrd, charctr-1);
printf("\nThe number of rows in the file %s are : %d\n", fname,rows);
printf("The average amount of symbols in a row is %f\n", averageSymbol);
}
fseek(fptr,0,SEEK_END);
pos=ftell(fptr);
i=0;
while(i<pos)
{
i++;
fseek(fptr,-i,SEEK_END);
ch=fgetc(fptr);
printf("%c",ch);
fputc(ch,fptr2);
}
fclose(fptr);
fclose(fptr2);
return 0;
}
This version first checks if a file called outputfile.txt exists and if no, it creates it. If said file already exists then the program overwrites the stuff which was originally in the file with the new program output (it doesn't clear the file all the way).

Fscanf Doesn't Take Inputs properly

I'm trying to take inputs with fscanf and to give output to another file but fscanf doesn't give the input it should give.
Here is my code:
#include <stdio.h>
int main() {
FILE *a;
FILE *b;
int i;
int played_matches, points, goaldif, ranking;
int wins, draws, losses, goals_scored, goals_against;
char team[18];
a = fopen("source.docx", "r");
b = fopen("aim.doc", "w");
for (i = 0; i < 10; i++) {
fscanf(a, "%d %s %d %d %d %d %d", &ranking, &team, &wins, &draws, &losses, &goals_scored, &goals_against);
played_matches = wins + draws + losses;
points = (3 * wins) + draws;
goaldif = goals_scored - goals_against;
fprintf(b, "%d %s %d %d %d ", ranking, team, played_matches, points, goaldif);
}
fclose(a);
fclose(b);
return 0;
}
#include <stdio.h>
int main() {
FILE *a;
FILE *b;
int i;
int played_matches, points, goaldif, ranking;
int wins, draws, losses, goals_scored, goals_against;
char team[18];
a = fopen("source.txt", "r");
b = fopen("aim.txt", "w");
for (i = 0; i < 10; i++) {
fscanf(a, "%d %s %d %d %d %d %d", &ranking, team, &wins, &draws, &losses, &goals_scored, &goals_against);
played_matches = wins + draws + losses;
points = (3 * wins) + draws;
goaldif = goals_scored - goals_against;
fprintf(b, "%d %s %d %d %d \n", ranking, team, played_matches, points, goaldif);
}
fclose(a);
fclose(b);
return 0;
}
& is for integer values.

C - read TXT change from dup to fgets and sscanf

I read from txt pairs of numbers
How check it only 2 numbers in each line and not 3. I want show the line is the problem for example the pairs file:
3
25 35
14 42
30 60 70
Console: illegal input at line 4
I know That's not the correct way at all. Need use fgets to read and sscanf to parse.
I tried but the memory full garbage. How can I change it correctly?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i, c;
FILE *fp;
char str[100];
fp = fopen("./pairs.txt", "r");
if (dup2(fileno(fp), STDIN_FILENO < 0))
{
printf("Error opening file");
return -1;
}
if (feof(fp))
printf("Error reading file");
scanf("%d", &numOfPairs);
arrNum = (int *)malloc(sizeof(int) * numOfPairs * numbersInPair);
for (int i = 0; i < numOfPairs * numbersInPair; i += 2)
{
int num1, num2;
scanf("%d %d", &num1, &num2);
arrNum[i] = num1;
arrNum[i + 1] = num2;
}
}
Another try NOT working:
int main(int argc, char *argv[])
{
int index, i, numOfPairs;
int c;
FILE *file;
file = fopen("./pairs.txt", "r");
if ((c = getc(file)) == EOF)
{
perror("Error opening file"); //or return 1;
fclose(file);
}
while ((c = getc(file)) != EOF)
putchar(c);
{
fscanf(file, "%d", &numOfPairs);
allNumbers = (int *)malloc(sizeof(int) * numOfPairs * numbersInPair); //need multiply in 2 numbers for each pair
while (!feof(file) && numOfPairs > 0)
{
int x, y, arrIndex = 0;
numOfPairs--;
fscanf(file, "%d %d", &x, &y);
allNumbers[arrIndex] = x;
printf("The X : %d\n", x);
allNumbers[arrIndex + 1] = y;
printf("THE Y : %d\n", y);
arrIndex + 2;
}
fclose(file);
}

C Problems with fscanf

Thanks for all the answers, after the corrections the code did not work for a stupid error ... I opened both files with the same file pointer "database" ...
I've read dozens of questions like this but I can't get out of it, I'm going crazy.
The exercise that I have to do asks me to organize the items of a list in a file .txt that has elements of the type: Name Surname Age Wage, in alphabetical order according to the surname.
I have already created a function to insert the elements into the file and it works well.
I then went to the function to organize them but the process stops after the fscanf, and putting some test printf I saw that no values are assigned to the strings or that are assigned absurd numbers.
Please help ... thanks.
This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 64
#define MAXFILE 100
void insert();
int fullcheck();
void sort();
typedef struct {
char name[MAX];
char surname[MAX];
int age;
double wage;
} data;
int main() {
insert();
return EXIT_SUCCESS;
}
void insert() {
char c;
int i;
data tmp;
FILE* database;
if ((fullcheck())>MAXFILE-1)
printf("Errore: database pieno.\n");
else {
database=fopen("database.txt", "a");
printf("Nome: ");
fgets(tmp.name, MAX, stdin);
tmp.name[strlen(tmp.name)-1]='\0';
printf("Cognome: ");
fgets(tmp.surname, MAX, stdin);
tmp.surname[strlen(tmp.surname)-1]='\0';
for (i=0; i<strlen(tmp.surname); i++) {
if (tmp.surname[i]==' ')
tmp.surname[i]='#';
}
printf("Eta': ");
scanf("%d", &tmp.age);
printf("Salario: ");
scanf("%lf", &tmp.wage);
while((c=getchar())!='\n');
fprintf(database, "%s %s %d %.0lf \n", tmp.name, tmp.surname, tmp.age, tmp.wage);
fflush(database); fclose(database);
if ((fullcheck())>1)
sort();
}
}
int fullcheck() {
char c;
int r=0;
FILE* database;
if ((database=fopen("database.txt", "r"))==NULL) {
return 0;
}
else {
while((c=getc(database))!=EOF) {
if(c=='\n')
r++;
}
return r;
}
}
void sort() {
char tmpstr[MAX];
int len=fullcheck(), i, a, b;
data tmp[len];
FILE* database;
FILE* sorted;
database=fopen("database.txt", "r");
database=fopen("sorted.txt", "w");
for (i=0; i<=len; i++) {
fscanf(database, "%s %s %d %lf \n", &tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage);
}
for (a=0 ; a<(len-1); a++) {
for (b=0; b<(len-1); b++) {
if ((tolower(tmp[b].surname[0]))>(tolower(tmp[b+1].surname[0]))) {
strcpy(tmpstr, tmp[b].surname);
strcpy(tmp[b].surname, tmp[b+1].surname);
strcpy(tmp[b+1].surname, tmpstr);
}
}
}
for (a=0; a<(len-1); a++) {
fprintf(sorted, "%s %s %d %.0lf \n", tmp[a].name, tmp[a].surname, tmp[a].age, tmp[a].wage);
}
fflush(database); fclose(database); remove("database.txt");
fflush(sorted); fclose(sorted); rename("sorted.txt", "database.txt");
}
Off by 1
Code attempts to read into len+1 elements of tmp[].
data tmp[len];
for (i=0; i<=len; i++) { // too many
fscanf(database, "%s %s %d %lf \n", &tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage);
}
I saw that no values are assigned to the strings (OP)
Better code would use width limits and test fscanf() result before using the data scanned.
// v---- < not <=
for (i=0; i<len; i++) {
if (fscanf(database, "%63s %63s %d %lf",
&tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage) != 4) {
// ^^^^ test!
break;
}
Even better code would read a line with fgets() into a stirng and then attempt to parse the string.
Off by 2
Code's attempt to find number of lines can be short by 1 if the last line does not end with a '\n'.
Alternative
size_t fullcheck(void) {
FILE* database = fopen("database.txt", "r");
if (database == NULL) {
return 0;
}
int previous = '\n';
int c;
size_t r=0;
while((c=getc(database))!=EOF) {
if (previous == '\n') r++;
previous = c;
}
fclose(database);
return r;
}
Missing fclose()
fullcheck() doesn't close the file after opening it.
int
Use an int to distinguish the typically 257 different returns values of fgetc(). Note when char` is unsinged, OP's code is an infinite loop.
More woes
The loop to print the sorted list is off-by-one, too short. And the sorting itself only looks at the first letter of each name, should use strcmp.
#user3386109
Maybe more?
Make sure to close the file here, before every return:
int fullcheck() {
char c;
int r=0;
FILE* database;
if ((database=fopen("database.txt", "r"))==NULL) {
fclose(database);
return 0;
}
else {
while((c=getc(database))!=EOF) {
if(c=='\n')
r++;
}
fclose(database);
return r;
}
}
And also a little bit fixing in the loop_counters here:
void sort() {
char tmpstr[MAX];
int len=fullcheck(), i, a, b;
data tmp[len];
FILE* database;
FILE* sorted;
database=fopen("database.txt", "r");
sorted=fopen("sorted.txt", "w+");
for (i=0; i<len; i++) {
fscanf(database, "%s %s %d %lf \n", &tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage);
printf("%s", tmp[b+1].surname);
system("pause");
}
for (a=0 ; a<(len); a++) {
for (b=0; b<(len); b++) {
if ((tolower(tmp[b].surname[0]))>(tolower(tmp[b+1].surname[0]))) {
strcpy(tmpstr, tmp[b].surname);
strcpy(tmp[b].surname, tmp[b+1].surname);
strcpy(tmp[b+1].surname, tmpstr);
printf("%s", tmp[b+1].surname);
system("pause");
}
}
}
for (a=0; a<(len); a++) {
fprintf(sorted, "%s %s %d %.0lf \n", tmp[a].name, tmp[a].surname, tmp[a].age, tmp[a].wage);
}
fclose(sorted);
fclose(database);
}

fgetc() doesn't work properly in function

I am trying to read a text file, character by character, with fgetc() function but it does not show any output. It is a school project and it is still in very very simple way just to test the functionality of the program.
#include <stdio.h>
#include <stdlib.h>
void fn1(FILE *f);
void fn9(FILE *fp, char, char);
int main() {
FILE *fp = fopen("text.txt", "r");
if (fp == NULL) {
perror("Error: ");
exit(1);
}
fn1(fp);
fn9(fp, '0', '9');
fclose(fp);
return 0;
}
void fn1(FILE *f) {
int num, sum = 0, count = 0;
while (fscanf(f, "%d", &num) == 1) {
if (num > 0) {
sum += num;
count++;
}
}
printf("the avg of positive nums is %.2f", (float) sum / count);
}
void fn9(FILE *fp, char m, char n) {
int ch;
int count1 = 0, count2 = 0;
while ((ch = fgetc(fp)) != EOF) {
if (ch == m)
count1++;
if (ch == n)
count2++;
printf("%c", ch);
if (ferror(fp))
break;
}
printf("\n%c is seen %d times", m, count1);
printf("\n%c is seen %d times", n, count2);
fclose(fp);
}
The file's content that I test is:
90
16
-34
100
After fn(fp) return, fp will point to the last location in the file. It needs to be reset to the start of file before fn9 is called. Use fseek to point fp to the start of file and it should work :)

Resources