CS50 - 调用方法时会出现浮点异常

时间:2014-07-02 04:27:55

标签: c debugging cs50

我是一名新的程序员,他试图通过为CS50做pset来自学。我写了下面的代码,它没有问题。

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


string vencipher(string text, string key)
{
    for (int i=0, j=0, n =strlen(text); i < n; i++,j++)
    {   
        int m = strlen(key);
        if (text[i] >= 65 && text[i] <= 90 && key[j % m] >= 65 && key[j % m] <= 90)
        {
            text[i] = 65 + ((text[i] - 65) + (key[j % m] - 65)) % 26;
        }
        else if (text[i] >= 65 && text[i] <= 90 && key[j % m] >= 97 && key[j % m] <= 123)
        {   
            text[i] = 65 + ((text[i] - 65) + (key[j % m] - 97)) % 26;
        }
        else if (text[i] >= 97 && text[i] <= 123 && key[j % m] >= 65 && key[j % m] <= 90)
        {
            text[i] = 97 + ((text[i] - 97) + (key[j % m] - 65)) % 26;
        }
        else if (text[i] >= 97 && text[i] <= 123 && key[j % m] >= 97 && key[j % m] <= 123)    
        {
            text[i] = 97 + ((text[i] - 97) + (key[j % m] - 97)) % 26;
        }
        else 
        {
            text[i] = text[i];
            j = j - 1;
        }    
    }       
    return text;
 } 

int keyvalidator(string text)
{
    int alphalen = 0;
    for (int i=0, n=strlen(text); i < n; i++)
    {
        if ((text[i] >= 97 && text[i] <= 123) || (text[i] >= 65 && text[i] <= 90))
        {
            alphalen = alphalen + 1;
        }
    }
    if (alphalen == strlen(text))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}  

int main(int argc, string argv[])
{
    if (argc != 2 || keyvalidator(argv[1]) != 1)
    {
        printf("That is not a valid secret key!\n");
        return 1;
    }

    if (argc == 2)
    {
        string secretKey = argv[1];
        string plainText = GetString();
        printf("%s\n", vencipher(plainText, secretKey));       
    }
    return 0;
}

我想尝试将其分成一些不同的方法来尝试提高代码的可读性。这就是我所做的

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

string keycaseID(string key)
{
    for (int i=0, n=strlen(key); i < n; i++)
    {
        if (key[i] >= 65 && key[i] <= 90)
        {
            key[i] = 1;
        }

        else
        {
            key[i] = 0;
        }
    }
    return key;
}

string setkeycase(string key)
{
    for (int i=0, n=strlen(key); i < n; i++)
    {
        if (keycaseID(key)[i] == 1)
        {
            key[i] = key [i] - 65;
        }
        else if (keycaseID(key)[i] == 0)
        {
            key[i] = key [i] - 97;
        }
    }
    return key;
}

string vencipher(string text, string key)
{
    for (int i=0, j=0, n =strlen(text); i < n; i++,j++)
    {   
        int m = strlen(key);
        if (text[i] >= 65 && text[i] <= 90 && keycaseID(key)[j % m] == 1)
        {
            text[i] = 65 + ((text[i] - 65) + setkeycase(key)[j % m]) % 26;
        }
        else if (text[i] >= 65 && text[i] <= 90 && keycaseID(key)[j % m] == 0)
        {   
            text[i] = 65 + ((text[i] - 65) + setkeycase(key)[j % m]) % 26;
        }
        else if (text[i] >= 97 && text[i] <= 123 && keycaseID(key)[j % m] == 1)
        {
            text[i] = 97 + ((text[i] - 97) + setkeycase(key)[j % m]) % 26;
        }
        else if (text[i] >= 97 && text[i] <= 123 && keycaseID(key)[j % m] == 0)    
        {
            text[i] = 97 + ((text[i] - 97) + setkeycase(key)[j % m]) % 26;
        }
        else 
        {
            text[i] = text[i];
            j = j - 1;
        }    
    }       
    return text;
 } 

int keyvalidator(string text)
{
    int alphalen = 0;
    for (int i=0, n=strlen(text); i < n; i++)
    {
        if ((text[i] >= 97 && text[i] <= 123) || (text[i] >= 65 && text[i] <= 90))
        {
            alphalen = alphalen + 1;
        }
    }
    if (alphalen == strlen(text))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}  

int main(int argc, string argv[])
{
    if (argc != 2 || keyvalidator(argv[1]) != 1)
    {
        printf("That is not a valid secret key!\n");
        return 1;
    }

    if (argc == 2)
    {
        string secretKey = argv[1];
        string plainText = GetString();
        printf("%s\n", vencipher(plainText, secretKey));       
    }
    return 0;
}

较新的代码编译但是当我运行它时,我得到一个&#34;浮点异常,&#34;根据我的研究,模数除以0的结果。我搜索了我的代码几次,我找不到任何除法的实例。我想知道是否有人可以帮助我找到我的错误并解释为我在这里导致浮点异常的原因。

2 个答案:

答案 0 :(得分:0)

我还看到了内存损坏的浮点异常,因此在代码中任何地方都没有/字符的情况更可能发生。

我会告诉你某事你做错了。通过多次调用keycaseID()相同的字符串(就像在setkeycase()中一样),您可以保证最终得到一个全零的字符串(0而不是'0')。 / p>

第一次将所有元素转换为1或0,具体取决于它们的情况(因此您将丢失其原始值)。第二次,因为它们全部是01,它们将小于65,因此所有设置为0。

假设您的密钥是所有字母字符(大写或小写),您可以使用类似的东西将其转换为0到25的值:

for (int i = strlen (key) - 1; i >= 0; i--)  // needs string.h
    if (isupper (key[i]))                    // needs ctype.h
        key[i] -= 'A';
    else
        key[i] -= 'a';

或者更短:

for (int i = strlen (key) - 1; i >= 0; i--)  // needs string.h
    key[i] = toupper (key[i]) - 'A';         // needs ctype.h

这些都不是完全可移植的,因为C并没有强制A-Z是连续的代码点,但是,只要你避开奇怪的非ASCII环境,你应该没问题: - )

答案 1 :(得分:0)

问题原因是指针问题,我们还没有在课堂上讨论。这里发生的是字符串是由指向第一个字符的内存中的地址的指针定义的,所以当我尝试通过初始化一个新变量来创建字符串的副本时,我正在创建一个地址,从而编辑原始输入字符串和新副本,因为它们共享相同的内存地址。

因此,m的长度确实为0,因为keycaseID正在修改key的内存地址处的值,因此擦除键并导致setkeycase返回空字符串。