简体   繁体   中英

Why does this program return a "?" symbol in C

I'm following along with cs50x and in problem set 2. This is the idea I had for solving the Caesar problem. I'm yet to implement the key idea due to the fact that it won't print out the word. I'm new to arrays and have searched a bit about why this is occurring. I think that I'm overcomplicating the code and could just use the string given by the user instead of transferring it to a function but now that I've started the idea I want to know why it isn't working and if there is a way to make it work. When ran, the program should accept a command line of a single number, if it has no command line it should fail, if the number is negative it should fail, if it is not a number it should fail and if it has more than 1 argument it should fail. Thanks

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



string cipher(string word, int key);

int main(int argc, string argv[])
{

    // Checks whether the user inputted only 1 argument
    if (argc == 2)
    {
        // Convert argv to an int
        int key = atoi(argv[1]);
        string plainText = get_string("plaintext:  ");

        // Use function to return the (soon to be encrypted) string
        string cipherText = cipher(plainText, key);

        // Print for how long the word is
        int n = strlen(plainText);
        for (int i = 0; i < n; i++)
        {
            // Print the char of the array based upon the iteration of the loop which runs for however long the word is
            printf("%c", cipherText[i]);
        }
        printf("\n");
        // If input is not a positive integer then it will fail
        if (key < 1)
        {
            printf("Usage: ./caesar key\n");
        }
    }
    else
    {
        // If user inputted too many or no inputs then it will fail
        printf("Usage: ./caesar key\n");
    }
    return 0;
}

string cipher(string word, int key)
{
    // Find the length of the word in order to set the size of the array
    // This is so that both strings, the word inputted and the word to return are the same to add to
    int n = strlen(word);

    string cipherText[n];

    // Loop through the input word
    for (int i = 0; i < n; i++)
    {
        // If char[i] is a letter then copy that letter into ciphertext
        if (isalpha(word[i]))
        {
            cipherText[i] =& word[i];
        }
        else
        {
            cipherText[i] =& word[i];
        }
    }
    // Return the array which, for example the input word is nobody
    // Return array[n, o, b, o, d, y]
    return cipherText[0-n];
}

The issue is that you are attempting to copy the address of the "word" character array characters into the associated cipher text array element which will print out unknown characters (noted in the above comments).

    // Loop through the input word
    for (int i = 0; i < n; i++)
    {
        // If char[i] is a letter then copy that letter into ciphertext
        if (isalpha(word[i]))
        {
            cipherText[i] = &word[i];
        }
        else
        {
            cipherText[i] = &word[i];
        }
    }

When I ran your program with the code like that, I indeed got a series of question marks.

@Una:~/C_Programs/Console/CypherCS50/bin/Release$ ./CypherCS50 12
plaintext: Hello
?????

I then revised it to perform a copy of character elements from "word" to "cipherText".

// Loop through the input word
for (int i = 0; i < n; i++)
{
    // If char[i] is a letter then copy that letter into ciphertext
    if (isalpha(word[i]))
    {
        cipherText[i] = word[i];
    }
    else
    {
        cipherText[i] = word[i];
    }
}

Then, reran the program.

@Una:~/C_Programs/Console/CypherCS50/bin/Release$ ./CypherCS50 12
plaintext: Hello
Hello

Seeing that the same data came out, my guess is that you still need to work on the actual encryption bits. But, the crux of the issue was referencing the memory of the work array elements.

Give that a try.

This does not fix your OP issue, but addresses another issue and responds to our exchange in comments above. Here is a "skeleton" demonstrating how you might approach incrementally developing code for this task. The 'excessive' printf's serve to prove that things are proceeding as you want as the source code becomes more elaborate..

// Functions defined before use do not need to be prototyped
// do-nothing "skeleton" to be completed
string cipher(string word, int key)
{
    printf( "In cipher with key %d and str '%s'\n", key, word ); // temp code confirmation

    return word; // for now...
}

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return -1; // early termination
    }
    printf( "argv[1] = %s\n", argv[1] ); // prove functionality

    int key = atoi(argv[1]);
    printf( "key = %d\n", key ); // prove functionality

    if (key <= 0)
    {
        printf("Key must be positive integer");
        return -1; // early termination
    }
    string plainText = get_string("plaintext:  ");
    printf( "plain = %s\n", plainText ); // prove functionality

    string cipherText = cipher(plainText, key);
    printf( "cipher = %s\n", cipherText ); // prove functionality

    return 0; // All done!
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM