Search code examples
cvariable-assignmentvoidabstract-data-typechar-pointer

C: String Variable Loses Value After Returning From Void Function


hope you are well.

I recently started learning ADT (Abstract Data Type) in college, and I have an assignment that states the following:

Complete ADTDate adding the following primitive function:

void dayWeekStr(DatePtr date,char *buffer)// places the day of the week of the date in buffer

So in main() you define a char pointer, and send it to the function alongside the date struct. Basically what the function does is, it calls a getter to obtain the Gregorian Day in form of a number (I'm storing the dates in Julian Days); this is, from 0 (sunday) to 6 (saturday), and from that I have a switch that assigns each day in form of a string ("Tuesday") to buffer. It looks like this:

void dayWeekStr(DatePtr date,char *buffer)
{
    switch (dayWeek(date))
    {
        case 0:
            buffer="Sunday";
            break;
        case 1:
            buffer="Monday";
            break;
        case 2:
            buffer="Tuesday";
            break;
        case 3:
            buffer="Wednesday";
            break;
        case 4:
            buffer="Thursday";
            break;
        case 5:
            buffer="Friday";
            break;
        case 6:
            buffer="Saturday";
            break;
        default:
            printf("ERROR\n");
            break;
    }
}

Back in main() you print it and that's it. My main looks like this:

int main()
{
    int d=0,m=0,y=0;
    printf("DD MM YYYY: ");
    scanf("%d %d %d",&d,&m,&y);
    printf("\n");
    DatePtr date1=createDate(d,m,y);
    char *s=getDinamicShortDate(date1);
    char *strDay;
    dayWeekStr(date1,strDay);
    printf("Date: %s, %s\n",strDay,s);

    date1=destroyDate(date1);
    free(s);
    s=NULL;
    return 0; 
}

So when I run it, I expect this:

DD MM AAAA: 9 9 2022
    
Fecha: Friday, 9/9/2022

But instead, this is the result:

DD MM AAAA: 9 9 2022

Fecha:

I really don't know what happened. I tried printing buffer's value inside the function, and it seems it stores it, but then in main it doesn't.

I also tried changing the function to

char *dayWeekStr(DatePtr date)

so it actually returns a string after the switch:

char *dayWeekStr(DatePtr date)
{
    switch (dayWeek(date))
    {
        case 0:
            return "Sunday";
            break;
        case 1:
            return "Monday";
            break;
        case 2:
            return "Tuesday";
            break;
        case 3:
            return "Wednesday";
            break;
        case 4:
            return "Thursday";
            break;
        case 5:
            return "Friday";
            break;
        case 6:
            return "Saturday";
            break;
        default:
            return "-1";
            break;
    }
}

In main it only changes from

char *strDay;
dayWeekStr(date1,strDay);

to

char *strDay=dayWeekStr(date1);

and it does work. I believe the problem has something to do with the char pointer variable retaining its value after exiting the void function, but what's the issue here?


Solution

  • You have passed the value of the pointer to your function, which is stored in a local variable. Assigning to that local variable does nothing to the original pointer, but if we used string functions which use the value in that pointer, we can. For instance, using strcpy to copy the correct string into the buffer pointed to by the function argument.

    #include <string.h>
    #include <stdio.h>
    
    void weekday(int day, char *buffer) {
      char *days[] = {
        "Sunday", "Monday", "Tuesday", "Wednesday",
        "Thursday", "Friday", "Saturday"
      };
    
      if (day <= 6 && day >= 0) {
        strcpy(buffer, days[day]);
      }
      else {
        strcpy(buffer, "-1");
      }
    }
    
    int main(void) {
      int day = 2;
      char day_of_week[20] = {0};
    
      weekday(day, day_of_week);
    
      printf("%s\n", day_of_week);
    
      return 0;
    }
    

    Note also that rather than using a long switch statement or if/else, I've simply indexed into an array of strings. Remember this pattern anytime you are using a switch for a lookup with sequential numbers.