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.