Home > Back-end >  Setting return value of char pointer to a char array
Setting return value of char pointer to a char array

Time:11-23

Trying to learn C. To that end, I'm coding a program that creates a TroubleTicket report. The user is prompted to enter, priority, name and problem. I'm using a struct to store the data and create a struck array. Using the array approach for now as I'm developing the code. Eventually, I'd to use a linked list.

Anyhow, the get_input() function reads in the user input and returns a char pointer. Included the get_input() and create_ticket() functions.

#define NUM_TICKETS 10

char* get_input(int maxlen)
{
    static char s[110];
    char ch;
    int i = 0;
    int chars_remain = 1;

    while (chars_remain)
    {
        ch = getchar();
        if ((ch == '\n') || (ch == EOF))
        {
            chars_remain = 0;
        }
        else if (i < maxlen - 1)
        {
            s[i] = ch;
            i  ;
        }
    }
    s[i] = '\0';
    return s;
    
void create_ticket()
{
    struct ticket
    {
        int priority;
        int number;
        char * name;
        char * problem ;
        char * assigned_to;
        char * status ;
    };
    struct ticket tkt_array[NUM_TICKETS];
    struct ticket new_ticket;
    
    printf("Enter your name: ");
    new_ticket.name = get_input(20);
    printf("new_ticket.name: %s \n", new_ticket.name);
        
    printf("Enter problem description: ");
    new_ticket.problem = get_input(100);
    printf("new_ticket.problem: %s \n", new_ticket.problem);
    
    printf("Assigned to: ");
    new_ticket.assigned_to = get_input(20);
    printf("new_ticket.assigned_to %s\n ", new_ticket.assigned_to);
    
    printf("Enter ticket status: ");
    new_ticket.status = get_input(10);
    printf("new_ticket.status: %s \n", new_ticket.status);
    
}

I noticed that initial input was read and displayed correctly but subsequent inputs overwrote prior input.

For example, after name was entered, the entered value is displayed

printf("Enter your name: ");
new_ticket.name = get_input(20);
printf("new_ticket.name: %s \n", new_ticket.name);

But after problem description is entered, new_ticket.name was changed to display the problem description text. Took me a while to figure out that the problem is the return s in get_char(). It returns a pointer. The address is the same but the value changes and struct ticket pointers point to the same address of return s from get_char(). How can I save the return value in a variable and not get it reset on subsequent call to get_input? s is a char *, how can I save the return value of a pointer in a variable?

printf("Enter problem description: ");
new_ticket.problem = get_input(100);
printf("new_ticket.problem: %s \n", new_ticket.problem);
printf("new_ticket.name: %s \n", new_ticket.name);

How can I save the return value in a variable and not get it reset on subsequent call to get_input? s is a char *, how can I save the return value of a pointer in a variable? I hope I clearly stated the issue.

CodePudding user response:

This answer addresses only the problem stated in the question, not other errors or problems in your code.

Your function get_input uses a single array static char s[110]; to store the input and always returns the address of this array.

Assignments like new_ticket.name = get_input(20); will store the same address in all pointer variables, so all will actually point to the same variable s which will contain the last input.

One option to solve this would be to replace the pointers in your structure with arrays and either pass this to get_input or copy the value using strcpy.

Or you could use the (non-standard) function strdup to get a dynamically allocated duplicate of the input string. If this function is not available, you could implement it using malloc and strcpy.

Example:

    new_ticket.name = strdup(get_input(20));

or

    const char *s1;
    char *s2;
/* ... */

    s1 = get_input(20);
    s2 = malloc(strlen(s1)   1);
    if(s2 == NULL)
    {
        /* handle error */
    }
    else
    {
        strcpy(s2, s1);
    }
    new_ticket.name = s2;

or

    struct ticket
    {
        int priority;
        int number;
        char name[20];
        char problem[100];
        char assigned_to[20];
        char status[10];
    };

/* ... */
    strcpy(new_ticket.name, get_input(sizeof(new_ticket.name));

CodePudding user response:

The static keyword creates a value that exists once, so multiple invocations of the function point to the same data.

If you want to dynamically create data with a lifetime that you control, you may allocate your own memory.

malloc(size) will allocate a block of memory with the size provided. This memory will exist and be valid until you call free on that memory.

You should be careful though, calling free twice, or forgetting to call it at all, are common sources of bugs within c code.

The other option in this is to have the caller of the function provide the memory. You could change your struct ticket to have char name[MAX_NAME_LEN], and update the function get input to get_input(int max_len, char * buffer). This also solves the problem, while avoiding potentially erroneous malloc and frees.

  • Related