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.
Related
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);.
#include<stdio.h>
#include<conio.h>
typedef struct cr{
char name[20];
int credit;
}cr;
void main(){
int i ;
FILE *fp;
cr *ptr;
cr data[20];
clrscr();
ptr=data;
fp=fopen("c:\\new\\damn.txt","rb");
fread(ptr,sizeof(cr),1,fp);
printf("%s\n",ptr->name);
getch();
}
the file damn.txt has a string and an int with spaces in between them
content : " prateek 20"
but when i read this file with fread and then when i am printing the contents of the structure using %s and %d , i found out that all the content is stored in structure only in name array and nothing is stored in credit ? what is happening ?how can i read the structure in the format of sturcture ? and save it in the variables respectively ?why 20 is not storing in credit ?
I always do
memset(cr, 0, 20);
fread(pt,19,1,fp);
So you always have a terminating null at the end
I'm new here, and I need some help. :)
I am working on a program that has to write and read a binary file. I have to add lectures to it, they look like:
COURSECODE;COURSENAME;MAXAPPLICANTS;ACTUALAPPLICANTS;
I could write that in a file without any problems using char*.
My question is: how do I read that back in a struct if the records are non-fixed size? (e.g.: coursename can be Linear Algebra or Analysis -> length is non-determined) I also need to modify the actual applicants number, how do I find the character position of it, and the current line?
I'd be happy with ideas, and I would appreciate any source code as well, I was programming in C++ and C is a hard step-back for me.
Thank you in advance!
Your structure looks like
struct student {
char *coursecode;
char *coursename;
char *max_applicants;
char *actual_applicants;
};
Just add another member into your structure say int size which stores total size of structure.
Every time when you read from binary file you should read first 4 bytes you will get complete size of record,then see how many characters are there into record,read that much and tokenize string by ; you will find your records.
without termination characters it is impossible.
If you dedicate some character to split data apart, then its possible.
for instance, 3 strings can be told apart by their \0. so you read until \0, three times.
You could read the file into a char* buffer, then replace any ; with \0 (the string termination character) and finally you take pointers of the begins of the fields into your struct:
struct student {
char *coursecode;
char *coursename;
char *max_applicants;
char *actual_applicants;
};
You might want to parse numeric fields with atoi first.
Piece of advice #1: if you're Hindi and you ever re-born, start by learning C, only then transition to C++.
Piece of advice #2: so if I understand correctly, you have four strings in a row, separated by semi-colons. Then you can use strtok_r() to split up each line and put the contents of the file in an array of structs (all error checking omitted for clarity, but you should definitely have some):
typedef struct {
char *code;
char *name;
int max_appl;
int cur_appl;
} Course;
char buf[1024];
FILE *f = fopen("courses.txt", "r");
size_t size = 0;
size_t allocsize = 8;
Course *c = malloc(allocsize * sizeof(*c));
char *end;
while (fgets(buf, sizeof(buf), f) != NULL) {
if (size >= allocsize) {
allocsize <<= 1;
c = realloc(c, allocsize * sizeof(*c));
}
c[size].code = strdup(strtok_r(buf, ";", &end));
c[size].name = strdup(strtok_r(NULL, ";", &end));
c[size].max_appl = strtol(strtok_r(NULL, ";", &end), NULL, 10);
c[size].cur_appl = strtol(strtok_r(NULL, "\n", &end), NULL, 10);
size++;
}
int i;
for (i = 0; i < size; i++) {
Course *p = c + i;
printf("%s\n%s\n%d\n%d\n\n", p->code, p->name, p->max_appl, p->cur_appl);
free(p->code);
free(p->name);
}
free(c);
fclose(f);
Trying to scan from a file into a C array but I'm getting an error. It worked for me when I was using a file with only numbers on each line like:
1.2
3.4
5.2
But now I have this file:
0001:Satriani:Joe:6:38.0
0002:Vai:Steve:1:44.5
0003:Morse:Steve:10:50.0
0004:Van Halen:Eddie:3:25.75
0005:Petrucci:John:8:42.25
0006:Beck:Jeff:3:62.0
Here is how I'm trying to scan it into an array, but I get a segmentation fault!
FILE *employeesTXT;
int empID[100];
char lastName[100];
char firstName[100];
int payGroup[100];
double hoursWorked[100];
employeesTXT = fopen("employees.txt", "r");
if (employeesTXT == NULL)
{
printf("Error: file cannot be opened.\n");
} else {
while (fscanf(employeesTXT, "%[^:]:%[^:]:%[^:]:%d:%lf\n", &empID[i], lastName[i], firstName[i], &payGroup[i], &hoursWorked[i]) != EOF)
{
i++;
}
fclose(employeesTXT);
numRecords = i;
for(i = 0; i < numRecords; i++){
printf("%d - %s - %s - %d - %.2lf\n", empID[i], lastName[i], firstName[i], payGroup[i], hoursWorked[i]);
}
}
It has to be something in this line... %[^:]:%[^:]:%[^:]:%d:%lf\n
Your argument parameters are wrong for the strings:
fscanf(employeesTXT, "%[^:]:%[^:]:%[^:]:%d:%lf\n",
&empID[i], lastName[i], firstName[i], &payGroup[i], &hoursWorked[i])
lastName and firstName are declared as an array of 100 char. You want those to be strings so you need to define them to be an array of 100 "buffers".
Try changing the declarations to:
char lastName[100][50]; /* 50 or whatever the max length you'd expect + 1 */
char firstName[100][50];
I believe that should work just like that.
You also have a different issue with empID, you're reading the value as a string and not an integer. In the format, it should be %d for integers if these are indeed integers in your input.
As pointed out, for the names you are assigning each new employees' information into an one dimensional array, thereby overwriting the previous employee's information (except the first character). This eventually leads to your error when you try to assign a long enough name to an index near the end of your array which causing it to write over the last index. You can use a two dimensional array as suggested for the names:
char lastname[number_of_employees][maximum_length_of_name];
and each lastname[i] will be a null terminated string.
But, this is what structures are made for.
// Define it before main()
struct employee_type{
int empID;
char *lastname;
char *firstname;
int paygroup;
double hoursworked;
}
// In main()
struct employee_type employees[100]; // Declare an array of employee_type structures.
Change
char lastName[100];
char firstName[100];
to
char lastName[100][100];
char firstName[100][100];
Also while reading empID[i] don't use %[^:], use %d instead.
You need to have addresses as parameters for fscanf, this won't work as parameter as it is only a character:
lastName[i]
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.