【问题标题】:C - Changing a string seems to change unrelated strings in the same way (CS50)C - 更改字符串似乎以相同的方式更改不相关的字符串 (CS50)
【发布时间】:2022-01-15 21:41:53
【问题描述】:

代码如下:

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


int main(int argc, string argv[])
{
    string key = argv[1];
    string keyupper = argv[1];
    string keylower = argv[1];


    if (argc != 2) //makes sure there is exactly 2 arguments (the program executable and the key)
    {
        printf("Please input a key.\n");
        return 1;
    }

    else if (strlen(key) != 26) //makes sure the key is exactly 26 letters
    {
        printf("Please make sure the key is 26 unique letters.\n");
        return 1;
    }



    for (int i = 0; i < 26; i++) //the loop to make the uppercase key
    {
        keyupper[i] = toupper(keyupper[i]);
    }



    for (int i = 0; i < 26; i++) //the loop to make the lowercase key
    {
        keylower[i] = tolower(keylower[i]);
    }

本质上,我想使用在执行程序时输入的密钥进行非常基本的加密,它需要包含 26 个唯一字母。我想创建两个数组,一个大写和一个小写,以使其他一切对我来说更容易,但是在运行此代码时,所有键都变为大写或小写,具体取决于最后创建的循环(在这种情况下,它们都是变成小写)。即使key 被更改为小写,即使它只用作声明一次。除了这个,其他一切都有效。

这是针对 CS50 课程的,因此库中包含 toupper() 等函数。

这是我的第一个问题,如果措辞不当,非常抱歉。谢谢!

【问题讨论】:

  • 它们不是不相关的字符串:三个变量都指向同一个字符串。 string key = argv[1]; 不会创建新字符串,只会创建指针的副本。例如,您需要string key = strdup(argv[1]);
  • 如果你查看string 的typedef,你会发现它是一个指针。它不包含它指向的数据的副本。所有的指针都指向同一个数据块。如果您需要数据的副本以便能够对其进行更改并保持原始数据不变,请制作副本。
  • 谢谢大家!我想我已经尽可能地了解它了,现在我知道该怎么做了。
  • 再一次,cs50 在 typedef 别名中隐藏基本指针类型(如 char *)的可怕尝试再次让毫无戒心的初学者陷入困境。如果所有这三个变量都是char * 而不是string,并且main 的参数包括char *argv[] 而不是string argv[],那么问题会更加更加明显。指针在 C 中无处不在 使用,相信我,C 工程师希望看到那些 * 的。它是一面巨大的挥舞旗帜,宣布“这是指向某物的指针”。接受这一点,不要像 cs50 那样在别名中隐藏指针类型。
  • @Nizz 你没有正确理解。指针一个变量。它是一个变量,其值为地址。正如int 保存整数,float 保存浮点值,char 保存字符值一样,指针也是如此;他们持有地址。 int a; int *p = &amp;a; 声明了两个变量;一个int var 和一个指向int var 的指针。 cs50 的标头在别名 string 后面隐藏了一个指针类型,这使得 less 很明显,您的所有代码所做的只是将相同的 address 复制到三个不同的指针变量中,所有之后他们指向相同的数据

标签: arrays c string cs50


【解决方案1】:

代码无法复制字符串内容

[这里说的是string,不是string这个类型]

在 C 中,string 是“...是一个连续的字符序列,以第一个空字符终止并包括第一个空字符。”

代码只复制了指针而不是字符串的内容。

string key = argv[1];
string keyupper = argv[1];
string keylower = argv[1];

评论讨论表明 OP 现在知道代码错误的原因。

修复的代码

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

// Avoid naked magic numbers, instead define them
#define KEY_N 26

int main(int argc, string argv[]) {
    // Do not code argv[1] until after argc check
    // string key = argv[1];
    // string keyupper = argv[1];
    // string keylower = argv[1];

    if (argc != 2) {
        printf("Please input a key.\n");
        return 1;
    }

    char *key = argv[1];
    // else if (strlen(key) != 26)letters
    if (strlen(key) != KEY_N) {
        printf("Please make sure the key is 26 unique letters.\n");
        return 1;
    }

    char keyupper[KEY_N + 1];
    char keylower[KEY_N + 1];

    // for (int i = 0; i < 26; i++)
    for (size_t i = 0; i < KEY_N; i++) {
        // keyupper[i] = toupper(keyupper[i]);
        keyupper[i] = toupper((unsigned char) key[i]);
    }
    keyupper[KEY_N] = '\0';
    ...

【讨论】:

  • @nielsen 是的。修改代码 - 也处理负面的char
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-25
  • 1970-01-01
相关资源
最近更新 更多