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

#define MAX_STRING  20

char *getFirstName() {
    char firstName[MAX_STRING];
    printf("Please enter your first name: ");
    gets(firstName);
    return (firstName);
}

char *getLastName() {
    char lastName[MAX_STRING];

    printf("Please enter your last name: ");
    gets(lastName);
    return (lastName);
}

char *getNickName() {
    char nickName[MAX_STRING];
    printf("Please enter your nick name: ");
    gets(nickName);
    return (nickName);
}

char *getCompleteName(const char *firstName,
                      const char *lastName,
                      const char *nickName) {
    char *completeName;
    sprintf(completeName, "%s \"%s\" %s", firstName, nickName, lastName);
    return (completeName);
}

int main() {
    char *firstName;
    char *lastName;
    char *nickName;
    char *completeName;

    firstName   = getFirstName();
    lastName    = getLastName();
    nickName    = getNickName();

    completeName = getCompleteName(firstName, lastName, nickName);
    printf("Hello %s.\n", completeName);
    return (EXIT_SUCCESS);
}

What is wrong with the code. It always print nickname in all the the three varaiables firstName, lastName and nickName.

Output: Output]

it must display the complete name. I think error is in the getCompleteName function.

6
  • 3
    You are returning an array that is on the stack. When the function ends so does that part of the stack. The return from these functions point to stuff that can and does change Commented Feb 21, 2016 at 9:09
  • 1
    Instead of the picture - cut'n'paster the output Commented Feb 21, 2016 at 9:14
  • 1
    I have in-lined the image for you, but as Ed says, the output is plain-text and could have more easily and readably been posted as such. Commented Feb 21, 2016 at 9:16
  • Can you point out the mistake exactly where it lies. ? Commented Feb 21, 2016 at 9:16
  • 1
    You should use fgets instead of gets to avoid overflows Commented Feb 21, 2016 at 9:17

6 Answers 6

2

In function getCompleteName, you must allocate memory for completeName before you compose the contents into it:

char *getCompleteName(const char *firstName, 
                      const char *lastName,
                      const char *nickName)
{
    size_t size = strlen(firstName) + strlen(lastName) + strlen(nickName) + 5;
    char *completeName = malloc(size);
    if (completeName) {
        snprintf(completeName, size, "%s \"%s\" %s", firstName, nickName, lastName);
    }
    return completeName;
}

Notes:

  • the calling function will be responsible for freeing the memory. This allocation scheme is practical but error prone, known to cause memory leaks in sloppy implementations.
  • the rest of the code has the same problem: pointers must point to allocated memory, static arrays or local arrays in the calling function.
  • you must not use gets(), it cannot be used safely. Use fgets() and strip the trailing linefeed.
Sign up to request clarification or add additional context in comments.

2 Comments

Is this a bit of hassle when the maximum length is knoiwn
@EdHeal: of course if the maximum length is known, this function should take a pointer to a local array in the callers scope and its size. For the OP's API, the above code works, and could be simplified if aprintf is available in the target environment.
1

I recommend to use arrays of char and pass them to your function as parameter. You local array char firstName[MAX_STRING]; goes out of scope if getFirstName terminates. This meas the variable is not longer accessible after getFirstName has terminated and a pointer to the variable is undefined behaivoir.

#include <stdio.h>

#define MAX_STRING 10

void getFirstName( char *firstName )
{
    printf("Please enter your first name: ");
    fflush( stdout );
    fgets( firstName, MAX_STRING, stdin );
}

void getLastName( char *lastName )
{
  printf("Please enter your last name: ");
  fflush( stdout );
  fgets( lastName, MAX_STRING, stdin );
}

void getNickName( char *nickName )
{
    printf("Please enter your nick name: ");
    fflush( stdout );
    fgets( nickName, MAX_STRING, stdin );
}

void getCompleteName (
         char*          completeName,
         const char*    firstName,
         const char*    lastName,
         const char*    nickName)
{
  sprintf(completeName,"%s \"%s\" %s",firstName,nickName,lastName);
}

int main ()
{
  char firstName[MAX_STRING];
  char lastName[MAX_STRING];
  char nickName[MAX_STRING];
  char completeName[MAX_STRING*3+10];

  getFirstName( firstName  );
  getLastName( lastName );
  getNickName( nickName );

  getCompleteName( completeName, firstName, lastName, nickName );
  printf("Hello %s.\n",completeName);
  return(EXIT_SUCCESS);
} 

Apart form this use fgets insted of gets, because fgets checks the maximum number of characters to be read (including the final null-character) See How to read from stdin with fgets()?

4 Comments

I think you need to add fflush after the printfs
This does not work: you must strip the '\n at the end of the line read by fgets(), plus you must check for end of file.
gets should not be used in an answer
This explains nothing. You just did his homework for him.
1
char* completeName;
sprintf(completeName,"%s \"%s\" %s",firstName,nickName,lastName);

Where does completeName point to? This invokes undefined behavior due to use of an indeterminate value.

You should provide static storage, e.g. with

static char completeName[128];

The next problem is that automatic variables, such as go out of scope when the function returns. You should make the arrays static to avoid this.

2 Comments

.. That would not help much either - see my comment above
I have done this way but it always diplay nickname 3 times as output.
1

1) You cannot use the array on the stack - perhaps this could would be better

 void getDetail(const char * const prompt, char *detail, int maxSize)
 {
    printf("%s:", prompt);
    fflush(stdout); // Gives the user a chance to set it
    if (fgets(detail, maxSize, stdin) == NULL) {
       detail[0] = 0; // EOF - Empty string
    }
    else
    {
       // Strip off new line
       size_t l = strlen(detail);
       if (detail[l - 1] == '\n') detail[l - 1] = 0;
    }

 }

2) Using it

char firstName[MAX_SIZE];
getDetail("Please enter you first name", firstName, MAX_SIZE);


... ditto for the others

3) Now making the complete name

char completeName{MAX_SIZE * 3 + 10]; // Cannot be bothered to work out the exta but that will be enough
sprintf(completeName,"%s \"%s\" %s",firstName,nickName,lastName);

... If you wish put this into a function passing in the array to it. But does not seem worthwhile in the example

4) Printing the complete name

printf("Complete name is :%s\n", completeName);

1 Comment

Note that because of the trailing \n, the buffer should be defined with an extra byte: its size should be the maximum length of the field + 2.
0

The pointer variable completeName is uninitialized, causing what the C standard calls unidentified behaviour. Anything can happen.

You are also trying to return arrays from your functions. They are converted to pointers to the first element in each array, and that pointer is returned. But since the array is a local variable, with what is called "storage class auto", it disappears when the function returns. Rhe memory may be re-used for other things, but the pointer still points to that place in memory. Again, the behaviour is undefined.

Comments

0

Use arrays of char and fgets instead of gets. By the way, your initial code produces segmentation error on Ubuntu 15.10 and gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010.

SK

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.