我的常量在改变,我不知道为什么,甚至不知道如何

My constant is changing, and I dont know why, or even how

我正在制作一个基本上“加密”文本的程序,方法是用其他字母替换字母。所以你基本上 运行 程序并输入一个分布,然后输入你想要加密的文本,它会把密码还给你。

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

string make_lower(string word);

int main (int argc, string argv[])
{
    //we examine the input
    if (argc < 2 || argc > 2)
    {
        printf("Usage: ./substitution key\n");
        return (1);
    }
    
    if (strlen(argv[1]) != 26)
    {
        printf("Key must contain 26 characters.\n");
        return (1);
    }
    
    if (strlen(argv[1]) == 26)
    {
        for (int i = 0; i < 26; i++)
        {
            if (isdigit(argv[1][i]))
            {
                printf("Key must onlyontain alphabetic characters.\n");
                return (1);
                exit(0);
            }
        }
        
        for (int i = 0; i < 26; i++)
        {
            for (int o = i + 1; o < 26; o++)
            {
                if (argv[1][i] == argv[1][o])
                {
                    printf("Key must not contain repeated characters.\n");
                    return (1);
                    exit(0);
                }
            }
        }
        
        //we prompt the user for the words to transcribe
        const string text = get_string("plaintext:  ");
        
        //we set everithing in lower caso to compare it, and set a new variable to store the original text so we can convert the 
        // upper cases back later
        string ntext = text;
        
        printf("%s\n", text);
        
        argv[1] = make_lower(argv[1]);
        
        ntext = make_lower(ntext);
        
        printf("%s\n", text);
        
        string alphabet = "abcdefghijklmnopqrstuvwxyz";
        
        //we substitute the text to the desired outcome
        for (int i = 0, n = strlen(ntext); i < n; i++)
        {
            for (int o = 0; o < 26; o++)
            {
                if (ntext[i] == alphabet[o])
                {
                    ntext[i] = argv[1][o];
                }
            }
        }
        
        printf("%s\n", text);
        
        printf("ciphertext: ");
        
        for (int i = 0, n = strlen(ntext); i < n; i++)
        {
            if (isupper(text[i]))
            {
                printf("%c", toupper(ntext[i]));
            }
            else
            {
                printf("%c", ntext[i]);
            }
        }
        
        printf("%s\n", text);
        
        printf("\n");
        
        return(0);
        
        exit(0);
    }
}

string make_lower(string word)
{
    for (int i = 0; i < strlen(word); i++)
    {
        word[i] = tolower(word[i]);
    }
    
    return(word);
}

所以我的问题出在代码的输出上,因为问题是如果你想要加密的文本是例如“Hello”,它应该像“Ktlly”这样的例子出现,但我的输出是“ktlly”,因此结果中不显示大写字母。

当您输入要加密的代码时,程序将其存储在一个常量字符串中,然后创建一个新变量并将其设置为等于您输入的文本,然后程序将该新变量转换为小写,因此它可以进行比较,最后当我们对文本进行加密时,我尝试通过制作一个 if 语句(第 82 行)将我想要的那些字符再次变成大写,但事实并非如此。我试着看看为什么,这就是为什么我设置在第 56、62、78 和 94 行打印常量,看看为什么它不起作用,结果发现变量在变化,即使是应该是一个常数。起初在第 56 行它仍然是原始文本;然后在第 62 行,它是相同的文本,但小写;然后在第 78 行和第 94 行,它本身被修改为文本的加密版本。

基本上就是这样,我不知道为什么会这样。至少对我来说,代码似乎是正确的,我的理论是它与函数有关,或者它与洞代码内置的大“if”语句有关。感谢您通读所有这些。

make_lower 改写了它的参数。您需要复制 string。考虑使用 strdup().

我有点惊讶这没有引发编译器警告。

string make_lower(string word)
{
    word = strdup(word);
    //...

以下评论错误:

//we set everithing in lower caso to compare it, and set a new variable to store the original text so we can convert the 
// upper cases back later
string ntext = text;

cs50.h中定义的标识符string只不过是数据类型char *typedef。这意味着 string 类型的变量实际上并不包含字符串,而只是指向一个字符串。

在上面引用的行中,您只是复制指针,而不是实际的字符串。由于 ntexttext 现在都指向同一个字符串,当您修改 ntext 指向的字符串时,您也在修改 text 指向的字符串。这似乎不是你想要的。

如果要创建字符串的副本,而不仅仅是复制指针,则必须首先使用 malloc, and then you can copy the string using strcpy:

为新字符串分配内存
//allocate memory for copy of the string
string ntext = malloc( strlen(text) + 1 ); //add 1 for the terminating null character of the string

//copy the string
strcpy( ntext, text );

大多数编译器还支持函数 strdup,它在单个函数调用中处理内存分配和字符串复制。如果您的编译器支持该函数,那么您可以改用它:

string ntext = strdup( text );

请注意,所有内存分配函数(例如 mallocstrdup)都可能失败,例如当操作系统内存不足时。在那种情况下,函数 mallocstrdup 将 return 一个 NULL 指针。如果你使用这样一个 NULL 指针而不事先检查它是否是 NULL,那么你的程序很可能会崩溃。出于这个原因,我在上面发布的代码实际上是错误的,因为它在取消引用指针之前没有检查 NULL

因此,下面的代码会更好,它检查 NULL 的 return 值,如果内存分配失败,则打印错误消息并退出程序:

对于malloc/strcpy:

//allocate memory for copy of the string
string ntext = malloc( strlen(text) + 1 );

//verify that allocation was successful
if ( ntext == NULL )
{
    fprintf( stderr, "memory allocation error!\n" );
    exit( EXIT_FAILURE );
}

//copy the string
strcpy( ntext, text );

对于strdup

string ntext = strdup( text );

if ( ntext == NULL )
{
    fprintf( stderr, "memory allocation error!\n" );
    exit( EXIT_FAILURE );
}