I have my struct, and I have a vector of that struct. Also, I have a .csv file with data separated by comma.
What I need to do is take each value of every line of the .csv file and throw it into my struct vectors. Each line corresponds to a different vector index.
File.csv model
1,carlos,1232
321,patricia,212
5,james riko,23432
The quantity of fields in the same lane may vary, but it will always be separted by comma only.
I did something using strtok() but I couldn't find a way to fill the struct with that.
My Code:
typedef struct{
int num_acc;
char name[25];
double value;
}struct_acc;
int main(){
FILE *arq_acc;
struct_acc acc[3];
char buffer[256];
char *pointer;
arq_acc = fopen("accs.csv", "r");
if(arq_acc == NULL){
printf("Error"); exit(0);}
while(pointer = fgets(buffer, sizeof(buffer), arq_acc) ){
char *token;
while( (token = strtok(pointer, ",") != NULL){
//Then I don't know how to fill the struct vector.
}
return 0;
}
I just pasted my old code to show you that I'm actually trying to do something.
I couldn't find a way to do what I need with this code, so I can get total differente code ideas to reach my goal.
In the old code, I need to restart the loop to change to the next value of the currently lane, then I can't add something like this:
while( (token = strtok(pointer, ",") ) != NULL ){
acc[0].num_acc = token;
// Now I need to set pointer as NULL and read the token again, to get the next value of the first row. But I can't do it like this. ;\
}
Since the data in the file are uniform, you can use sscanf. Keep track of an index that indicates which account from the array to fill.
sscanf(buffer, "%d,%24[^,],%lf",
&(acc[index].num_acc),
acc[index].name,
&(acc[index].value));
Related
I am trying to place some text into a structure part of my array is a array which takes part of the text.
For example my structure is:
struct animal
{
char animal_Type[11];
int age;
int numberOfLegs;
int walksPerDay;
char favoriteFood[];
};
I will then have input such as:
dog,2,4,2,biscuits,wet
cat,5,4,0,biscuits,wet,dry,whiskers
bird,1,2,0,birdseed,biscuits,bread,oats,worms,insects,crackers
I have a working solution that places all the values up to walks per day into the structure, however I want to be able to place the food items into Favorite food. I have a dynamic array for this, but i'm not sure how to read remaining text into the favoriteFood array.
The code used is:
fp = open("animals.txt","r");
struct animal *animal = malloc(sizeof(sturct animal)*3);
int i = 0;
if(fp != NULL) {
while(i < 3) {
fscanf(fp,"%s %d %d %d %s",
animal[i].animal_Type,
animal[i].age,
animal[i].numberOfLegs,
animal[i].walksPerDay,
animal[i].favoriteFood); // need to be able to enter the string of food into here
i++
}
How would I go about doing this?
First of, your struct doesn't match what you've said in the comments.
char favoriteFood[];
The above is an array of char, so couldn't possibly hold a list of favourite foods except if it were one string. And since the size of the array is unspecified, you'd not be able to fill it like you have been either. Instead what you actually want is
char **favoriteFood;
unsigned int favoriteFoodSize;
That will let you create an expanding list of strings to fit whatever data you need to accommodate.
As for reading it in, the best way would be to read the entire line in using fgets and then use something like strtok to break the line up by your separator character. First define a very large string to hold the entire line and a char * to hold each field.
char buffer[1024];
char *token;
And then to the main loop would be something like this:
while(fgets(buffer,1024,fp)) {
token=strtok(buffer,",");
strcpy(beasts[i].animal_Type,token);
token=strtok(NULL,",");
beasts[i].age = atoi(token);
/* etc... */
}
You'd need to check whether token is ever NULL to cope with the possibility of short lines and handle it accordingly. And also make sure that the string copied into animal_Type isn't longer than 10 characters...or alternative make it a char * so you can have any size of string.
For the favoriteFood, you'll need to use realloc to increase the size of it to accommodate each new food added and keep going through the string until you run out of tokens.
token=strtok(NULL,",");
if(token) {
beasts[i].favoriteFood=malloc(sizeof(char *));
beasts[i].favoriteFood[0]=strdup(token); // Need to index using 0 as favoriteFoodSize won't have a value yet
beasts[i].favoriteFoodSize=1;
token=strtok(NULL,",");
while(token) {
beasts[i].favoriteFood=realloc(beasts[i].favoriteFood,(beasts[i].favoriteFoodSize+1)*sizeof(char *));
beasts[i].favoriteFood[beasts[i].favoriteFoodSize]=strdup(token);
beasts[i].favoriteFoodSize++;
token=strtok(NULL,",");
}
}
The last food will have a \n in it as fgets keeps it in the buffer it reads, so you could use that to tell if you've finished processing all the foods (you will also need to remove it from the last food). Or if you don't have it, you know the line was longer and you'll need to read more in. But that seems unlikely based on your sample data.
And since you're doing lots of memory allocation, you should ensure that you check the values returned to make sure you've not run out of memory.
I've been looking for answer here, but didn't find solution for this particular problem.
I have this csv file
For imagination, I should have creating hockey players from this .csv file as
enum POZICE { UTOCNIK = 'U', OBRANCE = 'O', BRANKAR = 'B' };
typedef struct hrac {
int cislo;
char jmeno[50];
enum POZICE pozice;
int utocnaSila;
int obrannaSila;
struct hrac *dalsi;
} tHrac;
Number, name, position of player(keeper, defender, etc.), his attack power, defensive power and link to next player.
Creating method:
tHrac* vytvorHrace(int cislo, char* jmeno, enum Pozice pozice, int utocnaSila, int obrannaSila) {
tHrac* hrac = (tHrac*)malloc(sizeof(tHrac));
hrac->cislo = cislo;
strcpy(hrac->jmeno, jmeno);
hrac->pozice = pozice;
hrac->utocnaSila = utocnaSila;
hrac->obrannaSila = obrannaSila;
hrac->dalsi = NULL;
}
And now the core of my problem, loading method
void nactiSeznamHracu() {
char *tmp1[30];
char *tmp2[30];
char *tmp3[30];
char *tmp4[30];
char *ch[255];
int a = 0;
FILE* soubor = fopen(SEZNAM, "r");
fgets(ch, sizeof(ch), soubor);
fputs(ch, stdout);
sscanf(ch, "% [^;]%[^;]", tmp1, tmp2); // parsing whole char *ch into smaller pieces, wont work
puts(tmp1,tmp2);
fscanf(soubor, "%c [^;]%s [^;]", tmp3,tmp4); // without saving first line into ch, and cutting it right away
puts(tmp3);
//token = strtok(ch, "\n");
//puts(token);
}
I can succesfully load first line, but when I try somehow cut the lines into smaller pieces, like Number,Name,Attack,Deffence,Position, it won't work(or cutting only header into smaller pieces), I tried many ways, more than I've here, but result was always the same... (first two lines of img is unrelated, was just testing tHrac, creating and writing)
My intention is to create for cycle where it will load first line, load it seperately into variable which i will use to create tHrac and then it skip into next line and same thing ...
But my experience with C is low, so that's why I'm turning on you. Anyone can help?
sscanf(ch, "% [^;]%[^;]", tmp1, tmp2); // parsing whole char *ch into
puts(tmp1,tmp2);
fscanf(soubor, "%c [^;]%s [^;]", tmp3,tmp4);
tmp1 ,tmp2 and all are array 30 of pointers to char , and passing wrong arguments would cause undefined behavior.
In case either you need to use individual pointer of these arrays after allocating memory to them ,
Or use them as array to char or char * , and you need to allocate memory in latter case and then pass them to sscanf or fscanf.
Note- Also you should check return value of sscanf and fscanf functions .
I made a simple dictionary code, and surfed for an hour, and I found a file I/O code. But my compiler(I use Microsoft visual C++) says my code(unfortunately, the core part of the code) is wrong. but I can't get it. What is actually wrong and why???
/*
DosDic ver 1.0.0 2015-07-03
*/
#include<stdio.h>
#include<string.h>
char key = 0;
FILE *fp; //set a file pointer var
fp = fopen("dicdata.dat","r"); //open a file
int b = 0;
int trial = 0;
char result[];
char searchfor[] = fp; //save a whole list of dictionary in a var
int i;
char sb[]; //var for search in a list
int getsearchtrial(char sb[]){
for(i=0;i=strlen(sb);i++){ //how much I tried to reach to the word
switch((int)searchfor[b]-(int)sb[i]){ //are two alphabets same?
case 0 :
default : i=0;
}
b++; //keep finding in a list
trial++; //try again
}
return trial;
}
int adress;
int mainpage(){
printf("Type what you want to search : ");
scanf("%c",sb[ ]);
getsearchtrial(sb[ ]) - strlen(sb[ ]) = adress; //where the word is located in the list
for(i = adress;i = adress + 30; i++){ //print
printf("%c",searchfor[i]);
}
printf("Thank you for using DosDic ver.1.0!"); //thank you!
}
void main(){ //call all those functions
mainpage();
fclose(fp); //close list
}
//and whats wrong with this? i cant even get it, but it's not working
Multiple issues.
First of all, you can't assign the result of fopen to fp outside the body of a function; you must move fp = fopen("dicdata.dat", "r"); to within the body of one of your functions (getsearchtrial most likely).
Secondly, you don't read from a file by simply assigning a file pointer to an object; you must use a library function like fscanf or fread or fgets. Assuming your file contains a single string of length 80, you'd need to write something like
char searchfor[81] = {0}; // make sure string is initially empty,
// extra space for string terminator
if ( !fgets( searchfor, sizeof searchfor, fp) )
{
// error reading from file
}
Of course, this depends on how your input file is structured. If it contains a list of strings, then you'll need to use a multidimensional array (or some other structure).
Third, when you declare an array, must specify its size before you can use it. result and searchfor are incomplete array definitions.
Finally, this line
getsearchtrial(sb[ ]) - strlen(sb[ ]) = adress;
needs to be reversed; the target of an assignment must be on the left of the assignment operator.
You need to step back and learn how to write C code from the ground up.
There is so much wrong I'm not even going to itemise it all here - most of it seems to stem from your lack of understanding of arrays in C.
Most notably...
You can't declare an array and not initialise it or specify a size.
You can't assign a FILE * to a char array (and expect decent
results).
You can't execute a statement like fp = fopen at the
global scope like you are.
Try this tutorial and you may fix 95% of your problems, then go from there.
So what my program should do is: Read a .txt file with this piece of code.
FILE *fp;
char filename[40],part1[4],part2[4];
int c=0,pt1,pt2;
printf("\nEnter a file name to open: ");
gets(filename);
if ((fp = fopen(filename, "r"))!= NULL)
{
printf("\nThe file %s was opened successfully!",filename);
}
else
{
printf("\nThe file didnt open succesfully!");
}
And then store each line in the row string like this.
fgets(part1,4,fp);
pt1 = atoi(part1);
struct input
{
char name[20],row[30],code[3],nPieces[3],needed[3],usage[3],nUses[3];
};
struct input list[pt1];
while (c++ < pt1 )
{
fgets(list[c].row,30,fp);
printf ("\n%s", list[c].row);
}
But the problem is that after that i must take the row string and cut it into pieces (for exp the 1st line of txt was <1 Glass 2 0 9 3 1> where each number represents something) So what i want is to put the "1" into the code[3] string the "Glass" into the name[30] string etc. I tried to make it work using the isspace() scaning the row string and whenever it found a space it would copy the row array from 0-(the space - 1) using strncpy(). For some reason when ever i run tha program is stops working. Anyone that could suggest anything?
It seems you want to allocate an array of size pt1, but that won't work because this is compile time and the value of pt1 is not known.
With:
struct input
{
char name[20],row[30],code[3],nPieces[3],needed[3],usage[3],nUses[3];
};
you declare a variable, but it seems you want to define a type, so:
typedef struct input
{
char name[20],row[30],code[3],nPieces[3],needed[3],usage[3],nUses[3];
};
and then later you must malloc the memory:
struct input list= calloc(pt1, sizeof(struct input));
The statement
struct input list[pt1];
should give a compiler error (does with my compiler).
So what i want is to put the "1" into the code[3] string the "Glass"
into the name[30] string etc.
It's much easier with sscanf() rather than isspace() and strncpy():
sscanf(list[c].row, "%2s%19s%2s%2s%2s%2s",
list[c].code,
list[c].name, list[c].nPieces, list[c].needed, list[c].usage,
list[c].nUses)
I need to access a variable length array i have created on the first line reading from a file.
In order to access the array for when i am reading the following lines i would need to initialize it before line 1 is read out side of my conditional statement. but this is before I know the length of the array.
here is an example of my code
int count=0;
while (fgets(line, sizeof(line), fd_in) != NULL) {
if(count==0){
//get wordcount from line
int word[wordcount];
//put line data into array, using strtok()
}else{
//need to access the array here
}
count++;
}
Edit: My question is how should i go about being able to access this array where i need it?
Looks like you want contents of word array to be preserved between loop iterations. This means, you must put the array to the scope outside the loop. In your question code, you want to determine size inside the loop, so you'd essentially need to redefine the size of VLA, which is not possible. You can do this by using malloc as shown in another answer, but looking at your code, it's better to duplicate your call to fgets, allowing you to move the definition of VLA outside your loop, something like:
if(fgets(line, sizeof(line), fd_in) != NULL) {
//get wordcount from line
int word[wordcount];
//put line data into array, using strtok()
int count = 1; // start from 1 per your question code, is it right?
while(fgets(line, sizeof(line), fd_in) != NULL) {
//need to access the array here
count++;
}
}
VLA arrays can't be accesses outside of the scope where they are declared (the scope is inside { } symbols).
So, if your fileformat has the total count in first line, you can use dynamic memory, and malloc your array:
int *words = NULL;
int count=0;
while (fgets(line, sizeof(line), fd_in) != NULL) {
if(count==0){
int wordcount = ... //get wordcount from line
//Allocate the memory for array:
words = (int*) malloc( wordcount * sizeof(int) );
//put line data into array, using strtok()
}else{
//need to access the array here
words[count-1] = ....
}
count++;
}