Combining two files of floats into a single file in C - c

My task is to read from two files both containing floats. Then I have to put them in a new file in an ascending order. The code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int numLines(const char * fileName){
FILE *file=fopen(fileName,"r");
int lines=0;
char c;
while((c=fgetc(file))!=EOF){
if(c==10){
lines++;
}
}
fclose(file);
return lines;
}
float * fileToArray(const char * fileName){
FILE *file=fopen(fileName,"r");
int numOfLines= numLines(fileName);
float * arr= (float*)malloc(numOfLines*sizeof(float));
int i;
for(i=0;i<numOfLines;i++){
fscanf(file,"%f\n",&arr[i]);
}
fclose(file);
return arr;
}
int cmpfunc(const void *a, const void *b){
float fa= *(const float*) a;
float fb= *(const float*) b;
return (fa>fb)-(fa<fb);
}
int isSorted(FILE *fp){
float prev;
float o;
do{
fscanf(fp,"%f\n",&prev);
fscanf(fp,"%f\n",&o);
if(prev>o){
fclose(fp);
return 1;
}
}while(fscanf(fp,"%f\n",&o)==1);
fclose(fp);
return 0;
}
int main(int argc, const char * argv[]){
const char *fileName1;
const char *fileName2;
const char *fileOut;
FILE *fp1;
FILE *fp2;
FILE *fp3;
float *arr1;
float *arr2;
int size1;
int size2;
if(argc!=4){
printf("Usage: fileSort.exe FILENAME1 FILENAME2 FILEOUT");
return 0;
}
else{
fileName1= argv[1];
fileName2= argv[2];
fileOut= argv[3];
fp1= fopen(fileName1,"r");
fp2= fopen(fileName2, "r");
fp3= fopen(fileOut, "w");
if(fp1!=NULL && fp2!=NULL){
arr1=fileToArray(fileName1);
arr2=fileToArray(fileName2);
size1=sizeof(arr1)/sizeof(float);
size2=sizeof(arr2)/sizeof(float);
if(!isSorted(fp1) || !isSorted(fp2)){
printf("The files are not sorted in increasing order. Please sort them.");
}
else{
float * arr3= malloc((size1+size2)*sizeof(float));
int k;
memcpy(arr3,arr1,size1*sizeof(float));
memcpy(arr3+size1,arr2,size2*sizeof(float));
qsort(arr3,size1+size2,sizeof(float),cmpfunc);
for(k=0;k<(size1+size2);k++){
fprintf(fp3,"%f\n",arr3[k]);
}
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
}
else{
printf("Files could not be opened\n");
}
return EXIT_SUCCESS;
}
Two sample files for testing this code would be:
data1.txt:
0.586399
0.769484
0.864755
6.229683
data2.txt:
0.279828
0.309235
0.591884
0.962811
1.361349
10.203892
12.158343
The result should be their ordered combination. However, I get this as a result:
0.279828
0.309235
0.586399
0.769484
No matter what I change, it always writes four numbers into the resulting file. The helper functions seem to be doing their jobs just fine. It looks like the problem comes up when I'm trying to create the third array and fill it up (or at least I assume that's the source). I have no idea where this problem is coming from though. I would really appreciate some help on this issue.

The variable arr1 is not an array, it is a pointer to a float even though you are using it as pointer to the first float element in the array.
This means that sizeof will return to you the size of the pointer which is either 4 bytes or 8 bytes depending whether you are compiler 32-bit or 64-bit.
One way to fix this is to pull out the calculation of the number of lines like this:
int size1 = numLines(fileName1);
int size2 = numLines(fileName2);
arr1=fileToArray(fileName1, size1);
arr2=fileToArray(fileName2, size2);

Related

Struct initialized in function loses values (although it's an array)

I'm trying to initialize array *dip inside "leggif1", inside it if you do a print it's all normal but if you try to print in the main, after the initialization, everything loses its values.
Same thing happen with ADT of first grade "Divisione" and i can't understand why (even though they are passed "by reference" thanks to their pointers).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int matricola;
char nome[20+1],cognome[20+1];
int comp[4];
}dipendente;
typedef struct divisione *Divisione;
struct divisione{
dipendente *dip;
char nome[10+1];
int terna[4][3]; //numero minimo di addetti,competenza minima totale, competenza ottimale totale
//per ognuna delle 4 tipologie
};
void leggif1(dipendente *dip, char *filename);
int leggif2(Divisione *Div, char *filename);
void DIVstampa(Divisione *Div,char *filename,int D);
Divisione DIVinit();
void DIVfree(Divisione *Div);
int main(int argc,char **argv) {
dipendente *dip;
Divisione *Div;
leggif1(dip,argv[1]);
int D=leggif2(Div, argv[2]);
DIVstampa(Div,"stdout",D);
return 0;
}
void leggif1(dipendente *dip, char *filename) {
FILE *fp=fopen(filename,"r");
int i,N;
fscanf(fp,"%d",&N);
dip=malloc(N*sizeof(dipendente));
for(i=0;i<N;i++)
fscanf(fp,"%d %s %s %d %d %d %d",&dip[i].matricola,dip[i].nome,dip[i].cognome,
&dip[i].comp[0],&dip[i].comp[1],&dip[i].comp[2],&dip[i].comp[3]);
}
int leggif2(Divisione *Div, char *filename) {
FILE *fp=fopen(filename,"r");
int i,j,D;
fscanf(fp,"%d",&D);
Div=malloc(D*sizeof(Divisione));
for(i=0;i<D;i++)
Div[i]=DIVinit();
for(i=0;i<D;i++) {
fscanf(fp, "%s", Div[i]->nome);
for (j = 0; j < 4; j++)
fscanf(fp, "%d %d %d", &Div[i]->terna[j][0], &Div[i]->terna[j][1], &Div[i]->terna[j][2]);
}
return D;
}
void DIVstampa(Divisione *Div, char *filename, int D) {
FILE *fp;
if(strcmp(filename,"stdout")==0)
fp=stdout;
else
fp=fopen(filename,"w");
int i,j;
for(i=0;i<D;i++) {
fprintf(fp,"%s\n", Div[i]->nome);
for(j=0;j<4;j++)
fprintf(fp,"%d %d %d\n", Div[i]->terna[j][0], Div[i]->terna[j][1], Div[i]->terna[j][2]);
}
}
Divisione DIVinit(){
Divisione Div=malloc(sizeof (*Div));
return Div;
}
void DIVfree(Divisione *Div){
free(Div);
}
The leggif1 function ignores the value of dip and assigns it a new value. That value is never returned to main.
The type of dip is dipendente* and when called in main the value of the pointer is passed to the function. Overwriting that local copy in the function does not affect the value of the pointer in main.
C only has 'call by value', always make sure you known what that value represents.
This can be solved by returning the dip from the function instead of taking it as a parameter:
dipendente* leggif1(char *filename)
{
//open file and read N
dipendente *dip = malloc(N * sizeof *dip);
if (!dip) {
return NULL;
}
// read in the data
return dip;
}
another way is to use a dipendente** (a pointer to a pointer) but that would, in this case, make the code needlessly complex.
The leggif2 function has the same problem.

Allocating memory for an array of struct i get an error

the code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
typedef struct word{
char word[20];
int occurrance;
} word;
int array_word_creator(word *array, FILE *fp);
void initialize(word array[], int max);
void comparator(word array[], int max, FILE *fp);
void printer(word array[], int max);
int main(int argc, char *argv[])
{
FILE *f_sent, *f_words;
word *array;
int arr_lenght=0;
if(argc!=3)
{
printf("Wrong argument number, please use NAME FILE1 FILE2;\n");
exit(EXIT_FAILURE);
}
if((f_sent=fopen(argv[1], "r"))==NULL||(f_words=fopen(argv[1], "r"))==NULL)
{
printf("Can't find or open the files, please check if the name is correct\n");
exit(EXIT_FAILURE);
}
arr_lenght=array_word_creator(array, f_words);
comparator(array, arr_lenght ,f_sent);
printer(array, arr_lenght);
return 0;
}
int array_word_creator(word *array, FILE *fp)
{
int n,i=0;
fscanf(fp,"%d",&n);
*array= malloc(n*sizeof(word));
while(fscanf(fp,"%s", array[i].word)!=EOF)
{
i++;
}
initialize(array,n);
return n;
}
void initialize(word array[], int max)
{
int i;
for(i=0;i<max;i++)
{
array[i].occurrance=0;
}
}
void comparator(word array[], int max, FILE *fp)
{
char word[MAX];
int i;
while(fscanf(fp,"%s", word)!=EOF)
{
for(i=0;i<max;i++)
{
if(strcmp(word, array[i].word)==0)
{
array[i].occurrance++;
}
}
}
}
void printer(word array[], int max)
{
int i;
for(i=0;i<max;i++)
{
if(array[i].occurrance>0)
{
printf("The word '%s' occurs %d times\n", array[i].word, array[i].occurrance);
}
}
}
And the compiler says me:
C:\Users\Matteo\Google Drive\Programming\C\lab3\es1\main.c|47|error: incompatible types when assigning to type 'word' from type 'void *'|
I just studied memory allocation so i'm having some trouble with it, especially with structures. If possible, plase link me also some good docs about this subject.
thank you!
In main word *array is a pointer to a structure of type word.
You then pass array, which does not point to anything, to the function array_word_creator.
You then try to assign the pointer returned by malloc to where array is pointing, but it doesn't point anywhere yet, and even if it did, it would be pointing to a word (since it is a word *), so it can't store a pointer, hence the compiler error.
If you want to set the array pointer in main to the result of malloc, you have to pass a pointer to the pointer. int array_word_creator(word **array, FILE *fp), then you would call it by doing array_word_creator(&array, .... ), the your *array = malloc will work.
You want this:
...
arr_lenght = array_word_creator(&array, f_words);
...
int array_word_creator(word **array, FILE *fp)
{
int n, i = 0;
fscanf(fp, "%d", &n);
*array = malloc(n * sizeof(word));
while (fscanf(fp, "%19s", (*array)[i].word) != EOF)
{
i++;
}
initialize(*array, n);
return n;
}

Array of struct from binary file

I have to write a function that will read an array of structures of type Product with data from a binary file.This file contains the number of products - nr and a number of articles of type Product. What's wrong? Thank you in advance!
#define SIZE 30
typedef struc{
int id;
char[SIZE] name;
float price;
}Product;
void create(Product *p, FILE *fptr)
{
p = malloc(sizeof(Product));
fread(p, 1, sizeof(Product), fptr);
}
int main(int argc, char* argv[])
{
FILE *fptr = fopen(argv[1],"rb");
Product *p;
create(p, fptr);
return 0;
}
You have to modify it to something like this:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 30
typedef struct{
int id;
char name[SIZE];
float price;
}Product;
int readproducts(Product *p, FILE *fptr, int nr)
{
if(nr != fread(p, sizeof(Product), nr, fptr))
return -1;
return 0;
}
int main(int argc, char* argv[])
{
FILE *fptr = fopen(argv[1],"rb");
int nr = 0;
if(NULL == fptr) return -1;
// First read number of products from file
// Assuming this number is written as 4 byte integer - at the start of file
if(fread(&nr, 4, 1, fptr) != 1)
return -1;
// Now, read the products
Product *p = malloc(nr * sizeof(Product));
if(-1 == readproducts(p, fptr, nr))
return -1;
fclose(fptr);
return 0;
}
The way you had used malloc in your function was wrong, see here why.
PS. That said, binary writing/reading might not be portable across different computers.

command line arguments issues

At the moment the program is reading "unable to open the input file" which means the size is 0. I made the input file with my editor, but I'm not sure what the issue could be. Is there anything up with my code that could cause this? Or is it more likely I just messed up the input.txt file?
#include <stdio.h>
#include <stdlib.h>
int load_data(char* filename, int *x, float *y)
{
int i=0;
FILE* file=fopen(filename,"r");
if(file==NULL)
{
return 0;
}
int size;
fscanf(file, "%d", &size);
for(i=0;i<size;i++)
{
fscanf(file, "%d%f", &x, &y);
}
fclose(file);
return size;
}
void print_data(int *acn, float *amt, int size)
{
int i;
int *p;
for(i=0;i<size;i++)
{
printf("%-10d%-10f ", *(acn+i), *(amt+i));
}
}
int main(int argc, char** argv)
{
int size=0, *x;
char *filename;
float *y;
if(argc!=3)
{
printf("\nInsufficient arguments.\n");
return 0;
}
int n=atoi(argv[2]);
int *acn;
float *amt;
int *fp=malloc(sizeof(int)*n);
if(size==0)
{
printf("\nUnable to open the input file.\n");
return 0;
}
load_data(filename, x, y);
print_data(acn, amt, size);
free(fp);
return 0;
}
There are number of problems in you program -
You are name of file from commal line but you do not store it in char *filename; and in function int load_data(char* filename, int *x, float *y)
you are passing filename.But filename does not have the name of file in it stored.
fscanf(file, "%d%f", &x, &y); when you pass pointer in fscanf with %d you don't need & operator.Just this will do-
fscanf(file, "%d%f", x, y);
You need to allocate memory using malloc to x and y.
size in both functions are different as you declare it again in the function and in main.Thats why size is always 0 in int main.
void print_data in this function you are printing value of acn and amt but both the pointer are unintialized and you are printing it so it will give undefined behaviour.
Also you have pointers which are declared in your program but not used .
In following lines of code (which you have posted), the value of size variable is 0. The value has never been updated, before checking at line if(size==0). That is why this if check is returning true and printing "Unable to open the input file".
You may want to set the value of size variable before this if check.
int size=0, *x; //HERE YOU ARE WRITING "SIZE" VARIABLE
char *filename;
float *y;
if(argc!=3)
{
printf("\nInsufficient arguments.\n");
return 0;
}
int n=atoi(argv[2]);
int *acn;
float *amt;
int *fp=malloc(sizeof(int)*n);
if(size==0) //HERE YOU ARE READING/CHECKING "SIZE" VARIABLE. THERE IS NO CHECGE IN VARIABLE BEFORE THIS SO, VALUE IS STILL '0'
{
printf("\nUnable to open the input file.\n");
return 0;
}

getting fscanf to store in structs in C

I have an assignment where I need to get Values of RLC circuits from a file and calculate the resonant frequency however my issue is when I use the fscanf function it reads only the first line of the file and the rest comes out as zeros .
#include <stdio.h>
data
int h;
typedef struct cct
{
int code[50];
float R[50];
float L[50];
float C[50];
} CCT;
int read(CCT cct[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%d,%f,%e,%e\n", cct[n_p].code, cct[n_p].R,cct[n_p].L, &cct[n_p].C);
}
int main()
{
FILE* fp = fopen("U://datafile.txt", "rt");
int i = 0;
CCT cct[50];
int size;
while (!feof(fp)) {
read(cct, i, fp);
i++;
}
size = i;
for (i = 0; i < size; ++i)
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code[i], cct[i].R[i],
cct[i].L[i], cct[i].C[i]);
scanf("%d",&h);
fclose(fp);
}
and this is the data file
1,4.36,2.23e-2,4.65e-8
2,4.57,2.01e-2,5.00e-8
3,3.99,2.46e-2,4.82e-8
4,4.09,2.60e-2,4.70e-8
I would appreciate if someone could point put why it only gets the first line. Thanks
CCT is composed of multiple arrays (you have arrays of arrays, which is wrong for the exercise, but that's not the point) and you always write to the element zero of the arrays. For example, cct[n_p].code in fscanf() is the address of the array, which is identical to the address of cct[n_p].code[0]. Then you print code[i] in the output loop, which is blank except for i == 0.
fscanf(fp,"%d,%f,%e,%e", cct[n_p].code, cct[n_p].R,cct[n_p].L, cct[n_p].C);
...
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code[0], cct[i].R[0], cct[i].L[0], cct[i].C[0]);
Something like the following, perhaps
#include <stdio.h>
typedef struct cct {
int code;
float R;
float L;
float C;
} CCT;
int h;
int read(CCT cct[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%d,%f,%e,%e\n", &cct[n_p].code, &cct[n_p].R, &cct[n_p].L, &cct[n_p].C);
}
int main(){
FILE* fp = fopen("U://datafile.txt", "rt");
int i = 0;
CCT cct[50];
int size;
while (!feof(fp)) {
read(cct, i, fp);
i++;
}
size = i;
for (i = 0; i < size; ++i)
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code, cct[i].R, cct[i].L, cct[i].C);
scanf("%d",&h);
fclose(fp);
}

Resources