my_funcs.c:

int x = 0;

FILE *stockIngredientes = fopen( "C:/Dropbox/Work/ISEC/P/ingredientes.txt", "r+" );

while( fgets( tmp, 100, stockIngredientes ) != NULL ){
    ingredientes[x].nome = strtok( tmp, ":" );
    ingredientes[x].identificadorNum = strtok( NULL, ":" );
    ingredientes[x].quantStock = strtok( NULL, ":" );
    ingredientes[x].limMin = strtok( NULL, ":" );
    ingredientes[x].consumoMed = strtok( NULL, ":" );

    x++;
}
printf("%s", ingredientes[0].nome);
printf("%s", ingredientes[4].nome);

Hey guys, my problem is as follows:

Looking at this piece of code im declaring a counter called x initialized as 0, followed by opening a file for read and write, I read all the lines of the file and in each line I use strtok to split the line into the data I need and assign it to my variables inside of a structure vector.

Now the problem comes, if I printf for example "ingredientes[x].nome" inside the while the values are all different, but outside the while all the elements of the vector become the same as the last element of the vector... I would like to know why this happens, I'm really confused.

printf("%s", ingredientes[0].nome);
printf("%s", ingredientes[4].nome);

Both these lines print the same name.. when clearly they shouldn't.

See if this helps, look at the comments.

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

//#######################################
// This must be what your structure
// looks like
struct {
    char *nome;
    char *identificadorNum;
    char *quantStock;
    char *limMin;
    char *consumoMed;
} ingredientes[4];    

//#######################################
// This is what it should look like
struct {
    char nome[10];
    char identificadorNum[10];
    char quantStock[10];
    char limMin[10];
    char consumoMed[10];
} ShouldBe[4];

int main(){
  int i,x = 0;
  char tmp[100];
  //#####################################
  // This will act like you input file
  char *data[4] = {"name1:1111:8:3:44",
                   "name2:2222:8:3:44",
                   "name3:3333:8:3:44",
                   "name4:4444:8:3:44"};

  //##################################################
  // Here I will loop thru the array
  for ( i=0;i<4;i++){
    //################################################
    // Copy the data into the tmp array
    strcpy(tmp,data[i]);

    //################################################
    // Here you are just copying the value of the
    // pointer and not what it is pointing to
    ingredientes[x].nome = strtok( tmp, ":" );
    ingredientes[x].identificadorNum = strtok( NULL, ":" );
    ingredientes[x].quantStock = strtok( NULL, ":" );
    ingredientes[x].limMin = strtok( NULL, ":" );
    ingredientes[x].consumoMed = strtok( NULL, ":" );
    x++;
  }
  //##################################################
  // Here is the wrong answer
  // nome is the first feild and above all nome point
  // to the first peice of memory of tmp
  printf("Wrong:  %s\n", ingredientes[0].nome);
  printf("Wrong:  %s\n", ingredientes[3].nome);

  x = 0;
  //#################################################
  // Here I will loop thru the array
  for ( i=0;i<4;i++){
    //###############################################
    // Copy the data into the tmp array
    strcpy(tmp,data[i]);

    //###############################################
    // You need to copy the values not just the 
    // pointer values.
    // You would want to do more error checking.
    strcpy(ShouldBe[x].nome,strtok( tmp, ":" ));
    strcpy(ShouldBe[x].identificadorNum,strtok( NULL, ":" ));
    strcpy(ShouldBe[x].quantStock,strtok( NULL, ":" ));
    strcpy(ShouldBe[x].limMin,strtok( NULL, ":" ));
    strcpy(ShouldBe[x].consumoMed,strtok( NULL, ":" ));
    x++;
  }
  //#####################################
  // Here is the right answer
  printf("Right:  %s\n", ShouldBe[0].nome);
  printf("Right:  %s\n", ShouldBe[3].nome);

  return 0;
}

Output

$ ./a.out
Wrong:  name4
Wrong:  name4
Right:  name1
Right:  name4
$

Edited 4 Years Ago by histrungalot: Fix

Hey thanks for your answer, I happened to fix my code by adding strdup() like this:

ingredientes[x].nome = strdup( strtok( tmp, ":" ) );

By doing so I believe I duplicated the value that is being pointed by strtok and not the memory address.

EDIT: I changed to the way you showed, I believe the aproach is much more correct. Case Solved.

Edited 4 Years Ago by mcjiwe

This question has already been answered. Start a new discussion instead.