hello
i have the following file:
11
Lockers, Daniel;Engineer;53500
Adamson, John;Manager;77500
Newhall, Bob;Programmer;40000
Brown, James;Clerk;28000

i need to put each employee into a struct and then each struct into an array.
so far i did this:

else
    {   

       fscanf(sourcefile,"%d\n",&count);
       printf("%d\n",count);
       Array=(employeeType *)malloc(sizeof(employeeType)*count);


       for(i=0;i<count;i++)
          {
          fscanf(sourcefile,"%s",Array[i].name);
          fscanf(sourcefile,"%s",Array[i].job);
          fscanf(sourcefile,"%d",&Array[i].salary);
          }

        }

     for(i=0;i<count;i++) 
     printf("The name of employee %d is %s his job is %s and his slary is %d\n", i+1, Array[i].name,Array[i].job,Array[i].salary);


free(Array);

this works only if the name, job and salary of the employees are separated by space.
can anyone tell me how i can read the stings when they are separated by ";" as the example?
thnks

Last name and first name are separated by a space, so fscanf() won't [easily] work with it. It's a lot simplier to just call fgets() to read the entire line at one time, then use strtok() to split it by ';'

I'd suggest reading each line with fgets() and then parsing it in memory to extract fields. You can do the parsing with sscanf(), though it can get a little tricky unless you guarantee that the file ends with a newline character, because you need to consider fields that end in all three of ';', '\n', and EOF:

#include <stdio.h>
#include <string.h>

int main(void)
{
    FILE *in = fopen("test.txt", "r");

    if (in) {
        char line[BUFSIZ];

        while (fgets(line, sizeof line, in)) {
            size_t pos = 0, n;
            char field[80];

            /* Trim the newline as it tends to cause trouble */
            line[strcspn(line, "\n")] = '\0';

            while (sscanf(line + pos, "%79[^;]%n", field, &n) == 1) {
                puts(field);
                pos += n;

                if (line[pos] == ';')
                    ++pos;
            }
        }

        fclose(in);
    }

    return 0;
}

If the file is guaranteed to end with a newline, the EOF case goes away and things become drastically simpler as you can do all of the work for the other two cases in the sscanf() format string:

#include <stdio.h>
#include <string.h>

int main(void)
{
    FILE *in = fopen("test.txt", "r");

    if (in) {
        char line[BUFSIZ];

        while (fgets(line, sizeof line, in)) {
            size_t pos = 0, n;
            char field[80];

            while (sscanf(line + pos, "%79[^;\n]%*[;\n]%n", field, &n) == 1) {
                puts(field);
                pos += n;
            }
        }

        fclose(in);
    }

    return 0;
}

i have tried with fgets() to read the entire line at one time, and then strtok() to split the line, but because i have to put each employee in a struct, it throws me an error.
can anyone help me?
here is the code:

j=1;

else
        {   

           fscanf(sourcefile,"%d\n",&count);
           printf("%d\n",count);
           Array=(employeeType *)malloc(sizeof(employeeType)*count);
           while( fgets(line,sizeof(line),sourcefile))
                  {
                  if (j==1)
                     {
                     Array[i].name= strtok(line,";");
                     j++;
                     }
                  if (j==2)
                     {
                     Array[i].job = strtok(line,";");
                     j++;
                     }
                  if (j==3)
                     {
                     Array[i].salary = strtok(line,";");
                     j=j-2;
                     }
                  while (nextWordPtr != NULL) 
                        {
                        if (j==1)
                           {
                           Array[i].name = strtok(line,";");
                           j++;
                           }
                        if (j==2)
                           {
                           Array[i].job = strtok(line,";");
                           j++;
                           }
                        if (j==3)
                           {
                           Array[i].salary = strtok(line,";");
                           j=j-2;
                           }
                        i++;
                        }
                  }
             }

        for(i=0;i<count;i++) 
        printf("The name of employee %d is %s his job is %s and his slary is %d\n", i+1, Array[i].name,Array[i].job,Array[i].salary);


    free(Array);

thnks

strtok() returns a pointer to the same array you're tokenizing, so the instant you read another line you'll have corrupted all previously stored records. Presumably your structure members are pointers, so you can write your own strdup() to make a copy of the token:

/*
    @description:
        Copies the string pointed to by s into a dynamically allocated array.
*/
char *dupstr(const char *s)
{
    char *mem = (char*)malloc(strlen(s) + 1);

    if (mem)
        strcpy(mem, s);

    return mem;
}

Then each token would be saved like so:

Array[i].name = dupstr(strtok(line,";"));

Just be sure to free the memory for each field when you're done with it:

for (i = 0; i < count; ++i) {
    free(Array[i].name);
    free(Array[i].job;
    ...
}

free(Array);

Edited 3 Years Ago by deceptikon

Hello,
I have try with dupstr() and it keeps throws me the same error with before.

temp = strtok(NULL,";");
Array[i].name= temp;



temp = dupstr(strtok(NULL,";"));
Array[i].name= temp;

these two cases throws me the same error : incompatible types in assignment

this is the code i use:

while( fgets(line,sizeof(line),sourcefile))
                  {
                  temp = strtok(line,";");
                  while (temp != NULL) 
                        {
                        if (j==1)
                           {
                           temp = dupstr(strtok(NULL,";"));
                           Array[i].name= temp;
                           j++;
                           }
                        if (j==2)
                           {
                           temp = strtok(NULL,";");
                           Array[i].job= temp;
                           j++;
                           }
                        if (j==3)
                           {
                           Array[i].salary = temp;
                           temp = strtok(NULL,";");
                           j=j-2;
                           }
                        i++;
                        }
                  }

any help appreciated

Your program is just tooo complicated. This is all you need.

int i = 0;
while( fgets(line,sizeof(line),sourcefile))
{
     Array[i].name= dupstr(strtok(line,";"));
     Array[i].job= dupstr(strtok(NULL,";"));
     Array[i].salary = dupstr(strtok(NULL,";"));
     ++i;
}

Edited 3 Years Ago by Ancient Dragon

only the Array is pointer.

typedef struct employee {
   char name[100];
   char job[100];
   int salary;

}employeeType;;


employeeType *Array=NULL;

Just as I suspected. You can't use = to assign a string, you must copy it. Note you don't need dupstr() function. Since salary is an int you need to convert from char* to int.

int i = 0;
while( fgets(line,sizeof(line),sourcefile))
{
     strcpy(Array[i].name, strtok(line,";"));
     strcpy(Array[i].job, strtok(NULL,";"));
     Array[i].salary = atoi(strtok(NULL,";"));
     ++i;
}

Edited 3 Years Ago by Ancient Dragon

This article has been dead for over six months. Start a new discussion instead.