1
string makecipher(string plaintext, string key1)
{

int lentext = strlen(plaintext);
// printf("%i",lentext);
char ciphertext[lentext];

for (int i = 0; i < lentext; i++)
{--some code---
    else
    {
        ciphertext[i] = key1[i];
    }
}
printf("%s cipehrtext\n", ciphertext);
return ciphertext;

}

in the main function the code is

       string newtext= makecipher(plaintext, argv[1] );
        printf("ciphertext: %s", newtext);

I am able to see the result in side the function. But I want to return ciphertext variable to the main for printing etc. the program runs and ciphertext inside the function prints but the newtest in main doesnt print.An error shows while compiling "function returns address of local variable".

1 Answer 1

1

In contrast to many other programming languages, in the language C, arrays cannot be directly copied, passed to or returned from functions like other data types (such as char, int and float). Instead, when you attempt to copy an array using the = operator, or attempt to pass an array to a function or to return one from a function, you are actually copying/passing/returning a reference to the array, instead of an actual copy of the array. This reference is technically called a "pointer". You will learn more about them in Week 4 of CS50.

The language C was designed this way for performance reasons, because copying a large array can be very expensive in terms of performance.

For the reason stated above, the line

return ciphertext;

will not create a copy of the array ciphertext, but will instead return a reference to the existing array ciphertext.

In C, when you declare a local variable in a function, that variable has a lifetime that ends when the function ends. This rule also applies to local arrays. The array ciphertext will cease to exist as soon as the function makecipher ends.

Therefore, when your return a reference to the array ciphertext from the function makecipher, you are returning a reference to an array that will cease to exist immediately after the function returns. For this reason, the reference you are returning is effectively useless. Your compiler noticed this and is therefore warning you about this with the error message "function returns address of local variable". The "address of local variable" is the reference to the array ciphertext.

The CS50 data type string (which does not exist in standard C) is also a reference to an array, but is not an array itself. So if you declare the function makecipher to return a string, you are actually declaring the function to return a reference to an array.

For the reasons stated above, your approach of attempting to create a copy of the array and returning that copy, will not work. Although it is possible to do this in C, you will first have to watch Week 4 of CS50 in order to understand how to do this.

The Problem Sets of Week 2 of CS50 are designed in such a way that it is not necessary to create a copy of the array. Instead, the intended way of solving the problem is to either

  • print every individual ciphertext character immediately after calculating its values, so that they don't have to be stored in an array, or
  • overwrite the original plaintext characters with the ciphertext characters.

If you really want to store all ciphertext characters in a separate array in order to print them all out at once, then there are several ways of doing this. You will learn of one way in Week 4 of CS50. However, for now, the simplest way of doing this is to create a second array in the function main which is of the same size as your plaintext array, which you can pass to your function makecipher.

Below you will find an example program on how this can be done. Note, however, that this program is merely a demonstration on how to solve this particular problem, and is not a solution to the assignment.

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

//forward declaration
void makecipher(string ciphertext, string plaintext);

int main(void)
{
    // Declare an array with an example plaintext
    // string. Your actual solution code should not
    // hard-code the plaintext, but should get the
    // plaintext from the user using the function
    // "get_string" instead.
    char plaintext[] = "This is a test.";

    // Declare an array for the ciphertext that is
    // of the same size as the plaintext.
    char ciphertext[strlen(plaintext) + 1];

    // pass both arrays to the function "makecipher"
    makecipher(ciphertext, plaintext);

    //print the plaintext as well as the ciphertext
    printf("Plaintext:  %s\n", plaintext);
    printf("Ciphertext: %s\n", ciphertext);
}

void makecipher(string ciphertext, string plaintext)
{
    int len = strlen(plaintext);

    // encipher one character per loop iteration
    for (int i = 0; i < len; i++)
    {
        // In this demonstration, the enciphering merely
        // consists of converting the character to
        // upper-case. This is simply to demonstrate that
        // the character sequence can be modified.
        ciphertext[i] = toupper(plaintext[i]);
    }

    //add the terminating NUL character to the end
    ciphertext[len] = '\0';
}

This program has the following output:

Plaintext:  This is a test.
Ciphertext: THIS IS A TEST.

As you can see, the function makecipher was able to write a modified copy of plaintext to ciphertext, and the function main was able to print both.

All the function makecipher did was to convert the lower-case characters to the corresponding upper-case character. Therefore, this is not a good cipher. However, this is sufficient for demonstration purposes. For the assignment, you will have to program a better cipher.

Here is a working demonstration of this program.

6
  • Thanks a lot Gave a good understanding Commented Apr 14, 2023 at 12:19
  • @AsifDawood: I am pleased that I was able to help. If my answer solved your problem, then you may want to consider accepting my answer. See this official help page for further information: What should I do when someone answers my question? Commented Apr 14, 2023 at 12:37
  • I have seen cases where locally defined strings and integers are returned. Ex. in string get_guess(int wordsize) in wordle, a string is defined locally and returned. Also another example in exercise runoff the function int find_min(void) returns a locally defined integer. Both these programs ran smoothly. i am not able to post the code for the same since there is character restriction in the comment box. Can you explain this please Commented Apr 15, 2023 at 16:31
  • @AsifDawood: Returning locally defined int variables is not a problem and should always work, because an actual copy of the int is returned. However, this is not the case with locally defined arrays, because only the reference to the array is returned. Commented Apr 15, 2023 at 16:49
  • @AsifDawood: The CS50 data type string is nothing more than a reference to an array. Therefore, whether it is ok to return a "locally defined string" depends on what the string is referencing. If it is referencing the result of get_string or an element of argv, then it should not be a problem. However, it if is referencing a local array, then it is a problem. However, even in this case, the program may happen to work despite the string variable referencing an object whose lifetime has ended, if that object happens to not have been overwritten by anything else. [...] Commented Apr 15, 2023 at 16:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .