Using fread() to read struct - c

i am trying to use fread to enter data to this structure, i have defined this structure as an header like this
#ifndef__HEADER_H__
#define__HEADER_H__
struct input_par
{
char key[5];
char key_node[5];
char src_ip[15];
char dst_ip[15];
char src_port[5];
char dst_port[5];
};
#endif
in my main function, in file input_data i have stored this data
#822!822!172.28.6.137!172.28.6.110!5000!6000|
for me # means start of the data and | means end of valid data here i want to enter 822 to key, 822 to key_node, 172.28.6.137 to src_ip and so on 6000 to dst_port, i am not able to do this for testing purpose i am just entering only 822 to key. I am using fread for the first time please help
#include"file_header"
#include <stdio.h>
main()
{
int i;
struct input_par input_par;
FILE *fp;
fopen("input_data","r");
if(*fp == "#")
{
while(*fp!= "!")
{
for(i=0;i<5;i++)
{
fread(&input_par.key, sizeof(input_par),1,fp);
printf("%d\n",input_par.key);
}
}
}
fclose(fp);
}

Well, you have some errors in your code. As #unaperson pointed out, that is not the use of FILE, and definitely you should learn about it.
If you are going to read each char in the file, and interpret # as a delimiter, you can use fgetc instead of fread, which is used for reading big chunks. Be aware that fgetc returns an int, in order to be able to check the end-of-file error condition (you cannot read anymore).
You can read each field until the next delimiter, and store it in the appropriate field of your struct.

Related

How to get data from CSV file to struct by C language?

I have an csv file (delimited by commas). I want to get data in this file to struct. But it's not work correct. And I want get data from row 2 (ignore header).
Sorry if my English not good.
Thank you for your help.
#include <stdio.h>
struct Student
{
char id[7];
char firstname[50];
char lastname[50];
char gender[6];
char birthday[10];
char department[5];
char city[50];
};
int main()
{
struct Student st[100];
int n=0;
FILE *filename;
filename = fopen("student.csv","r");
while (!feof(filename))
{
fscanf(filename,"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,]",st[n].id,st[n].firstname,st[n].lastname,st[n].gender,st[n].birthday, st[n].department,st[n].city);
n++;
}
fclose(filename);
printf("%s\n",st[0].id);
printf("%s\n",st[0].firstname);
printf("%s\n",st[0].lastname);
printf("%s\n",st[0].gender);
printf("%s\n",st[0].birthday);
printf("%s\n",st[0].department);
printf("%s\n",st[0].city);
return 0;
}
In CSV format at the end of each line, you usually don't have a comma, If that is the case in your CSV file too, then change the format you are providing to fscanf,
from this,
"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,]"
to this,
"%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]"
if you try to read till next comma , for the city field too, then you will end up reading the string city\n6929245 to st[n].city which is wrong and will result in an incorrect reading pattern and might end up in segfault.
And to avoid printing the first line, you can skip the index 0 in your st array, because the first line that you read will be stored in the 0th index of the st array and from index 1 will be your data.

How to write string member of structure to file using fwrite?

I have a code in c and I am using structure which contains name to get user input using scanf() function. whenever i try to write the name in file using fwrite() it does not write all the characters I have enter but only few(only four characters). I know the problem is with sizeof() of fwrite() function but I cant figure what should be written inside sizeof() so I can store the string I get from user. I know it will work if char name[20] is used instead of char *name.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
struct Emp
{
char *name;
char *addr;
}*e;
int main()
{
FILE *fp;
e=(struct Emp *)malloc(sizeof(struct Emp));
e->name=(char *)malloc(sizeof(char )*20);
fp=fopen("Employee.txt","r+");
if(fp==NULL)
{
fp=fopen("Employee.txt","w+");
if(fp==NULL)
{
printf("cannot open the file");
exit(1);
}
}
printf("Name of Employee: ");
scanf("%s",e->name);
fwrite(e->name,sizeof(e->name),1,fp);
return 0;
}
If I input name of Employee: chiranjibi fwrite()function will only write chir in the file. Is there any way to get this code working so i can input any number of characters from user?
sizeof(e->name) returns the size of the pointer (typically 4 or 8)
Use strlen(e->name) to get the length of the string. Assuming the string in null terminated.
You can directly give 4 as the second parameter to fwrite() call.
fwrite(e->name,4,1,fp);
Hence, it only write first four character into the file. If you want to change based on user input, declare a variable and fetch from user the number of character to be printed and then pass the variable as the second parameter to this function call.

Reading in char from file into struct

For my assignment, I have to read in a text file with a varying amount of lines. They follow the following format:
AACTGGTGCAGATACTGTTGA
3
AACTGGTGCAGATACTGCAGA
CAGTTTAGAG
CATCATCATCATCATCATCAT
The first line is the original line I will testing the following ones against, with the second line giving the number of remaining lines.
I'm having trouble trying to save these to a struct, and can't even get the first line to save. I tried using the void function with an array and it seems to work, but can't seem to transfer it over to structs.
Here's my code so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
int main(){
char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");
char firstDna[LENGTH]="";
struct dna first;
struct dna first.code[]= "";
makeArray(input,first);
// printf("%s",filename);
system("pause");
return 0;
}
void makeArray(FILE *input,struct dna first){
int i=-1;
//nested for loops to initialze array
//from file
while(i != '\n'){
fscanf(input,"%c",first[i].code);
printf("%c", first[i].code);
i++;
}//closing file
fclose(input);
}
Since this is for a class assignment, I want to preface this by saying that a good way to tackle these types of assignments is to break it up into tasks, then implement them one by one and finally connect them. In this case the tasks might be something like:
parse the first line into a (struct containing a) char array.
parse the number into an int variable
parse each remaining line in the file like you did with the first line
test the first line against the other lines in the file (except the number)
You also mentioned in a comment that the struct is for extra credit. For that reason, I'd recommend implementing it using just a char array first, then refactoring it into a struct once you have the basic version working. That way you have something to fall back on just in case. This way of developing might seem unnecessary at this point, but for larger more complicated projects it becomes a lot more important, so it's a really good habit to get into as early as possible.
Now, let's look at the code. I'm not going to give you the program here, but I'm going to identify the issues I see in it.
Let's start with the main method:
char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");
This opens the file you're reading from. You're opening it correctly, but the first line is in this case unnecessary, since you never actually use the filename variable anywhere.
You also correctly close the file at the end of the makeArray function with the line:
fclose(input);
Which works. It would, however, probably be better style if you put this in the main method after calling the makeArray function. It's always a good idea to open and close files in the same function if possible, since this means you will always know you didn't forget to close the file without having to look through your entire program. Again, not really an issue in a small project, but a good habit to get into. Another solution would be to put the fopen and fclose functions in the makeArray function, so main doesn't have to know about them, then just send the char array containing the filepath to makeArray instead of the FILE*.
The next issue I see is with how you are passing the parameters to the makeArray function. To start off, instead of having a separate function, try putting everything in the main method. Using functions is good practice, but do this just to get something working.
Once that's done, something you need to be aware of is that if you're passing or returning arrays or pointers to/from functions, you will need to look up the malloc and free functions, which you may not have covered yet. This can be one of the more complex parts of C, so you might want to save this for last.
Some other things. I won't go into detail about these but try to get the concepts and not just copy paste:
struct dna first.code[]= ""; should probably be first.code[0] = \0;. \0 is used in C to terminate strings, so this will make the string empty.
Passing %c to fscanf reads a single character (you can also use fgetc for this). In this case, it will probably be easier using %s, which will return a word as a string.
Assuming you do use %s, which you probably should, you will need to call it twice before the loop - once to get the first DNA sequence and another time to get the number of other DNA sequences (the number of iterations).
Each iteration of the loop will then test the original DNA sequence against the next DNA sequence in the file.
I hope that helps!
sample to fix
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
struct dna *makeArray(FILE *input, int *n);//n : output, number of elements
int main(void){
char filename[] = "input1.txt";
FILE *input = fopen(filename,"r");
struct dna first = { "" };
fscanf(input, "%24s", first.code);//read first line
printf("1st : %s\n", first.code);
int i, size;
struct dna *data = makeArray(input, &size);//this does close file
for(i = 0; i < size; ++i){
printf("%3d : %s\n", i+1, data[i].code);
}
free(data);//release data
system("pause");
return 0;
}
struct dna *makeArray(FILE *input, int *n){//n : output, number of elements
int i;
fscanf(input, "%d", n);//read "number of remaining lines"
struct dna *arr = calloc(*n, sizeof(struct dna));//like as struct dna arr[n] = {{0}};
for(i = 0; i < *n; ++i){
fscanf(input, "%24s", arr[i].code);
}
fclose(input);
return arr;
}
a simple fix might be :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
void makeArray(FILE *input,struct dna *first){
int i=0;
fscanf(input,"%c",&first->code[i]);
printf("%c",first->code[i]);
while(first->code[i] != '\n' && i < LENGTH){
i++;
fscanf(input,"%c",&first->code[i]);
printf("%c",first->code[i]);
}
}
int main() {
struct dna first;
char filename[] = "input1.txt";
FILE *input = fopen(filename,"r");
makeArray(input,&first);
fclose(input);
printf("%s",first.code);
return 0;
}
PS: i tried to not change your original code
in order to change the code[Length] in the makeArray function you will have to pass it's adresse this is why i call mkaeArray function this way : makeArray(input,&first);.

How read lines of file and get them to array in C?

I would like to create a function to read file line by line. One every line is one name.
int readConfig(char ** path, FILES ** files )
{
FILE* f;
f = fopen("file", "r");
int ch;
while ((ch=fgetc(f)) != EOF )
{
}
return 0;
}
How to use the fgetc function to parse the file? And how to get the results to the files[count].name?
Right off the bat:
char configFile [11] = "kernels.cfg";
[11] is too small. Try:
char configFile [12] = "kernels.cfg";
or
char configFile [] = "kernels.cfg"; /* let the compiler do the counting */
Also char is too small for ch -- use:
int ch;
You may also find fgets() -- which reads a whole line at at time -- simpler to use than fgetc().
You are getting SIGSEGV because of modifying string literal and that causes an undefined behavior (e.g. your SIGSEGV). I am not sure what should be stored in filename and name variables. If by line:
strcpy(files[count].filename,'.bin');
you've meant to add a '.bin' to filename variable, then this approach is wrong. You should use strcat. strcpy would write to filename from beginning of this variable, so some chars previously saved there would be overwritten. strcpy also adds a null termination char, so if you wanted to print it out, printf would stop on that \0 char and won't go further. However, the real problem is that you should allocate with malloc some space for your variables in struct. Then you will be able to modify them.
Consider simple example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct file {
char* name;
char* filename;
};
int main(void)
{
struct file x;
x.name = malloc(30);
x.filename = malloc(40);
strncpy(x.name, "copied_string", 13);
printf("%s\n", x.name);
strcat(x.name, "_suffix");
printf("%s\n", x.name);
strcpy(x.name, "erased");
printf("%s\n", x.name);
free(x.name);
free(x.filename);
return 0;
}
output:
copied_string
copied_string_suffix
erased
This should make it a little more clear what's the origin of your crash. You should also consider using fgets or getline. Remember to free what you've malloc'd.
EDIT:
Calling readConfig(&path, &files); results in passing to readConfig a pointer of type FILES (*)[256]. Consider changing FILES files[256]; to
FILES* files = malloc(sizeof(FILES)*256);
and later call your function like readConfig(&path, files);
Then you would pass to readConfig function a compatible type of files.

Reading/Writing/Modifying a struct in C

I am taking some information from a user (name, address, contact number) and store it in a struct. I then store this in a file which is opened in "r+" mode. I try reading it line by line and see if the entry I am trying to enter already exists, in which case I exit. Otherwise I append this entry at the end of the file. The problem is that when I open the file in "r+" mode, it gives me Segmentation fault!
Here is the code:
struct cust{
char *frstnam;
char *lastnam;
char *cntact;
char *add;
};
Now consider this function. I am passing a struct of information in this function. Its job is to check if this struct already exists else append it to end of file.
void check(struct cust c)
{
struct cust cpy;
FILE *f;
f=fopen("Customer.txt","r+");
int num=0;
if (f!= NULL){
while (!feof(f)) {
num++;
fread(&cpy,sizeof(struct cust),1,f);
if ((cpy.frstnam==c.frstnam)&(cpy.lastnam==c.lastnam)&(cpy.cntact==c.cntact)&(cpy.add==c.add))
{
printf("Hi %s %s. Nice to meet you again. You live at %s and your contact number is %s\n", cpy.frstnam,cpy.lastnam,cpy.add,cpy.cntact);
return;
}
}
fwrite(&c,sizeof(struct cust),1,f);
fclose (f);
}
printf("number of lines read is %d\n",num);
}
The problem is that your structure contains pointers to strings and not strings themselves. So freading and fwriting will not work because the pointer values will be read and written but aren't valid between runs of the application.
A simple fix would be to change the structure to:
struct cust{
char frstnam[25];
char lastnam[25];
char cntact[25];
char add[25];
};
It's not a great fix, but it is a fix and might work for you.
Also, comparing strings that way won't work - that just compares the pointers.
You might want something more like this:
if ( strcmp(cpy.frstnam,c.frstnam) == 0 && strcmp(cpy.lastnam,c.lastnam) == 0 ...
{
printf("Hi ...
return;
}
That will compare the actual contents of the string arrays, not the pointers.
Also "&" is a bitwise AND and "&&" is the logical AND you want here.
If you find a matching contact, your current code will return without first closing the file. Eventually you may run out of available file descriptors and calls to fopen will fail.

Resources