Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C-奇怪的字符出现在字符串中_C_Gcc - Fatal编程技术网

C-奇怪的字符出现在字符串中

C-奇怪的字符出现在字符串中,c,gcc,C,Gcc,我正在尝试用C编写一个简单的Caesar密码。我正在创建一个加密函数,它接收一个字符串(char*,要加密的文本)和一个整数(密钥) 在函数中,我为接收移位字符的空字符串分配内存。然后,我遍历初始字符串中的每个字符,询问它是否是字母字符(a-z)。如果是,则根据键进行移动。如果不是,它只是重复当前字符。问题是:当字符如。甚至在结尾出现空格,也会添加一些“?”。我已经输入了printf语句,我的猜测是未定义的行为正在发生,但我自己无法理解。我希望有人能帮助我。下面是我写的代码和奇怪的结果 char

我正在尝试用C编写一个简单的Caesar密码。我正在创建一个加密函数,它接收一个字符串(char*,要加密的文本)和一个整数(密钥)

在函数中,我为接收移位字符的空字符串分配内存。然后,我遍历初始字符串中的每个字符,询问它是否是字母字符(a-z)。如果是,则根据键进行移动。如果不是,它只是重复当前字符。问题是:当字符如。甚至在结尾出现空格,也会添加一些“?”。我已经输入了printf语句,我的猜测是未定义的行为正在发生,但我自己无法理解。我希望有人能帮助我。下面是我写的代码和奇怪的结果

char* encrypt(char* entry, int key) {
    int i = 0;
    key = key % 26;
    char * tmp = (char *)malloc(strlen(entry));
    if (!tmp) {
        printf("Error during allocation.\n");
        return entry;
    }
    //memset(tmp, 0, 1); // Tried with and without it.
    char t;
    while ((t = *(entry + i))) {
        printf("Current letter: %c\n",*(entry+i));
        if ((t >= 65 && t <= 90) || (t >= 97 && t <= 122)) { //is letter 
            *(tmp + i) = t + key > 90 ? t + key - 26 : t + key;
        }
        else { //isnt letter
            printf("No letter char appeared. Code = %d\n",t); 
            *(tmp+i) = t;
        }
        printf("tmp letter: %c\n",*(tmp+i));
        printf("current tmp: %s\n----------------\n",tmp);
        i++;
    }
    printf("final tmp = %s\n",tmp);
    entry = tmp;
    free(tmp);
    return entry;
}

tldr;您正在打印从未初始化过的内存中的字符串。尝试使用
calloc
而不是
malloc

我认为您的示例中出现的情况是,您缺少零字节来终止字符串。为了理解正在发生的事情,你必须考虑这两件事:

  • C字符串以零字节终止(
    \0
    )。处理C字符串的函数总是希望字符串末尾有一个零字节。如果没有这样的终止符,他们只会假设字符串还没有结束
  • malloc
    不初始化分配的内存。这意味着
    printf(“%s”,malloc(10))可能打印或不打印某些内容。这取决于大量因素,因此通常被称为“未定义行为”
  • 回到您的案例:您分配
    tmp
    ,但从不使用零初始化它。但这是打印报表工作所必需的。因此,使用类似于
    calloc(1,strlen(entry)+1)
    的方法。(请注意
    +1
    。字符串终止符(
    \0
    )还需要一个字节)

    为了让您了解正在发生的事情,我建议您添加一个
    memset(tmp,'X',strlen(条目))在您的
    malloc
    行之后。然后试着理解输出


    旁注:以下内容不会将字符串从
    tmp
    复制到
    entry

    entry = tmp;
    free(tmp);
    return entry;
    

    基本上,您只需在此处返回
    tmp
    ,它指向一个空闲内存块,并将导致函数外部的无效内存访问。您想要使用的是
    memcpy

    tldr;您正在打印从未初始化过的内存中的字符串。尝试使用
    calloc
    而不是
    malloc

    我认为您的示例中出现的情况是,您缺少零字节来终止字符串。为了理解正在发生的事情,你必须考虑这两件事:

  • C字符串以零字节终止(
    \0
    )。处理C字符串的函数总是希望字符串末尾有一个零字节。如果没有这样的终止符,他们只会假设字符串还没有结束
  • malloc
    不初始化分配的内存。这意味着
    printf(“%s”,malloc(10))可能打印或不打印某些内容。这取决于大量因素,因此通常被称为“未定义行为”
  • 回到您的案例:您分配
    tmp
    ,但从不使用零初始化它。但这是打印报表工作所必需的。因此,使用类似于
    calloc(1,strlen(entry)+1)
    的方法。(请注意
    +1
    。字符串终止符(
    \0
    )还需要一个字节)

    为了让您了解正在发生的事情,我建议您添加一个
    memset(tmp,'X',strlen(条目))在您的
    malloc
    行之后。然后试着理解输出


    旁注:以下内容不会将字符串从
    tmp
    复制到
    entry

    entry = tmp;
    free(tmp);
    return entry;
    

    基本上,您只需在此处返回
    tmp
    ,它指向一个空闲内存块,并将导致函数外部的无效内存访问。您想要使用的是与此问题无关的
    memcpy

    ,但在
    释放
    后返回指针。释放内存后,不允许使用它指向的内存。@xing这确实解决了我的问题!你能给我一个更深刻的解释吗?谢谢:)您将入口设置为指向与tmp相同的位置,然后将其释放。
    tmp
    entry
    都指向释放的内存,不允许使用它们。在不使用ITI后释放内存如果没有其他东西使用内存,则内容可能可以访问,并且相同。但这不是保证,是未定义的行为。任何事情都可能发生,包括数据。或者撞车。或随机数据。它不考虑空值,它只给出字符串中的字符数。终止符必须始终手动添加,因为它并不总是需要的。例如,如果您将字符串写入文件,您希望知道要写入多少个字符,而不是多少加一。与此问题无关,但在释放后返回一个指针。释放内存后,不允许使用它指向的内存。@xing这确实解决了我的问题!你能给我一个更深刻的解释吗?谢谢:)您将入口设置为指向与tmp相同的位置,然后将其释放。
    tmp
    entry
    都指向释放的内存,不允许使用它们。在不使用ITI后释放内存如果没有其他东西使用内存,则内容可能可以访问,并且相同。但这不是保证,是未定义的行为。任何事情都可能发生,包括数据。或者撞车。或随机数据。它不考虑空值,它只给出字符串中的字符数。终止符必须始终手动添加,因为它并不总是需要的。例如,如果将字符串写入文件,则希望知道要写入的字符数,而不是h
    entry = tmp;
    free(tmp);
    return entry;