How to extract data from a file in C - c

I have a .dat file containing 6 columns of N numbers like so:
-4.997740e-01 -1.164187e+00 3.838383e-01 6.395961e+01 -1.938013e+02 -4.310365e-02
-1.822405e+00 4.470735e-01 -2.691410e-01 -8.528020e+01 -1.358874e+02 -7.072167e-01
9.932887e-01 -2.157249e+00 -2.303825e+00 -5.508925e+01 -3.548236e+02 1.250405e+00
-1.871123e+00 1.505421e-01 -6.550555e-01 -3.254452e+02 -5.501001e+01 8.776851e-01
1.370605e+00 -1.028076e+00 -1.137059e+00 6.096598e+01 -4.472264e+02 -1.268752e+00
............ ............ ............ ............ ........... ...........
I want to write a code in C language where I extract the data from the file.dat and I assign the numbers of each column to a vector; for example:
V1=[-4.997740e-01;-1.822405e+00;9.932887e-01;-1.871123e+00;1.370605e+00];
and so on for all the 6 columns.
The only thing I know so far is that I need to start by doing something like this:
int main(){
FILE *fp;
fp=fopen("file.dat","r");
if (!fp){
printf("Error\n");
return 1;
}
return 0;
}
Does anyone know what I should do in order to accomplish my goal?

Try this
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_ROW 256
int main()
{
FILE *file;
float data[MAX_ROW][6];
int index;
float *row;
file = fopen("file.dat", "r");
if (file == NULL)
{
perror("fopen()");
return 1;
}
index = 0;
row = data[0];
while (fscanf(file, "%f%f%f%f%f%f", &row[0], &row[1], &row[2], &row[3], &row[4], &row[5]) == 6)
{
printf("[%f;%f;%f;%f;%f;%f]\n", row[0], row[1], row[2], row[3], row[4], row[5]);
row = data[index++];
}
fclose(file);
return 0;
}
note that you could need to make data dynamically allocated to be able to resize it.

Related

Using feof to read whole file and print result give me double end

I have, I'm trying to read a binary file until end and print the result, I'm using and while with "feof" to read until end of file and printing each result, but I have a problem it is giving me double end result.
I'm still learning C, so I don't know why its giving me double end result, I have tried so many ways, but this was for me the best way and easiest that at least works, but now I'm stuck after 2 hours trying to fix it.
Result:
0
1
2
3
4
5
6
7
8
9
9
Expected:
0
1
2
3
4
5
6
7
8
9
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// https://www.aprendeaprogramar.com/cursos/verApartado.php?id=16007
struct Datos
{
int cero;
int uno;
int dos;
int tres;
int cuatro;
int cinco;
int seis;
int siete;
int ocho;
int nueve;
};
struct Datos datosEscrito = {0,1,2,3,4,5,6,7,8,9};
FILE *fichero;
fichero = fopen("tabla2.dat", "wb");
fwrite(&datosEscrito, sizeof(datosEscrito), 1, fichero);
fclose(fichero);
int datoLeido;
FILE *fichero2;
fichero2 = fopen("tabla2.dat", "rb");
while (!feof(fichero2))
{
fread(&datoLeido, sizeof(datoLeido), 1, fichero2);
printf("%u", datoLeido);
printf("\n");
}
fclose(fichero2);
}
PD: I don't want the code fix, I want to understand why is giving me double end and an approach to fix the error myself, or another way to do the same. Thanks for the help.
Code edit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fichero;
fichero = fopen("tabla2.dat", "wb");
int count=0;
while (count != 10)
{
fwrite(&count, sizeof(count), 1, fichero);
count++;
}
fclose(fichero);
// PARTE LEER
int datoLeido;
FILE *fichero2;
fichero2 = fopen("tabla2.dat", "rb");
while (!feof(fichero2))
{
fread(&datoLeido, sizeof(datoLeido), 1, fichero2);
printf("%u", datoLeido);
printf("\n");
}
fclose(fichero2);
return 0;
}
The main problems in your program are that feof will only return a nonzero value when the previous fread (or other read operation) has detected an end-of-file condition and that you use the value even when fread would have told you by its return value that it has not read any data.
The functions feof and ferror are intended to distinguish between EOF and error after a failed file operation.
To fix the read loop you can use e.g.
do
{
/* we expect to read 1 member */
if(fread(&datoLeido, sizeof(datoLeido), 1, fichero2) == 1)
{
printf("%u", datoLeido);
printf("\n");
}
} while ((!feof(fichero2)) && !ferror(fichero2));
There are more problems in your code.
The format %u corresponds to a type unsigned int. For int you should use %d.
You write the binary representation of a structure struct Datos to a file, then you read back individual values of type int.
Although this seems to produce the expected result in your case it may not work in other cases. A structure can contain padding bytes that are not part of any structure field. These would have undefined values. In any case writing/reading the binary representation of variables is implementation-dependent. The data format may change when you use a different compiler (new version, different OS, different CPU...) or even with different compiler settings.
I was able to "fix" the problem, but i think it is a dirty fix, but at least works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fichero;
fichero = fopen("tabla2.dat", "wb");
int count=0;
while (count != 10)
{
fwrite(&count, sizeof(count), 1, fichero);
count++;
}
fclose(fichero);
// PARTE LEER
int datoLeido;
FILE *fichero2;
fichero2 = fopen("tabla2.dat", "rb");
while (!feof(fichero2))
{
fread(&datoLeido, sizeof(datoLeido), 1, fichero2);
if(!feof(fichero2))
{
printf("%d", datoLeido);
printf("\n");
}
}
fclose(fichero2);
return 0;
}
Thanks to all for the help and #David Schwartz gave me the hint after reading that i am not checking if the file end it before print the data

Fill a file with an array of struct type in C

I need to feel a file with a list of purchase
I declared a type struct name purchase that must contain the information : item, price and date of purchase in day/month/year ordered by date of purchase.
But it doesn't work and I don't know why.
This is the code source:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct Date {
int day,month,year;
} Date;
typedef struct purchase{
char item[20];
float price;
Date date_purchase;
} purchase;
void fillFile(char Name_F[30] , purchase T[30] , int N) {
FILE * P_Fichier;
P_Fichier=fopen(Name_F,"w");
int i=1;
while (i< N )
{
fprintf(P_Fichier,T[i].item);
fprintf(P_Fichier,T[i].price);
fprintf(P_Fichier,T[i].date_purchase);
i++;
}
}
You need to specify the format specifier in fprintf(), like this:
fprintf(P_Fichier, "%s\n", T[i].item);
fprintf(P_Fichier, "%f\n", T[i].price);
fprintf(P_Fichier, "%d/%d/%d\n", T[i].date_purchase.day, T[i].date_purchase.month, T[i].date_purchase.year);
These are the typical format specifiers that'd use with printf() too, so %s for string, %f for float and %d for int.
I'd suggest you to check if the file is opened before attempting to write into it (file pointer is going to be NULL if it didn't open). You also need to close the file when you are done writing your data, like fclose(P_Fichier);.
Moreover, i should start from 0, otherwise you'll skip your first element. However, since you already know how many times you want the loop to be executed, I'd advise you to use a for-loop, like this:
for (int i = 0; i < N; ++i)
Putting everything together, you should get:
void fillFile(char Name_F[30], purchase T[30], int N) {
FILE* P_Fichier;
P_Fichier = fopen(Name_F, "w");
if (P_Fichier == NULL) {
# file failed to open
fprintf(stderr, "Unable to open %s file.\n", Name_F);
return;
}
for (int i = 0; i < N; ++i) {
fprintf(P_Fichier, "%s\n", T[i].item);
fprintf(P_Fichier, "%f\n", T[i].price);
fprintf(P_Fichier, "%d/%d/%d\n", T[i].date_purchase.day, T[i].date_purchase.month, T[i].date_purchase.year);
}
fclose(P_Fichier);
}
You have to use format specifiers to use fprintf().
Also results of fopen() should be checked and files opened should be closed.
void fillFile(char Name_F[30] , purchase T[30] , int N) {
FILE * P_Fichier;
P_Fichier=fopen(Name_F,"w");
if (P_Fichier == NULL) return; /* check if file open is successful */
int i=1;
while (i< N )
{
fprintf(P_Fichier,"%s\n",T[i].item); /* %s for strings */
fprintf(P_Fichier,"%f\n",T[i].price); /* %f for float */
fprintf(P_Fichier,"day:%d, month:%d, year:%d\n", /* %d for int */
T[i].date_purchase.day, T[i].date_purchase.month, T[i].date_purchase.year);
i++;
}
fclose(P_Fichier); /* close file when done */
}

How to create a txt file from FOR loop?

I wrote a C++ code using iterative methods. For this, I used a FOR loop. However, I need to save every result by iteration in same text file (or DATA file) as a columns. How can I do it? Thanks for your advices.
This a simple version of my code:
#include <iostream>
#include <conio.h>
#include <iomanip>
using namespace std;
int i;
main()
{
cout<<"Value 1"<<right<<setw(20)<<"Value 2"<<endl;
for(i=0;i<5;i++)
{
cout<< left << setw(20) << i+10
<< setw(20) << i<<endl;
}
getch();
}
For most purposes using a CSV file would be better. Here is a code that does what you need.
#include <stdio.h>
int main() {
FILE * fpw; // A file pointer/handler that can refer to the file via a cpp variable
fpw = fopen("data.txt", "w"); // Open the file in write("w" mode
if (fpw == NULL) {
printf("Error"); // Detect if there were any errors
return 0;
}
fprintf(fpw, "Value 1,Value 2\n"); // Write the headers
int i = 0;
for (i = 0; i < 5; i++) {
fprintf(fpw, "%d,%d\n", i + 10, i); // Write the values
}
fclose(fpw); //Don't forget to close the handler/pointer
return 0;
}
Output:
A file data.txt will be created with following contents:
Value 1,Value 2
10,0
11,1
12,2
13,3
14,4

C - Reading from a file and saving the info on a variable

im having a problem reading from these 2 files bellow, file1 and file2, and then saving their information in 2 variables.
From the file1 i want to save the name of channels, and from the file2 i want to save the name of the users and the channel where they are signed.
I was thinking of creating 2 typedef struct(shown bellow) and then create 2 variables(shown bellow) and open the files and put the info on those lists.
I also know of another way to do it which is making a 2D array like this char[100][100], the only problem with both these solutions is that I have to impose an upper limit on the amount of the channels the list/array has.
Im not sure if these are the best ways to do it or if there is a better and easier way to do it, could you guys help?
If you guys need any more information just say so, Thanks!
Edit1: i've added the read from the file1 code that i have right now and i think it is working or so it seems but my problem/question was more of is it the right way to save the information to a variable or is there a better/easier way to do it? thanks.
Channel channels[MAX_CHANNELS];
Registration registrations[MAX_REGISTRATIONS];
typedef struct{
char name_channel[20];
int id;
} Channel;
typedef struct{
char username[50];
char name_channel[20];
} Registration;
File1:
General
SO
PCD
FBD
File2:
2016-09-26 14:00:01 paul General
2016-09-26 14:01:11 mary SO
2016-09-27 10:33:17 paul SO
2016-09-27 13:32:10 rachel General
2016-09-27 13:32:12 rachel FBD
code to read the file(i have only done the file1 yet).
File *file1 = fopen("channels.txt", "r");
if(file1==NULL){ perror("Reading error: "); exit(1); } ;
char line[100];
int i = 0;
int w=0;
for(w;w<MAX_CHANNELS;w++){
channels[w].id=-1;
strcpy(channels[w].name, "n");
}
while(fgets(line, 100, file1) != NULL){
printf("Line read: %s", line);
line[ strlen(line) -1 ] = 0;
Channel a;
strcpy(a.name , line);
a.id=1;
channels[i]=a;
i++;
}
fclose(canais);
int k;
for(k=0; k<MAX_CHANNELS; k++){
if(channels[k].id!=-1)
printf("testing var with channels: %s\n", channels[k].name);
}
Just a few tips that might help(in the code comments) :) I think its fine the way you are doing it. I think this is extensible as well since you can add a new member to a struct if you want to enrich you data further. I have seen strtok used to parse through data quite a bit. Strtok should eliminate the need for you to overwrite the newline due to the way it works.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MYSTRINGLEN (50) // In general "magic numbers"
//in code makes it hard to read, though these are fairly apparent,
//but try using #define where you can
typedef struct {
char name[MYSTRINGLEN];
// int id;
}Channel;
typedef struct {
char username[MYSTRINGLEN];
char name[MYSTRINGLEN];
} Registration;
int main(int argc, char *argv[]){
int i = 0;
//int w = 0; not needed
int k = 0;
char line[100];
Channel channels[BUFSIZ] = {{{0}}}; // num of brackets depends on num of nested data structure
Registration registrations[BUFSIZ] = {{{0}}};
/* init all to zero instead w/ bracket syntax
for (w = 0; w < BUFSIZ; w++){
channels[w].id = -1;
strcpy(channels[w].name, "n");
}
*/
FILE * file1 = fopen("channels.txt", "r");
//Many people use strtok to get done what you are doing here if you are interested
while(fgets(line,100,file1)){ // do not need to explicitly state NULL
printf("Line read %s\n", line);
line[strlen(line) -1] = 0;
//Channel a; You have already initialized a whole array of struct, just use them
strcpy(channels[i].name, line);
//a.id = 1;
//channels[i]=a;
i++;
}
fclose(file1);
for(k = 0; k < BUFSIZ; k++){
if (0 != channels[k].name[0]){ //can test if string was populated, dont need id flag
printf("testing var with channels: %s\n", channels[k].name);
}
}
return 0;
}
de here

Error with content being read out of file

Hello fellow programmers i am trying to understand what exactly is happening in this area of my code.
Problem: I read some contents into a file , then i am trying to read back the contents out of the file just to make sure its the right contents i had put into the file but it is not giving me the correct output, so i am a little confused here is the code(saved content as binary) :
typedef struct acc
{
int id_no;
int pin;
float bal;
}Acc;
int Crte_acc(FILE *flepss)
{
int i,cnt;
Acc user[1000];
cnt = 1000;
for (i=1;i<1000;i++)
{
cnt+=1;
user[i].id_no = cnt;
user[i].bal=1000;
user[i].pin=0000;
fwrite(&user[i].id_no,sizeof(int),1,flepss);
fwrite(&user[i].pin,sizeof(int),1,flepss);
fwrite(&user[i].bal,sizeof(int),1,flepss);
}
return fclose(flepss);
}
Yea so above is the code that takes a file pointer and a count to keep the id to increase by 1 ( 1001,1002 etc), bal and pin required that i set the var with those digits.So i am wondering whats the problem, this is the code of me displaying the contents.
void DisplyFile()
{
FILE *dfp;
int x;
Acc pruser[1000];
dfp = fopen("Account.dat","rb");
fseek(dfp,0,SEEK_SET);
while (1)
{
if(!feof(dfp))
{
for (x=1;x<1000;x++)
{
fread(&pruser[x].id_no,sizeof(pruser[x].id_no),1,dfp);
fread(&pruser[x].pin,sizeof(pruser[x].pin),1,dfp);
fread(&pruser[x].bal,sizeof(pruser[x].bal),1,dfp);
printf("%d ",pruser[x].id_no);
printf("%d ",pruser[x].pin);
printf("%.2f\n\n",pruser[x].bal);
}
}
else
{
break;
}
}
}
EDIT: By contents coming out wrong i mean , giving me garbage values as to show that my write to file was not saved.
The problem may come from a missing fclose or fopen...
There is almost nothing to do to build something that works.
Three things to check :
-Does a fopen correspond to a fclose ?
-Are opening types similar ? Are both "wb" and "rb" used ?
-Another point is fwrite(&user[i].bal,sizeof(int),1,flepss);...bla is a float. float and int may have the same sizeof, but...It is safer to assume that it is not always the case !
#include <stdio.h>
typedef struct acc
{
int id_no;
int pin;
float bal;
}Acc;
int Crte_acc()
{
FILE *flepss;
int i,cnt;
Acc user[10];
cnt = 1000;
flepss = fopen("Account.dat","wb");
for (i=1;i<10;i++)
{
cnt+=1;
user[i].id_no = cnt;
user[i].bal=10;
user[i].pin=0000;
fwrite(&user[i].id_no,sizeof(int),1,flepss);
fwrite(&user[i].pin,sizeof(int),1,flepss);
fwrite(&user[i].bal,sizeof(float),1,flepss);
}
return fclose(flepss);
}
void DisplyFile()
{
FILE *dfp;
int x;
Acc pruser[10];
dfp = fopen("Account.dat","rb");
fseek(dfp,0,SEEK_SET);
while (1)
{
if(!feof(dfp))
{
for (x=1;x<10;x++)
{
fread(&pruser[x].id_no,sizeof(pruser[x].id_no),1,dfp);
fread(&pruser[x].pin,sizeof(pruser[x].pin),1,dfp);
fread(&pruser[x].bal,sizeof(pruser[x].bal),1,dfp);
printf("%d ",pruser[x].id_no);
printf("%d ",pruser[x].pin);
printf("%.2f\n\n",pruser[x].bal);
}
}
else
{
break;
}
}
fclose(dfp);
}
int main()
{
Crte_acc();
printf("file printed\n");
DisplyFile();
printf("end file read 1\n");
DisplyFile();
printf("end file read 2\n");
return 0;
}
To compile : gcc main.c -o main
Bye,

Resources