Home > Software engineering >  How to pass an array of files as an argument
How to pass an array of files as an argument

Time:09-15

I am struggling to pass an array of files as an argument to pthread_create function.

FILE *arqvs[arq];
  for(int i=1, count=0;i<=arq;i  , count  ){
    changeName(file, i); //change the name of the file based on the index
    arqvs[count] = fopen(file, "r");
    
    if(arqvs[count]==NULL){
      printf("Erroro:(\n");
      exit(1);
    }
  }

The code above shows how I am creating the array and opening the files in "r" mode. I have done some tests and it seems to work well. Is reads all the files based on the number of the variable arq. The problem comes out when I try to pass the array to the function pthread_create as mentioned above..

Here's the code:

for(int i=0;i<trd; i  ){
    pthread_create(&thread[i], NULL, funcao, &**arqvs);
  }

And here's the function:

void * funcao(void * args){
  char voto[2];
  FILE *** fileName = (FILE***) args;
  while (fgets(voto, sizeof(voto), *fileName[0])) {
  printf("%s", voto); 
  pthread_exit(NULL);
}

This code does not work, and I dont know why. It has been awhile since I programmed in C, so, I would appreciate any hints or answers.

CodePudding user response:

In C, arrays are usually passed to functions/threads by passing a pointer to the first element of the array. If the length is unknown to the called function/thread, then an additional parameter is often passed which specifies the number of elements in the array.

If the number of elements in the array (which is the value of arq) is known to both threads, then you only need to pass a pointer to the first element of the array. Otherwise, you will also have to pass the number of elements in the array to pthread_create, for example by instead passing a pointer to a struct which also contains this information.

Assuming that the number of elements in the array does not have to be passed, you should change the line

pthread_create(&thread[i], NULL, funcao, &**arqvs);

to

pthread_create(&thread[i], NULL, funcao, arqvs);

which is equivalent to:

pthread_create(&thread[i], NULL, funcao, &arqvs[0]);

This is because the array arqvs automatically decays to a pointer to the first element of the array when used in this context.

Since the array's element type is FILE * and a pointer to the first element of the array has been passed to the function funcao, this means that the type of the passed pointer is FILE **. Therefore, you should change the line

FILE ** fileName = (FILE**) args;

to:

FILE ** fileName = (FILE**) args;

Also, fileName does not seem like an appropriate name for this pointer. A better name would be something like files or streams.

CodePudding user response:

The value (&**argvs) you're passing in to pthread_create is a FILE *. But then in funcao, you are casting it to a FILE *** which is not the same, so everything breaks (undefined behavior).

You need to make sure the value you pass in and the value you cast the void * to are the same type. In your case, it probably makes the most sense to use FILE **. So you can call pthread_create as:

pthread_create(&thread[i], NULL, funcao, arqvs);

and in funcao, use it as:

FILE ** files = (FILE**) args;

Note that arq (the size of the array) is lost when you convert the array to a pointer, so you have no good way of knowing how many FILE *s there are in funcao. It may make more sense to create a struct that holds both the (pointer to the) array and the array size, and pass a pointer to that to the thread function.

CodePudding user response:

Just pass the array directly, there's no need to use &. Arrays automatically decay to a pointer when used as function arguments.

for(int i=0;i<trd; i  ){
    pthread_create(&thread[i], NULL, funcao, arqvs);
}
void * funcao(void * args){
  char voto[2];
  FILE **fileName = args;
  while (fgets(voto, sizeof(voto), fileName[0])) {
    printf("%s", voto); 
  }
  pthread_exit(NULL);
}
  • Related