DFT95
DFT95

Reputation: 27

too few arguments while calling functions (c)

I'm still ridiculously new to this, but I think I've got this code coming along nicely. This program sizes up some hardcoded-in grades and converts them to letter form according to my classes syllabus. In the gradePrint function, the strcopy_s functions all give the "too few arguments while calling functions" error.

Here is the code:

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

int grade(name,attendance, assignments, programs, quizzes, exam) // this takes the int values from the main function
{
    int attendancePercent, assignmentsPercent, programsPercent, quizzesPercent, examPercent; // makes the percentage values
    int finalGrade;

    attendancePercent = attendance * 5 / 100;
    assignmentsPercent = assignments * 20 / 100;
    programsPercent = programs * 30 / 100;
    quizzesPercent = quizzes * 25 / 100;
    examPercent = exam * 20 / 100;
    finalGrade = (attendancePercent + assignmentsPercent + programsPercent + quizzesPercent + examPercent +2);
    finalGrade = gradePrint(name, finalGrade); // this sends the finalGrade and the name over to gradePrint

}





int gradePrint(name, finalGrade) {

    char letter[100];


    if (finalGrade > 105 || finalGrade < 0) { printf("%d is not a valid grade.\n", finalGrade); }
    if (finalGrade <= 105 && finalGrade >= 97) { strcpy_s(letter, "A+"); }
    if (finalGrade <= 96 && finalGrade >= 94) { strcpy_s(letter, "A"); }
    if (finalGrade <= 93 && finalGrade >= 90) { strcpy_s(letter, "A-"); }
    if (finalGrade <= 89 && finalGrade >= 87) { strcpy_s(letter, "B+"); }
    if (finalGrade <= 86 && finalGrade >= 84) { strcpy_s(letter, "B"); }
    if (finalGrade <= 83 && finalGrade >= 80) { strcpy_s(letter, "B-"); }
    if (finalGrade <= 79 && finalGrade >= 77) { strcpy_s(letter, "C+"); }
    if (finalGrade <= 76 && finalGrade >= 74) { strcpy_s(letter, "C"); }
    if (finalGrade <= 73 && finalGrade >= 70) { strcpy_s(letter, "C-"); }
    if (finalGrade <= 69 && finalGrade >= 60) { strcpy_s(letter, "D"); }
    if (finalGrade < 60) { strcpy_s(letter, "F"); }


    printf("%s\t", name);
    printf("Grade: %d\n", finalGrade);

}




int main() // individual values are put into main function
{

    char personOne, personTwo,personThree,personFour,personFive,personSix,personSeven,personEight,personNine;
    char name;



    personOne = grade("Adams, Tom",95, 93, 95, 99, 94); //each person all the way down recalls the grade function
    personTwo = grade("Curry, Jane",95, 85, 88, 87, 89);
    personThree = grade("Franklin, John",70, 50, 65, 50, 57);
    personFour = grade("George, Pat",85, 87, 81, 82, 88);
    personFive = grade("Keene, Mary",85, 72, 75, 68, 75);
    personSix = grade("Kraft, Martin",80, 85, 80, 88, 93);
    personSeven = grade("Martin, James",75, 65, 65, 52, 55);
    personEight = grade("Oakley, Ann",95, 85, 95, 88, 92);
    personNine = grade("Smith, Luke",95, 85, 75, 81, 75);
    system("pause");

}

I've spent all afternoon trying to fix this, looking at other questions on here etc. And the answer is probably staring me in the face, but I just can't see it. Can anyone help? Any advice is appreciated, thanks in advance

Upvotes: 0

Views: 607

Answers (1)

Ahmed Masud
Ahmed Masud

Reputation: 22374

Some thoughts before we begin

(This preamble is my opinionated.)

While older standards of C allow int to be the default type in situations where you don't explicitly declare a type (e.g. return values of functions; parameters to a function etc.) we always want to avoid this practice, as it may lead to incorrect assumptions by the C language compiler about the nature of a variable and thus lead to unexpected results. While C is probably the most powerful of all languages it's also very unforgiving and you have to tell it everything you mean for it to do. It assumes that you know what you're doing. So the best way to avoid mistakes is to be explicit and create small meaningful chunks of code and weave them together.


Actual Answer

Let's think about how you want to proceed.

First let's divide the issue up into two simple sub problems:

  1. We want to get the corresponding letters for a given grade.

  2. We need to figure out the weighted final grade for each person given their grades for each category.

Side Note: Here's the way you want to think about creating (or choosing not to create a function): Note, that I suggested we create functions for specific "change" but I on purpose avoided a function to do procedural stuff (e.g. print things out.)

STEP 1 – Overall structure

First let's create our overall program that has the structure we want with empty functions (they don't do anything useful but we expect to have that done next)

#include <stdio.h>

int calc_final_grade(
      int attendance, 
      int assignments, 
      int programs, 
      int quizzes,
      int exam);

const char *grade_to_letters(int grade);

int main()
{

      printf("Name: %s, Grade: %s\n", "Tom, Adams", 
           grade_to_letters(calc_final_grade(95, 93, 95, 99, 94)));

      return 0; /* successfully finished */
}

int calc_final_grade(
           int attendance, 
           int assignments, 
           int programs, 
           int quizzes,
           int exam) 
{
       /* TODO calculate something */
       return 100; /* just return a value for now */
}


const char *grade_to_letters(int grade) 
{
     const char result[] = "A+";

     /* TODO: actually do the conversion of grade to letters */

     /* FIXME: trouble with `return result` is we are returning a
      * memory address value (where "A+" is stored, but it's local to 
      * this function) so by the time our main function tries to 
      * _read_ the value at this memory address to print it,
      * the function context has been lost and its 
      * contents would've disappeared from under us */

     return result; 

}

The program above is good enough for us to build things out, except let's fix the memory problem in grade_to_letters.

We need a place to save the grade, but because what we want to save is a string (not a basic C type) we cannot just return it by value, we have to store it somewhere and return the address of where we stored it. Also, the place where we store it has to be valid within the context or scope of the part of the program that is trying to use it.

So we create a spot for the grade letter we are working in the scope of the function we want to use it in (in our case we are printing it in main) and pass the address of this spot along to the grade_to_letters function to actually use as storage of its result.

Which means, first grade_to_letters has to accept an address of store stuff at — let's make that happen:

So we change the definition of grade_to_letters to accept a location for results, in our case we want it to be enough for three characters (letter, a modifier, and the string terminating \0 character):

const char *grade_to_letters(
    char result[3], /* a place to store the results */
    ...); /* see below */

Note that now we don't have to declare a local variable for result, we already have a spot (although notice that we can still return the result!);

We can also notice that our grades can never be negative so we make them unsigned integers. So our prototype becomes:

const char *grade_to_letters(char result[3], unsigned int grade) 

Step 2 — Implement grade_to_letters

Now we can go ahead and create a simple grade_to_letters:

const char *grade_to_letters(char result[3], unsigned int grade) 
{
      /* set result to an error string XX */
      result[0] = result[1] = '?'; result[2] = 0;

      if (grade > 100) 
             return result; /* error string ?? */


      result[1] = '\0'; /* for simple grades this is `\0` */

      result[0] = 'F';                 /* everyone fails */
      if(grade >= 60) result[0] = 'D'; /* or gets a D */
      if(grade >= 70) result[0] = 'C';
      if(grade >= 80) result[0] = 'B'; 
      if(grade >= 90) result[0] = 'A';

      /* TODO: figure out a way to do +/- and store it at result[1] */

      return result; 
}

Testing grade_to_letters

#include <stdio.h>

int calc_final_grade(
      int attendance,
      int assignments,
      int programs,
      int quizzes,
      int exam);

const char *grade_to_letters(char result[3], unsigned int grade);

/* We change the main function to test the grade_to_letters 
 * scenarios
 */

int main()
{
      char result[3]; /* storage for letters */

     /* printf("Name: %s, Grade: %s\n", "Tom, Adams",
           grade_to_letters(result, calc_final_grade(95, 93, 95, 99, 94))); */

      /* test out different scenarios */
      printf("%3d: %2s\n", 100, grade_to_letters(result, 100));
      printf("%3d: %2s\n",  98, grade_to_letters(result,  98));
      printf("%3d: %2s\n",  94, grade_to_letters(result,  94));
      printf("%3d: %2s\n",  90, grade_to_letters(result,  90));
      printf("%3d: %2s\n",  88, grade_to_letters(result,  88));
      printf("%3d: %2s\n",  83, grade_to_letters(result,  83));
      printf("%3d: %2s\n",  77, grade_to_letters(result,  77));
      printf("%3d: %2s\n",  75, grade_to_letters(result,  75));
      printf("%3d: %2s\n",  71, grade_to_letters(result,  71));
      printf("%3d: %2s\n",  65, grade_to_letters(result,  65));
      printf("%3d: %2s\n",  55, grade_to_letters(result,  55));

      /* check boundaries (we should get ?? as a result) */
      printf("%3d: %2s\n", 105, grade_to_letters(result, 105));
      printf("%3d: %2s\n", -38, grade_to_letters(result, -38));

      return 0; /* successfully finished */
}

int calc_final_grade(
           int attendance,
           int assignments,
           int programs,
           int quizzes,
           int exam)
{
       /* TODO calculate something */
       return 100; /* just return a value for now */
}


const char *grade_to_letters(char result[3], unsigned int grade)
{
      /* set result to an error string '??' */

      result[0] = result[1] = '?'; 
      result[2] = 0; /* always terminate the string */

      if (grade > 100)
             return result;


      result[1] = 0; /* for simple grades this is also `\0` */

      result[0] = 'F';                 /* everyone fails */
      if(grade >= 60) result[0] = 'D'; /* or gets a D */
      if(grade >= 70) result[0] = 'C';
      if(grade >= 80) result[0] = 'B';
      if(grade >= 90) result[0] = 'A';

      /* TODO: figure out a way to do +/- and store it at result[1] */

      return result;
}

Adding support for +/-

Notice that the + or - only gets added when units part of the score is in [7,9] or [0,3] intervals respectively. So first we have to get the units part. Well that's easy if we get the remainder of the grade after dividing by 10 (e.g. 87/10 = 8 R 7) and we want the remainder 7 here; we can figure out + or -.

The remainder function in C is % operator; so look at this snippet:

  /* returns '+' / '-' or 0 depending on how high the grade's units
     value is */

  char plus_minus(unsigned int grade) 
  {
     unsigned int remainder = grade % 10; /* get the remainder */

     if (remainder >= 7) 
           return '+'; /* 7,8,9 */

     if (remainder <= 3) 
           return '-'; /* 0,1,2,3 */

     return 0; /* return `\0` char for 4,5,6 */
  }

Let's add this to our grade_to_letters function:

const char *grade_to_letters(char result[3], unsigned int grade)
{
      /* set result to an error string ?? */
      result[0] = result[1] = '?';
      result[2] = 0; /* string terminator */

      if (grade > 100)
             return result;


      result[1] = 0;
      result[0] = 'F';                 /* everyone fails */

      if(grade >= 60) result[0] = 'D'; /* or gets a D */

      if(grade >= 70) {  /* everyone above 70 */
        result[0] = 'C'; /* gets at least a C */
        result[1] = plus_minus(grade); /* and a possibly a plus or minus */
      }

      if(grade >= 80) result[0] = 'B';
      if(grade >= 90) result[0] = 'A';

      if(grade >= 100) 
            result[1] = '+'; /* edge case for 100% */

      return result;
}

IMPORTANT NOTES:

  1. Notice that we only put the plus_minus in the if(grade >= 70) which is where it belongs! We only have to do it there! It's going to work for all grade levels C, B, and A because the B and A are subsets of (grade>=70)

  2. When you run the program for value of grade=100 you won't get A+! that's because 10 divides 100 perfectly, so there's an edge case:

        if(grade >= 100) 
            result[1] = '+'; /* edge case for 100% */
    

We'll add this at the end and test the whole thing.

Here's the program so far:

#include <stdio.h>

int calc_final_grade(int attendance,
             int assignments, int programs, int quizzes, int exam);

const char *grade_to_letters(char result[3], unsigned int grade);
char plus_minus(unsigned int grade);

int main()
{
    char result[3];     /* storage */

    /* printf("Name: %s, Grade: %s\n", "Tom, Adams",
       grade_to_letters(result, calc_final_grade(95, 93, 95, 99, 94))); */

    printf("%3d: %2s\n", 100, grade_to_letters(result, 100));
    printf("%3d: %2s\n", 98, grade_to_letters(result, 98));
    printf("%3d: %2s\n", 94, grade_to_letters(result, 94));
    printf("%3d: %2s\n", 90, grade_to_letters(result, 90));
    printf("%3d: %2s\n", 88, grade_to_letters(result, 88));
    printf("%3d: %2s\n", 83, grade_to_letters(result, 83));
    printf("%3d: %2s\n", 77, grade_to_letters(result, 77));
    printf("%3d: %2s\n", 75, grade_to_letters(result, 75));
    printf("%3d: %2s\n", 71, grade_to_letters(result, 71));
    printf("%3d: %2s\n", 65, grade_to_letters(result, 65));
    printf("%3d: %2s\n", 55, grade_to_letters(result, 55));

    printf("%3d: %2s\n", 155, grade_to_letters(result, 155));
    printf("%3d: %2s\n", -38, grade_to_letters(result, -38));

    return 0;       /* successfully finished */
}

int
calc_final_grade(int attendance,
         int assignments, int programs, int quizzes, int exam)
{
    /* TODO calculate something */
    return 100;     /* just return a value for now */
}

const char *grade_to_letters(char result[3], unsigned int grade)
{
    /* set result to an error string XX */
    result[0] = result[1] = 'X';
    result[2] = 0;      /* always NUL terminate */

    if (grade > 100)
        return result;

    result[1] = 0;
    result[0] = 'F';    /* everyone fails */

    if (grade >= 60)
        result[0] = 'D';    /* or gets a D */

    if (grade >= 70) {
        result[1] = plus_minus(grade);
        result[0] = 'C';
    }

    if (grade >= 80)
        result[0] = 'B';
    if (grade >= 90)
        result[0] = 'A';
    if (grade >= 100)
        result[1] = '+';    /* edge case for 100% */

    /* TODO: figure out a way to do +/- and store it at result[1] */

    return result;
}

char plus_minus(unsigned int grade)
{
    unsigned int remainder = grade % 10;    /* get the remainder */

    if (remainder >= 7)
        return '+'; /* 7,8,9 */

    if (remainder <= 3)
        return '-'; /* 0,1,2,3 */

    return 0;       /* return `\0` char for 4,5,6 */
}


Step 3 — Calculate final grade:

Let's fix the main function and test out the final grades calculations for a single student. Our function is:

int calc_final_grade(int attendance,
             int assignments, int programs, int quizzes, int exam)
{
     return ( 5 * attendance 
           + 20 * assignments
           + 30 * programs
           + 25 * quizzes
           + 20 * exam) / 100;
}

Adding the values first and then dividing the result by a 100 gives us a better integer value at the end (it may be worthwhile to use the remainder function here for rounding up; or not)

Testing the grading function:

We can change the main to test out our grading function:

int main()
{
    char result[3];     /* storage */
    int grade;

    grade = calc_final_grade(100, 0, 0, 0, 0);
    printf("Name: %s, Grade: %s (%d)\n", "Attender", grade_to_letters(result, grade), grade);

    grade = calc_final_grade(0, 100, 0, 0, 0);
    printf("Name: %s, Grade: %s (%d)\n", "Homer worker", grade_to_letters(result, grade), grade);

    grade = calc_final_grade(0, 0, 100, 0, 0);
    printf("Name: %s, Grade: %s (%d)\n", "Programmer", grade_to_letters(result, grade), grade);

    grade = calc_final_grade(0, 0, 0, 100, 0);
    printf("Name: %s, Grade: %s (%d)\n", "Mr. Tester", grade_to_letters(result, grade), grade);

    grade = calc_final_grade(0, 0, 0, 0, 100);
    printf("Name: %s, Grade: %s (%d)\n", "Exam Wizard", grade_to_letters(result, grade), grade);

    return 0;       /* successfully finished */
}

Step-5 Putting it all together

Putting this together is left as an exercise for the reader

Final thoughts

Hopefully this gives you an insight into how to break down problems like this and start thinking about them.

Upvotes: 2

Related Questions