reading a csv file into struct array - c

I'm beginning to code in C. My code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STR_LEN 256
#define MAX_BOOKS 256
struct book{
int ID;
char *name;
char *dateIn;
char *dateOut;
};
struct book books[MAX_BOOKS];
/* PROTOTYPE OF FUNCTIONS */
int readBookFile();
void printBookList();
int main(int argc, char **argv)
{
int isOK = 0;
isOK = readBookFile();
printBookList();
system("pause");
return 0;
}
int readBookFile()
{
/* FileStream for the Library File */
FILE *bookFile;
/* allocation of the buffer for every line in the File */
char *buf = malloc(MAX_STR_LEN);
char *tmp;
/* if the space could not be allocaed, return an error */
if (buf == NULL) {
printf ("No memory\n");
return 1;
}
if ( ( bookFile = fopen( "library.dat", "r" ) ) == NULL ) //Reading a file
{
printf( "File could not be opened.\n" );
}
int i = 0;
while (fgets(buf, 255, bookFile) != NULL)
{
if ((strlen(buf)>0) && (buf[strlen (buf) - 1] == '\n'))
buf[strlen (buf) - 1] = '\0';
tmp = strtok(buf, ";");
books[i].ID = atoi(tmp);
tmp = strtok(NULL, ";");
books[i].name = tmp;
tmp = strtok(NULL, ";");
books[i].dateIn = tmp;
tmp = strtok(NULL, ";");
books[i].dateOut = tmp;
//tempBook.ID = atoi(buf);
printf("index i= %i ID: %i, %s, %s, %s \n",i, books[i].ID , books[i].name, books[i].dateIn , books[i].dateOut);
i++;
}
//free(buf);
fclose(bookFile);
return 0;
}
void printBookList()
{
int i;
//i = sizeof(books) / sizeof(books[0]);
//printf ("%i \n", i);
for (i = 0; i <= sizeof(books); i++)
{
if (books[i].ID != 0)
printf("index i= %i ID: %i, %s, %s, %s \n",i, books[i].ID , books[i].name, books[i].dateIn , books[i].dateOut);
else
break;
}
}
The problem is, that after readBookFile() ends, the Array of my struct is full of the last value of the input file..
My input file is:
1;das erste Buch; 12122013; 13122013
2;das Zweite Buch; 12122013; 13122013
3;das dritte Buch; 12122013; 13122013
4;das vierte Buch; 12122013; 13122013
5;das fünfte Buch; 12122013; 13122013
6;das sechste Buch; 12122013; 13122013
so in the readBookFile function the printf returns the correct values, but in the printBooksList() function all values seem to have changed to the last line of my inputfile.
Can anyone explain this to me and maybe point me in the right direction?
Thanks a lot
Hagbart

The problem is your struct:
struct book{
int ID;
char *name;
char *dateIn;
char *dateOut;
};
name, dateIn, dateOut are "pointer", they are just point to something, you're not allocating spaces for them.
What you do is just point them to tmp(buf).
So what you do in printBookList() is just print same string block, while ID is OK since it's not pointer.
To solve this, allocate space for them, you can use strdup(), but make sure to free them.

In the while loop:
while (fgets(buf, 255, bookFile) != NULL)
you are copying into the memory location of buffer new contents from file. As tmp points to a certain point in the buffer, its contents are being replaced too.
tmp = strtok(NULL, ";");
books[i].name = tmp;
You should allocate memory for each struct of the array and then use strcopy.
You can find an explanation of differences between strcpy and strdup here:
strcpy vs strdup

The reason is that in something like
books[i].name = tmp;
You're not actually copying a string from tmp into books[i].name: you just make both point to the same location - somewhere into the buf buffer.
Try using strdup instead, as in:
books[i].name = strdup(tmp);

Related

How to read from the file and write it in the structure? I have a little trouble with my code

I have to write this code, I mean I should read from the file name of students and their mark, and then sort students by the grow of mark. Now I just want to output only mark. I want to display grades using structures. I don't know where the problem is.
text.file
Jon 3
Alina 5
Ron 1
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>
int main()
{
const int N = 3;
int i = 0;
struct student {
char surname[50];
int mark;
};
struct student PI1[N];
char str[50];
const char s[1] = " ";
char* token;
FILE* ptr;
token = strtok(str, s);
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
while (fgets(str, 50, ptr) != NULL){
token = strtok(str, s);
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
PI1[i].mark = atoi(token);
i++;
}
fclose(ptr);
printf("The marks is:\n");
printf("%d %d %d", PI1[0].mark, PI1[1].mark, PI1[2].mark);
return 0;
}
You need to prevent the program from reading from the file pointer if opening the file fails:
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
perror("test.txt");
return 1; // this could be one way
}
The second argument to strok should be a null terminated string. const char s[1] = " "; only has room for one character. No null terminator (\0). Make it:
const char s[] = " "; // or const char s[2] = " "; or const char *s = " ";
Don't iterate out of bounds. You need to check so that you don't try to put data in PI1[N] etc.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
// ^^^^^^^^
Check that strok actually returns a pointer to a new token. If it doesn't, the line you've read doesn't fulfill the requirements.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
token = strtok(str, s);
if(!token) break; // token check
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
if (token) // token check
PI1[i].mark = atoi(token);
else
break;
i++;
}
You could also skip the strcpy by reading directly into your struct student since char str[50]; has the same length as surname. str should probably be larger though, but for now:
while (i < N && fgets(PI1[i].surname, sizeof PI1[i].surname, ptr) != NULL) {
token = strtok(PI1[i].surname, s);
if(!token) break;
token = strtok(NULL, s);
if (token)
PI1[i].mark = atoi(token);
else
break;
i++;
}
Only print as many marks as you successfully read
printf("The marks are:\n");
for(int idx = 0; idx < i; ++idx) {
printf("%d ", PI1[idx].mark);
}
putchar('\n');

How can I read input from a text file into an array of structs in C? (Segmentation fault occuring)

I'm trying to read in a text file, say input.txt, into an array of structs to then print out (and free memory of course). My C coding is a bit scratchy though, and I'm looking for help.
Input.txt contains lines of information about a single person. I want to read in the people, sort by name and print out in sorted order. Before I can do this, I'm just trying to create an array of people, allocate memory to each person, copy in the details from the text file, and then print them out finally. It's not even getting to the print out, as you can see it gives a segmentation fault:
I'm using the following:
gcc -Wall -O2 -o program filename.c
and getting this
Segmentation fault: 11
input.txt contents:
Joan 0212672938 joan#gmail.com
John 0365242939 john#yahoo.com
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
char *phone;
char *email;
};
int main(void) {
int i;
int peopleSize = 0;
char * pch;
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
struct person** people = malloc(100 * (sizeof (people[0])));
/* Create 100 people */
char *nameTmp = malloc(30 * sizeof nameTmp[0]);
char *phoneTmp = malloc(30 * sizeof phoneTmp[0]);
char *emailTmp = malloc(30 * sizeof emailTmp[0]);
/* Open the file for reading */
char *line_buf = NULL;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(&line_buf, &line_buf_size, f);
while (line_size >= 1) {
line_count += 1;
people[line_count-1] = malloc(sizeof (people[line_count-1]));
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%s\n", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc((strlen(nameTmp) + 1) * sizeof (people[line_count-1]->name[0]));
people[line_count-1]->phone = malloc((strlen(phoneTmp) + 1) * sizeof (people[line_count-1]->phone[0]));
people[line_count-1]->email = malloc((strlen(emailTmp) + 1) * sizeof (people[line_count-1]->email[0]));
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(&line_buf, &line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i++) {
printf("%s\t", people[i]->name);
printf("%s\t", people[i]->phone);
printf("%s", people[i]->email);
printf("\n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i++) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}
In general, when debugging, I would recommend compiling without optimizations and with the debug flag (-g). Then step through your program in GDB and see where it breaks.
Most of the fixes were already mentioned in the comments. See the code below for a line-by-line explanation of the fixes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // now you can use "person" type rather than "struct person"
char *name;
char *phone;
char *email;
} person;
int main(void) {
int i;
int peopleSize = 0;
char * pch = malloc(30); // Must be initialized before use
FILE *f = fopen("input.txt", "r");
if (f == NULL) return EXIT_FAILURE;
person** people = malloc(100 * (sizeof(person*))); //This is an array of 100 pointers to person so you want sizeof(person*)
/* Create 100 people */
char *nameTmp = malloc(30); // These are char arrays. Each char occupys a byte and malloc allocates byte by default.
char *phoneTmp = malloc(30);
char *emailTmp = malloc(30);
/* Open the file for reading */
char *line_buf = malloc(30); // MUst be initialized before use;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
/* Get the first line of the file. */
line_size = getline(&line_buf, &line_buf_size, f);
while (line_size >= 1) {
line_count += 1;
people[line_count-1] = malloc(sizeof(person)); // You are allocating memory for a single person, so you want sizeof(person)
/* if fgets returns an empty space or new line, no more people to add, break loop */
/* Within str, use strtok to divide strings up into name, phone and email */
strcpy(pch, line_buf);
pch = strtok (pch, " ");
strcpy(nameTmp, pch);
printf("%s\n", nameTmp);
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(phoneTmp, pch);
}
if (pch != NULL) {
pch = strtok (NULL, " ");
strcpy(emailTmp, pch);
}
/* Allocate enough memory to person->name and person->phone and person->email as required */
people[line_count-1]->name = malloc(strlen(nameTmp) + 1); // As above these are char arrays so there is no need for sizeof
people[line_count-1]->phone = malloc(strlen(phoneTmp) + 1);
people[line_count-1]->email = malloc(strlen(emailTmp) + 1);
/* Now copy values from temporary variables into actual person */
strcpy(people[line_count-1]->name, nameTmp);
strcpy(people[line_count-1]->phone, phoneTmp);
strcpy(people[line_count-1]->email, emailTmp);
/* Get the next line */
line_size = getline(&line_buf, &line_buf_size, f);
}
peopleSize = line_count;
/* Printing all the people out */
for (i = 0; i < peopleSize; i++) {
printf("%s\t", people[i]->name);
printf("%s\t", people[i]->phone);
printf("%s", people[i]->email);
printf("\n");
}
/* Freeing all of the memory */
for (i = 0; i < peopleSize; i++) {
free(people[i]->email);
free(people[i]->phone);
free(people[i]->name);
free(people[i]);
}
free(people);
return EXIT_SUCCESS;
}

Read a CSV file into a dynamic array of structs C

I'm fairly new to C. I'm trying to read a .CSV file, then parse each line, then store the data in a dynamic array of pointers to structs. Unfortunately I've gone wrong somewhere in my implementation which is resulting in an infinite loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct dataSet {
char ID;
char postcode;
int population;
char contact;
double x;
double y;
}data;
int main(int argc, char* argv[]) {
char line[100] = "";
int count = 0;
int each = 0;
data *allData = NULL;
data *temp = NULL;
FILE *file = fopen("dataset.csv", "r");
if (file == NULL)
{
printf("Error! File null");
return 1;
}
while (fgets(line, sizeof line, file))
{
if(NULL == (temp = realloc(allData, sizeof(*allData) * (count + 1))))
{
fprintf(stderr, "realloc problem\n");
fclose(file);
free(allData);
return 0;
}
allData = temp;
if (6 == scanf(line, "%s, %s, %d, %s, %lf, %lf",
&allData[count].ID,
&allData[count].postcode,
&allData[count].population,
&allData[count].contact,
&allData[count].x,
&allData[count].y)) {
count++;
}
else {
printf("Problem with data\n");
}
}
fclose(file);
for (each = 0; each < count; each++)
{
printf("%s, %s, %d, %s, %lf, %lf\n",
&allData[count].ID,
&allData[count].postcode,
&allData[count].population,
&allData[count].contact,
&allData[count].x,
&allData[count].y);
}
free(allData);
return 0;
}
Any help or tips would be greatly appreciated.
[s]scanf() is a nasty function. You don't have enough control once it fails. Problem is: there are too many conditions: the input can be incorrect, or the destination is not large enough. Even reading complete lines with fgets(), and parsing them afterwards, will only allow you to skip complete lines; also: the line buffer is mostly fixed sized, and fgets() could read incomplete lines. A way to keep complete control is to read character-based. This might imply a Finite State machine.
A simpler reader (using a zero-state machine) could be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct omg {
char o;
int m;
char g[11];
};
struct wtf {
unsigned size;
unsigned used;
struct omg *array;
};
#define INITIAL_SIZE 7
struct wtf read_stuff(char *name)
{
FILE *fp;
unsigned icol,irec,len;
char buff[123];
struct wtf this = {0,0,NULL};
fp = fopen(name, "rb" );
if (!fp) return this;
for (icol=irec=len=0; ; ) {
int ch;
if (this.used >= this.size) {
size_t newsize;
struct omg *tmp;
newsize = this.size? this.size*2: INITIAL_SIZE;
fprintf(stderr, "Realloc(%zu)\n", newsize);
tmp = realloc(this.array, sizeof *this.array * newsize);
this.array = tmp;
this.size = newsize;
}
ch = getc(fp);
switch(ch) {
case '\r' : continue;
/* End of field or record: terminate buffer */
#if 0
case ',' :
#else
case '\t' :
#endif
case '\n' :
buff[len] = 0;
break;
case EOF :
goto done;
/* Normal character: assign to buffer
** You may want to report too long fields here
*/
default:
if (len >= sizeof buff -2) continue;
buff[len++] = ch;
continue;
}
/* When we arrive here, we have a new field. Let's process it ...*/
switch (icol) {
case 0: /* Assign first field here from buff[], (dont forget to check len!) */
this.array[this.used].o = buff[0];
break;
case 1: /* Assign second field from buff[], this may need some additional checks
** You may want to avoid sscanf() here ...
*/
sscanf(buff, "%d", &this.array[this.used].m );
break;
case 2: /* Assign third field from buff[] */
if (len >= sizeof this.array[this.used].g)
len = sizeof this.array[this.used].g -1;
memcpy (this.array[this.used].g, buff, len);
this.array[this.used].g[len] = 0;
break;
default: /* Ignore excess fields
** You may want to report hem.
*/
break;
}
/* Do some bookkeeping */
len = 0;
if(ch == '\n') {
/* You may want to check if icol==2, here */
icol=0; irec++; this.used++;
}
else icol++;
}
done:
fclose(fp);
/* You could do a final realloc() here */
return this;
}
int main(int argc, char **argv)
{
struct wtf result;
unsigned idx;
result = read_stuff(argv[1] );
fprintf(stderr, "Result=%u/%u\n", result.used,result.size);
for (idx=0; idx < result.used; idx++) {
printf("%c %d %s\n"
, result.array[idx].o
, result.array[idx].m
, result.array[idx].g);
if (idx >= 10) break;
}
return 0;
}
You ask for tips...
1 - your struct is wrong if your plan was to use dynamic memory. The char members should be pointers to char, ( char * not char ) as shown below. But to reduce complexity, use char arrays instead of forcing dynamic allocation for struct members: i.e. do not use this:
typedef struct dataSet {
char *ID;
char *postcode;
int population;
char *contact;
double x;
double y;
}data;
Rather use this:
typedef struct dataSet {
char ID[80];
char postcode[11];
int population;
char contact[80];
double x;
double y;
}data;
If the lengths are not right, then make them bigger, but this will reduce calls to calloc() and free().
2 - suggested steps:
Count lines in file. (example here). This will essentially open the file, count the lines and close the file.
Use the count to allocate memory for that number of instances of data (i.e. data *records = malloc(sizeof(*records)*countOfLines); )
Open the file again. If file != NULL, then...
Begin to read file line by line in a loop, such as the fgets(...) loop you have.
In this loop, suggest replacing scanf() with a series of calls to strtok() making the appropriate conversion one-by-one. Its a few more lines of code, but is easier in the long run to see what parsing problems you might run into.
The following pseudo code illustrates...
data *record = malloc(CountOfLines*sizeof(*record));
if(record)
{
int i = 0;
while(fgets(line, sizeof line, file))
{
tok = strtok(line, ",");
if(tok)
{ //convert string
strncpy(record[i].ID, tok, sizeof(record[i].ID) - 1);
tok = strtok(NULL, ",");
if(tok)
{//convert string
strncpy(record[i].postcode, tok, sizeof(record[i].postcode) - 1);
tok = strtok(NULL, ",");
if(tok)
{//convert int
record[i].population = atoi(tok);
//and so on ...

How to shift letters to the right or left?

I am given a file with a string, for example "The United States was founded in *1776*". What I cannot figure out is how to shift letters one space to the left or right and have the letters wrap around. I am able to shift the letters from an a to b but not change its location within the word.
Example of this output would be:
"heT
nitedU
tatesS
asw
oundedf
ni
1776**"
In C, strings are stored as an array of chars in memory. Unlike C++ vectors, you can not insert or remove element within the array, you can only access their value or change their value.
If you declare a C string as follows:
char *myStr = "Fred";
It will be stored in memory as a five character array with the 5th character being the zero value which terminates a C string:
myStr[0] = 'F'
myStr[1] = 'r'
myStr[2] = 'e'
myStr[3] = 'd'
myStr[4] = 0
You need to design a for loop that copies each array element to the one before, while remembering that you need to save the one you are about to overwrite. In this example, it should result in the following copy operations being performed:
len = strlen(myStr);
saveCh = myStr[0];
myStr[0] = myStr[1];
myStr[1] = myStr[2];
myStr[2] = myStr[3];
myStr[3] = saveCh;
So now your job is to create a for loop that does that for any C string of any length.
So to rotate the chars within a C string to the left, you need to copy each char in the array at index i to previous array element i-1. The tricky part is to handle the wrap around properly when i=0 (in this example, you want to copy myStr[0] to myStr[3]. Now do that with a for loop.
You need to also understand that the last character of any C string is the null character (value zero), which terminates a C string. If you modify that element in the array, then your string will break. That is why saveCh is copied to myStr[3] and not to myStr[4].
void rotateStrLeftOneChar(char *myStr) {
// Always check for error and special cases first!
// If myStr is a NULL pointer, do nothing and exit
// If myStr is less than 2 chars, nothing needs to be done too.
if ((myStr != NULL) && (strlen(myStr)>1)) {
int len = strlen(myStr);
char saveCh = myStr[0];
int i = 0;
// Copy each char at index i+1 left to index i in the array
for(i=0; i<len-2; i++)
myStr[i] = myStr[i+1];
// The last character is special and is set to saveCh
myStr[len-1] = saveCh;
}
}
If you just need to output the letters to shift to the left and don't want to change original input then you can do:
#include <stdio.h>
#include <string.h>
void shiftletters(char * input, int i);
int main () {
char input[256];
int shift;
printf("Enter input : ");
scanf("%[^\n]s", input);
printf("Number of shifts : ");
scanf("%d", &shift);
shiftletters(input, shift);
return 0;
}
void shiftletters(char * input, int numshifts)
{
char str[256] = {'\0'};
char * delim = " \t";
char * pch = NULL;
int j, k, len, shifts;
if (input == NULL)
{
printf ("Invalid input\n");
return;
}
strcpy (str, input);
pch = strtok (str, delim);
while (pch != NULL)
{
len = strlen (pch);
if ((numshifts == len) || (len == 1))
{
printf ("%s\n", pch);
pch = strtok (NULL, delim);
continue;
}
if (len < numshifts)
shifts = numshifts % len;
else
shifts = numshifts;
for(j=shifts; j<len; j++)
printf("%c", pch[j]);
for(k=0; k<shifts; k++)
printf("%c", pch[k]);
printf("\n");
pch = strtok (NULL, delim);
}
}
The output of the program:
Enter input : The United States was founded in *1776*
Number of shifts : 1
heT
nitedU
tatesS
asw
oundedf
ni
1776**
like this
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum { L = -1, R = 1};
char *rotate(char word[], int dir){
size_t len = strlen(word);
char *temp = malloc(len + 1);
if(!temp){
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(temp, word);
for(char *src = temp; *src; ++src, ++dir){//or use memmove
word[(dir+len)%len] = *src;
}
free(temp);
return word;
}
int main(int argc, char *argv[]) {
FILE *fp = fopen("data.txt", "r");
if(fp == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
if(argc < 2){
fprintf(stderr, "Usage %s L|R...\n", argv[0]);
exit(EXIT_FAILURE);
}
char word[64];
while(fscanf(fp, "%63s", word)==1){
for(char *shift = argv[1]; *shift; ++shift){
int dir = *shift == 'L' ? L : R;
rotate(word, dir);
}
printf("%s\n", word);
}
fclose(fp);
}
using memmove version
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum { L = -1, R = 1};
char *rotate1(char word[], int dir){
size_t len = strlen(word);
if(len > 2){
char temp;
if(dir == L){
temp = word[0];
memmove(word, word+1, len-1);
word[len-1] = temp;
} else if(dir == R){
temp = word[len-1];
memmove(word+1, word, len-1);
word[0] = temp;
}
}
return word;
}
int main(int argc, char *argv[]) {
FILE *fp = fopen("data.txt", "r");
if(fp == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
if(argc < 2){
fprintf(stderr, "Usage %s L|R...\n", argv[0]);
exit(EXIT_FAILURE);
}
char word[64];
while(fscanf(fp, "%63s", word)==1){
for(char *shift = argv[1]; *shift; ++shift){
int dir = *shift == 'L' ? L : R;
rotate1(word, dir);
}
printf("%s\n", word);
}
}

Parsing CSV data into structure

I have to put the data from a csv file (name, address, telephone...) to a structure of my C program. It's been unsuccessful, unfortunately. I tried using strtok function to break into tokens every time it finds a ";" (because we're dealing with a Comma Separated File).
Here's what I've done:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAX_STR_LEN 256
#define MAX_BOOKS 256
struct estrutura
{
int id;
char nome[40];
char endereco[40];
char cidade[40];
char pais[20];
char cep[10];
char nasc[12];
char telefone[14];
char total[20];
};
struct estrutura cliente[200];
FILE *pFile;
//allocate buffer in each line
char *buf = malloc(MAX_STR_LEN);
char *tmp;
void abrir();
/* Functions to be coded
int menu();
int menu2(); //manutencao de clientes
void adicionar();
void alterar();
void excluir();
void exibir();
void pesquisar(); */
main()
{
system("cls");
abrir();
//menu();
}
void abrir() //open the csv file and copy it to
{
/* FileStream for the Library File */
FILE *pFile;
/* allocation of the buffer for every line in the File */
char *buf = malloc(MAX_STR_LEN);
char *tmp;
/* if the space could not be allocated, return an error */
if (buf == NULL) {
printf ("No memory\n");
}
if ( ( pFile = fopen( "control.csv", "r" ) ) == NULL ) //Reading a file
{
printf( "File could not be opened.\n" );
}
int i = 0;
while (fgets(buf, 255, pFile) != NULL)
{
if ((strlen(buf)>0) && (buf[strlen (buf) - 1] == '\n')) //checa leitura
buf[strlen (buf) - 1] = '\0';
tmp = strtok(buf, ";");
cliente[i].id = atoi(tmp); //atoi for int
tmp = strtok(NULL, ";"); //use strcpy for char
strcpy(cliente[i].nome,tmp);
tmp = strtok(NULL, ";");
strcpy(cliente[i].endereco, tmp);
tmp = strtok(NULL, ";");
strcpy(cliente[i].cidade, tmp);
tmp = strtok(NULL, ";");
strcpy(cliente[i].pais, tmp);
tmp = strtok(NULL, ";");
strcpy(cliente[i].cep, tmp);
tmp = strtok(NULL, ";");
strcpy(cliente[i].nasc, tmp);
tmp = strtok(NULL, ";");
strcpy(cliente[i].telefone, tmp);
tmp = strtok(NULL, ";");
strcpy(cliente[i].total, tmp);
//tempBook.ID = atoi(buf); fix below
printf("%i, %s, %s, %s, %s, %s, %s, %s, %s \n",i, cliente[i].id , cliente[i].nome, cliente[i].endereco, cliente[i].cidade, cliente[i].pais, cliente[i].cep, cliente[i].nasc, cliente[i].telefone, cliente[i].total);
i++;
}
//free(buf);
fclose(pFile);
}
How can I solve this problem? I can't successfully copy the data from 100 clients in the csv to a structure.
Thank you since now!
There are three main problems here:
The format string in printf("%i, %s, %s, %s, ...) doesn't match the parameters, you need one more %i: printf("%i, %i, %s, %s, %s, ...).
In your code you never call abrir() but you call menu(), which doesn't exist, therefore your code doesn't even compile.
If you are on Windows (and only then) you need fopen(..., "rt")) instead of fopen(..., "r"))
Furthermore (not causing actual problems in your code):
char *buf = malloc(MAX_STR_LEN); can be replaced by char buf[MAX_STR_LEN];. It's pointless to allocate memory dynamically if the amount of memory is known at compile time. In that case you must of course not call free(buf) (which is commented out anyway).
Following declarations just after struct estrutura cliente[200]; are useless, you can remove them.
FILE *pFile;
//allocate buffer in each line
char *buf = (char*)malloc(MAX_STR_LEN);
char *tmp;
Otherwise the program should work fine unless your input file has fields that are larger than the field in your struct estrutura.

Resources