How to retrieve array from void function and pass to other functions in Main?

I am a beginner in C

I have a problem in which I am passing an array of grades to main and will need to convert those grades to ints and find the min max and avg of them.

The specifications are

  • void getGrade(int argc, char *argv[])
  • int findMaximum(grade[])
  • int findMinimum(grade[])
  • float calculateAverage(grade[])
  • printResults(max, min, avg)

and these must all be called in order in the main function.

I am trying to figure out how to access the array "grade" manipulated in getGrade, to be able to pass it to the other functions in main.

int main(int argc, char *argv[]){
    getGrade(argc, argv)
    int max = findMaximum(grade);
    int min = findMinimum(grade);
    float avg = calculateAverage(grade);
    print results(max, min, avg);
    return 0;
}

void getGrade(int argc, char *argv[]){
    int i;
    int grade[argc - 1];
    for(i=0, i<argc -1; i++){
        grade[i] = atoi(*(argv + i + 1));
    }
}

3 answers

  • answered 2018-02-13 01:30 P0W

    The array grade can't be accessed outside of that function because it is local variable inside getGrade function.

    You'll have to first fill the grade array and then pass it to other functions. I don't recommend make it global variable.

    int main(int argc, char *argv[]){
        // Allocate memory for grade.
    
        int* grade = malloc( (argc -1 )* sizeof(int) );
    
        // Pass additional parameter, for number of items in grade array.
    
        getGrade(grade , argc -1, argv );
        int max = findMaximum(grade, argc -1 );
        int min = findMinimum(grade, argc -1 );
        float avg = calculateAverage(grade, argc -1 );
        /*print*/ results(max, min, avg);
    
        free(grade); // Release the memory
    
        return 0;
    }
    

  • answered 2018-02-13 01:30 Pablo

    The grade array is a local variable in getGrade, so when the function exits, the variable and their contents are lost.

    You have to create the array prior of the calls of this functions and pass the array and its length to the function. You will need to modify the functions to accept the length as well:

    void getGrade(grade, size_t len, char **argv);
    int findMaximum(int *grade, size_t len);
    int findMinimum(int *grade, size_t len);
    float calculateAverage(int *grade, size_t len);
    printResults(max, min, avg);
    
    
    void getGrade(grade, size_t len, char **argv)
    {
        for(size_t i = 0, i < len; i++)
            grade[i] = atoi(argv[i+1]);
    }
    
    int main(int argc, char **argv)
    {
        int grades[argc - 1];
        size_t len = argc - 1;
    
        getGrade(grades, len, argv);
    
        int max = findMaximum(grades, len);
        int min = findMinimum(grades, len);
        float avg = calculateAverage(grades, len);
        print results(max, min, avg);
    
        return 0;
    }
    

  • answered 2018-02-13 01:30 Luis Colorado

    You have several alternatives:

    • Make the array static. The array grade has been declared automatic variable (that only exists during its scope delimiters, which are the function body. But if you make it static it extends its life to all the program life (its a global variable, despite the fact that its name can be used only inside the function body). Then return a pointer to it.

      int *getGrade(int argc, char *argv[]){
          int i;
          static int grade[argc - 1];
          for(i=0; i<argc -1; i++){
              grade[i] = atoi(*(argv + i + 1));
          }
          return grade;
      }
      

      This has the inconvenient of not being reentrant, so you cannot have several threads making use of the function at the same time, as it has global data. Also, you cannot call the function until you have completely used the value from the last call, as there is only one array grade.

    • Allocate an array with malloc(3) and return it's pointer. Later, when you don't need the pointer anymore, you can free(3) it, so its memory is returned to the system.

      int *getGrade(int argc, char *argv[]){
          int i;
          int *grade = malloc((argc - 1) * sizeof *grade);
          for(i=0; i<argc -1; i++){
              grade[i] = atoi(*(argv + i + 1));
          }
          return grade;
      }
      

      The inconvenient is that you don't know (a priory) the number of allocated elements, so you have to provide it somehow. (In this case, you allocate argc - 1 elements, so you know the array size. Reentrancy: The reentrancy of this function depends on the reentrancy of the malloc(3) function. Nowadays, almost all implementations of malloc(3) can be used in different threads.

    • Pass it from the calling routine. This way you can decide, at each function call, the actual array, array size, and other aspects.

      int *getGrade(int argc, char *argv[], int *passed_grade, int size)
      {
          int i;
          for(i=0; i<argc - 1; i++){
              passed_grade[i] = atoi(*(argv + i + 1)); /* <== I don't understand why you don't write argv[i + 1] instead of this unreadable thing (APART THAT IT'S INCORRECT) */
          }
          return passed_grade;  /* returning it makes it possible to use this function in an expression. */
      }
      
      ...
      
      /* then, in main() */
      #define N (argc - 1)
      
      int grade[N];
      int min = findMinimum(getGrade(argc, argv, grade, N), N);
      int max = findMaximum(grade, N); /* grade has already been initialized in last line */
      

      The inconvenient in this approach is to carry two more parameters than previously, but it allows to use different array sizes and. Reentrancy: This function reentrancy depends on the passed array not being global.

    In my humble opinion, the third approach is the best, as it doesn't depend normally on the possible blocking of the malloc(3) routine (malloc can be blocked if used by several threads in some implementations), and doesn't depend on a static global data (making it not reentrant).

    NOTES

    • your posted code has several compilation errors (mainly syntax: a semicolon is missing between the two first expresions in the for loop; and a problem with the index used to access the argv array)

    • The last point, makes it impossible to compile and test your sample code without first converting it to a compilable example. DON'T DO THAT!!! Post a complete, testable and verifiable example, as we cannot guess what are simple typos or what is a concept error in your side. See this for more info.