How can I print out scanned in structure to file properly? (C) - c

I am trying to read from 2 files (f1.txt and f2.txt) using structures and print them out to the third file (f3.txt), but I seem to be getting some errors. Issues did not occur before I tried printing out the values to the file (fprintf command), and I cant seem to find a way to fix it..
This is for a homework assignment, but since I've been struggling to fix this issue for months now (yes, I'm pretty bad), I thought maybe anyone here knows how I can fix this.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX_NIME_PIKKUS 100
#define MAX_AINE_PIKKUS 100
#define MAX_KOOD 10
#define MAX_HINNE 5
#define DEBUG 0
int n;
int m;
struct Tudeng{
char Nimi[MAX_NIME_PIKKUS];
char Kood[MAX_KOOD];
};
struct Tudeng *pTudeng;
struct Aine{
char Nimetus[MAX_AINE_PIKKUS];
char aineKood[MAX_KOOD];
};
struct Aine *pAine;
struct Tud{
char Tudengikood[MAX_KOOD];
int Hinne[MAX_HINNE];
};
struct Tud *pTud;
char f1[] = "f1.txt";
char f2[] = "f2.txt";
char f3[] = "f3.txt";
FILE *fp1,*fp2,*fp3;
int sisendf1_kontroll();
int sisendf2_kontroll();
void tekita_failid();
void andmed_failidesse(char Tudeng1, char Tudeng2, char Aine1, char Aine2, char Tud1, int Tud2);
int main(void){
int a;
int b;
int c;
n = sisendf1_kontroll();
printf("Failist %s loeti %d tudengi andmed.\n", f1, n);
m = sisendf2_kontroll();
printf("Failist %s loeti %d aine andmed.\n", f2, m);
fp1 = fopen(f1,"r");
fp2 = fopen(f2, "r");
int i = 0;
a = sizeof(struct Tudeng);
b = sizeof(struct Aine);
c = sizeof(struct Tud);
pTudeng = malloc(a * n);
pAine = malloc(b * m);
pTud = malloc(c * m);
if(DEBUG)printf("Struktuuri Tudeng baidi aadress on %p, ühe kirje andmeteks eraldati mälu %d baiti, mälu eraldati massiivile kokku %d baiti \n", pTudeng, a, a * n);
if(DEBUG)printf("Struktuuri Aine baidi aadress on %p, ühe kirje andmeteks eraldati mälu %d baiti, mälu eraldati massiivile kokku %d baiti \n", pAine, b, b * m);
if(DEBUG)printf("Struktuuri Tud baidi aadress on %p, ühe kirje andmeteks eraldati mälu %d baiti, mälu eraldati massiivile kokku %d baiti \n", pTud, c, c * m);
int loopiks;
while(loopiks == 0){
while(!feof(fp1)){
fscanf(fp1,"%s",(pTudeng+i)->Nimi);
fscanf(fp1,"%s",(pTudeng+i)->Kood);
i++;
}
while(!feof(fp2)){
fscanf(fp2,"%s",(pAine+i)->Nimetus);
fscanf(fp2,"%s",(pAine+i)->aineKood);
fscanf(fp2,"%s",(pTud+i)->Tudengikood);
fscanf(fp2,"%d",(pTud+i)->Hinne);
i++;
}
loopiks = 1;
tekita_failid();
andmed_failidesse((pTudeng+i->Nimi), (pTudeng+i)->Kood, (pAine+i)->Nimetus, (pAine+i)->aineKood, (pTud+i)->Tudengikood, (pTud+i)->Hinne);
free(pTudeng);
free(pAine);
free(pTud);
}
//fprintf(fp3, "%s %s\n",(pTudeng+i)->Nimi,(pTudeng+i)->Kood);
fclose(fp1);
fclose(fp2);
return 0;
}
int sisendf1_kontroll(void){
char rida[122];
int n = 0, p;
fp1 = fopen(f1,"r");
if(fp1 == NULL){
printf("Sisendfaili %s avamine ebaonnestus!", f1);
exit(1);
}else{
while(!feof(fp1)){
fgets(rida, 122, fp1);
p = strlen(rida);
if (p > 1) n++;
}
}
fclose(fp1);
return n;
}
int sisendf2_kontroll(void){
char rida2[122];
int m = 0, o;
fp2 = fopen(f2,"r");
if(fp2==NULL){
printf("Sisendfaili %s avamine ebaonnestus!", f2);
exit(1);
}else{
while(!feof(fp2)){
fgets(rida2, 122, fp2);
o = strlen(rida2);
if (o > 1) m++;
}
}
fclose(fp2);
return m;
}
void tekita_failid(){
fp3 = fopen(f3, "w");
fclose(fp3);
return;
}
void andmed_failidesse(char Tudeng1, char Tudeng2, char Aine1, char Aine2, char Tud1, int Tud2){
fp3 = fopen(f3, "a");
int i;
int j;
while(i < n && j < m){
for(i = 0; i < n; i++){
fprintf(fp3, "%s %s ",(pTudeng+i)->Nimi,(pTudeng+i)->Kood);
}
for(j = 0; j < m; j++){
fprintf(fp3, "%s %s %s %d \n",(pAine+i)->Nimetus,(pAine+i)->aineKood, (pTud+i)->Tudengikood, (pTud+i)->Hinne);
}
}
return;
}
I expected the program to output the information from f1.txt and f2.txt to f3.txt, but currently compiler tells me that I cannot do that, since I'm using * int in last function, but it says that regular int is required.

Compiler is right:
andmed_failidesse expects an int as last parameter and you're passing Hinne which is an array of int, aka int*.
As Tud2 is not used anyway in your current code you can remove it from function signature or rework your function to use it.
Your compiler should also warn you that you have other unused parameters in your function.
It is obviously a work in progress: take a break, re-read your C courses and try to figure out what your function is supposed to do, and which parameters it needs.

Related

Why my code is printing last values retrieved from file instead of new one

I have the following code for reading files in C. It's reading from files but not like its supposed to be. It is showing up like this:
instead of like this:
Although I am calling the same print function. We are taking records for 4 employees. I know it's a logical error but I am unable to solve it.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct employee {
float hoursWorked, hourlyRate, federalTax, stateTax;
char name[20];
};
struct calc
{
float grosspay, fto, sto, np;
};
void print(struct employee s[], struct calc c[], int n)
{
for (int i = 0; i < 4; i++)
{
printf("\n%s's gross pay: $%.02f\n", s[i].name, c[i].grosspay);
printf("Federal tax owed: $%.02f\n", c[i].fto);
printf("State tax owed: $%.02f\n", c[i].sto);
printf("Net pay: $%.02f \n\n", c[i].np);
printf("\n");
}
}
void savetext(struct employee s[], struct calc c[], int n)
{
FILE *f;
f = fopen("employee.txt", "w");
for (int i = 0; i < n; i++)
{
fprintf(f, "%s\n", s[i].name);
fprintf(f, "%f %f %f %f\n", s[i].hoursWorked, s[i].hourlyRate, s[i].federalTax, s[i].stateTax);
fprintf(f, "%.2f %.2f %.2f %.2f\n", c[i].grosspay, c[i].fto, c[i].sto, c[i].np);
}
fclose(f);
}
void retrievetext(struct employee s[], struct calc c[], int n)
{
FILE *f;
int length;
f = fopen("employee.txt", "r");
for (int i = 0; i < n; i++)
{
fgets(s[i].name, sizeof(s[i].name), f);
length = (int)strlen(s[i].name);
s[i].name[length - 1] = '\0';
fscanf(f, "%f %f %f %f\n", &s[i].hoursWorked, &s[i].hourlyRate, &s[i].federalTax, &s[i].stateTax);
fscanf(f, "%.2f %.2f %.2f %.2f\n", &c[i].grosspay, &c[i].fto, &c[i].sto, &c[i].np);
}
fclose(f);
}
void savebin(struct employee s[], int n)
{
FILE *f;
f = fopen("employee.bin", "wb");
for (int i = 0; i < n; i++) {
fwrite(&s, sizeof(s[n]), n, f);
}
fclose(f);
}
void retrievebin(struct employee s[], int n)
{
FILE *f;
f = fopen("employee.bin", "rb");
for (int i = 0; i < n; i++) {
fread(&s, sizeof(s[i]), n, f);
}
fclose(f);
}
int main(){
savetext(st, c, 4);
retrievetext(st, c, 4);
printf("After reading text file");
print(st, c, 4);
savebin(st, 4);
retrievebin(st, 4);
printf("After reading bin file");
print(st, c, 4);
return 0;
}
You didn't get a warning here from this?
fscanf(f, "%.2f %.2f %.2f %.2f\n", &c[i].grosspay, &c[i].fto, &c[i].sto, &c[i].np);
fscanf() will eat any float you throw at it, specifying the %.2f format like this doesn't really work.
https://en.wikipedia.org/wiki/Scanf_format_string
Try using it like this:
fscanf(f, "%f %f %f %f\n", &c[i].grosspay, &c[i].fto, &c[i].sto, &c[i].np);
It was probably reading the file wrong, and then using the wrong line as an employee name.
PS: Your print() might have a small error:
for (int i = 0; i < 4; i++) // It should probably be i < n, instead of i < 4
And try to include an example input file, so people can test the code. At main(), there is no definition of st, so it's hard for people to see what's really happening if they can't test it themselves.

Segmentation fault error when I try to run this program

#include <stdio.h>
#include <stdlib.h>
#include "vettore.h"
int main(int argc, char *argv[]){
if(argc != 5)
printf("Incorrect parameters number\n");
else{
int n = atoi(argv[1]);
int *a = (int*) calloc(n, sizeof(int));
if(a == NULL)
printf("Unsufficient memory\n");
else{
finput_array(argv[2], a, n);
bubblesort(a, n);
foutput_array(argv[4], a, n);
int *oracle = (int*) calloc(n, sizeof(int));
finput_array(argv[3], oracle, n);
if(compare_array(a, oracle, n))
printf("PASS\n");
else
printf("FAIL\n");
}
}
}
I run the program this way: ./test_ordina_array.exe 12 TC4_input.txt TC4_oracle.txt TC4_output.txt but it gives me segmentation fault.
"TC4_output.txt" is created by the program while the other two files already exist.
This are the functions used:
void bubblesort(int a[], int n){
int i, j;
for(i = 0 ; i < n - 1; i++)
{
for(j = 0 ; j < n - i - 1; j++)
{
if (a[j] > a[j+1]) /* For decreasing order use < */
{
swap(&a[j], &a[j+1]);
}
}
}
}
void finput_array(char *file_name, int a[], int *n){
FILE *fd = fopen(file_name, "r");
if(fd == NULL)
printf("Errore in apertura del file %s\n", file_name);
else{
int i = 0;
fscanf(fd, "%d", &a[i]);
while(i<*n && !feof(fd)){
i++;
fscanf(fd, "%d", &a[i]);
}
fclose(fd);
if(i<*n)
*n = i;
}
}
void foutput_array(char *file_name, int a[], int n){
int i;
FILE *fd;
fd = fopen(file_name, "w");
if(fd == NULL)
printf("Errore in apertura del file %s\n", file_name);
else{
for(i=0; i<n; i++)
fprintf(fd, "%d\n", a[i]);
fclose(fd);
}
}
int compare_array(int a[], int b[], int n){
int i=0;
while(i<n && a[i] == b[i])
i++;
return (i==n) ? 1 : 0;
}
They are contained in "vettore.c" and "vettore.h" contains their prototypes.
The program has to order in ascending order the elements contained in the first txt file and write them in the output file.
You have problem when using finput_array
finput_array(argv[2], a, n);
Please replace by
finput_array(argv[2], a, &n);

C fork and pipe add numbers from a file

Totals different for same file when executed.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_FILE_NAME 100
#define RUNS 1
int main() {
int num,i;
FILE *fp;
char*s, buf[1024];
int count =0;
char c;
char filename[MAX_FILE_NAME];
printf("Enter filename: ");
scanf ("%s",filename);
if ((fp =fopen(filename, "r")) == NULL) {
printf("Error");
exit(1);
}
fscanf(fp,"%d",&num);
for (c = getc(fp); c!= EOF; c = getc(fp))
{
if (c == '\n'){
count = count+1;
}
}
printf("%s has %d numbers \n", filename, count);
int f;
printf("Choose from the options how many processes you want to use [1,2,4]: ");
scanf("%i", &f);
printf("%i processes \n", f);
int fds[f+1][2];
int numb[count];
int x,k;
time_t start, finish;
start = time(NULL);
for(i = 0; i < RUNS; i++)
{
pipe(fds[f]);
for( x = 0; x<f; x++)
{
pipe(fds[x]);
int ind[2];
ind[0] = ((x)*(count/f));
ind[1] = ((x+1)*(count/f));
write(fds[x][1], &ind, 2* sizeof(int));
if (fork() ==0)
{
int t =0;
int ind2[2];
read(fds[x][0], &ind2, 2*sizeof(int));
for( k = ind2[0]; k<ind2[1]; k++)
{
t += numb[k];
}
write(fds[f][1], &t, sizeof(int));
exit(0);
}
}
int m, tmp, total;
total = 0;
for( m = 0; m < f; m++)
{
for( m = 0; m < f; m++)
{
read(fds[f][0], &tmp, sizeof(int));
sleep(5);
total += tmp;
}
printf("DOne calc \n");
printf("Total: %i \n", total);
}
finish = time(NULL);
float runtime = (float)((finish-start)/RUNS);
printf("runtime: %f \n", runtime);
fclose(fp);
return 0;
}
You get random result for the same input because the calculation based on uninitialized int numb[count]; values.
According to the C99 standard, section 6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
Because of it int numb[count]; contains some random junk from memory. To get predictive results use explicit initialization:
#include <string.h> // memset
int numb[count];
memset (numb, 0, sizeof(numb)); // Zero-fills
Use the code bellow to put numbers from filename file into numb:
int i = 0;
char line[1024];
fseek(fp, 0, SEEK_SET);
while(fgets(line, sizeof(line), fp) )
{
if( sscanf(line, "%d", &numb[i]) == 1 ) // One number per line
{
++i;
}
}

Assigning value to struct variable

I am constructing a adjacency list that I am using to make a directed graph. I read two characters and then make a vertex out of each of them unless a vertex with that char has already been made. I am unfamiliar with structures so this is tripping me up. The values aren't being assigned and I am ending up with an empty list. I am assuming that it is something that has to do with pointers that I am overlooking but I can't seem to find the problem. I hope that someone can help. I will include my code and a sample output.
my.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
/* Forward declaration */
struct EDGETAG;
typedef struct
{
char c;
bool isVisited;
struct EDGETAG* p;
} VERTEX;
typedef struct EDGETAG
{
VERTEX* v;
struct EDGETAG* q;
} EDGE;
int main (int argc, char* argv[]);
int adjListSearch (char a, int size, VERTEX* adjList);
adjListSearch.c
#include "my.h"
int adjListSearch (char a, int size, VERTEX* adjList)
{
int i;
if(size == 0)
{
printf("empty\n");
return 1;
}
for(i = 0; i<size; i++)
{
if( adjList[i].c = a)
{
return 0;
printf("found\n");
}
}
printf("notfound\n");
return 1;
}
main.c
#include "my.h"
int main (int argc, char* argv[])
{
int y = 0;
int x = 0;
VERTEX *adjList;
adjList = (VERTEX*)calloc(26, sizeof(VERTEX));
//adjList = malloc(sizeof(VERTEX)*26);
FILE* p;
char *fp;
char a;
char b;
int check1 = 0;
int check2 = 0;
int size = 0;
int searchsuccess = 0;
int i;
//Statements
p = fopen( argv[1], "r");
while(fscanf(p," %c %c", &a, &b)!= EOF)
{
printf("a: %c b: %c\n",a,b);
check1 = adjListSearch(a,size,adjList);
if(check1==1)
{
adjList[size].c = a;
size = size +1;
}
//printf("%c\n", adjList[size].c);
check2 = adjListSearch(b,size,adjList);
if(check2==1)
{
adjList[size].c = b;
size = size +1;
}
}
//End While
printf("Size: %d", size);
for(i=0;i<size;i++)
{
printf("%c\n", adjList[size].c);
}
free(p);
return 0;
}
//End main
Sample Output
a: A b: B
a: B b: C
a: E b: X
a: C b: D
Size: 1
As you can see none of the characters are printed as being inside a structure.
EDIT 1:
I would want the expected output to look like
a: A b: B
a: B b: C
a: E b: X
a: C b: D
Size: 6
A
B
C
E
X
D
Edit 2
Still lost on this if anyone can help.
There were a variety of problems.
You should use fclose(p); and not free(p);.
You should print printf("%c\n", adjList[i].c); instead of printf("%c\n", adjList[size].c);.
As brokenfoot pointed out in his answer, you need to compare a instead of assign it in adjListSearch().
There were multiple unused variables (the compilation options I use complain about them).
There is no need to declare main() (though it doesn't do any harm to the program).
You don't check that there is an argv[1] to use.
You don't check that you opened the file.
You should really use while (fscanf(p, " %c %c", &a, &b) == 2), though it would only matter in this program if there were an odd number of characters to process. At least you were testing fscanf() which is more than many questions we see do.
In the code below, I printed more informative status messages.
main.c
#include "my.h"
int main(int argc, char *argv[])
{
VERTEX *adjList;
adjList = (VERTEX *)calloc(26, sizeof(VERTEX));
FILE *p;
char a;
char b;
int check1 = 0;
int check2 = 0;
int size = 0;
int i;
if (argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
return 1;
}
if ((p = fopen(argv[1], "r")) == 0)
{
fprintf(stderr, "Failed to open file %s for reading\n", argv[1]);
return 1;
}
while (fscanf(p, " %c %c", &a, &b) == 2)
{
printf("a: %c b: %c\n", a, b);
check1 = adjListSearch(a, size, adjList);
if (check1 == 1)
{
printf("Adding a = %c\n", a);
adjList[size++].c = a;
}
check2 = adjListSearch(b, size, adjList);
if (check2 == 1)
{
printf("Adding b = %c\n", b);
adjList[size++].c = b;
}
}
printf("Size: %d\n", size);
for (i = 0; i < size; i++)
{
printf("%c\n", adjList[i].c);
}
fclose(p);
return 0;
}
adjListSearch.c
#include "my.h"
int adjListSearch(char a, int size, VERTEX *adjList)
{
int i;
if (size == 0)
{
printf("empty\n");
return 1;
}
for (i = 0; i < size; i++)
{
if (adjList[i].c == a)
{
printf("found %c\n", a);
return 0;
}
}
printf("not found %c\n", a);
return 1;
}
Data
A B
B C
E X
C D
Sample output
a: A b: B
empty
Adding a = A
not found B
Adding b = B
a: B b: C
found B
not found C
Adding b = C
a: E b: X
not found E
Adding a = E
not found X
Adding b = X
a: C b: D
found C
not found D
Adding b = D
Size: 6
A
B
C
E
X
D
In adjListSearch(), change
if( adjList[i].c = a)
to
if( adjList[i].c == a)

Error: too few arguments to function 'strcmp'

I am having a few issues with my code. First: when I try to compile, I get error: too few arguments to function 'strcmp'. I have looked all over and made multiple changes and am still unable to get it to work. Second: when my code does compile (if I remove the strcmp part), it will not complete the count functions correctly. Can anyone please assist? Thank you!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int count(char array[], int size);
int stringLen(char array[]);
int convert(char ch);
int value, n;
int main()
{
//char * str;
//char s;
char a[100];
char b[100];
char c[100];
int charCount = stringLen(a);
int lCount = count(a, charCount);
printf("Enter your string: \n");
scanf("%s \n", a);
printf("Enter your string: \n");
scanf("%s \n", b);
printf("Enter your string: \n");
scanf("%s \n", c);
printf("The count is %d, length is %d\n", lCount, charCount);
int i;
for(i = 0; i < charCount; i++)
{
char c = a[i];
printf("Char %s = %d \n", &c, value);
}
n = strcmp(char string1[], char string2[], char string3[]);
printf("The first string in the alphabet is: %d \n", n);
return 0;
}
int stringLen(char array[])
{
char count;
int index;
while(array[index] !=0)
{
count++;
index++;
}
return count;
}
int count(char array[], int size)
{
int count;
int i;
for(i = 0; i < size; i++)
{
if(array[i] == 'a')
{
count ++;
}
else if(array[i] == 'A')
{
count ++;
}
}
return count;
}
This is not right way to use strcmp.
n = strcmp(char string1[], char string2[], char string3[]);
strcmp is used for compararison of string. See doc
int result = strcmp (string1,string2)
If strings are same, function will return 0.

Resources