【问题标题】:C Program stops as soon as value is returnedC程序在返回值后立即停止
【发布时间】:2022-01-25 08:15:36
【问题描述】:

我正在为 CS50 的 Pset2 创建一个替换程序,在该程序中我输入一个 26 个字母的密钥,然后输入一些文本,它会根据密钥上的相应字母对其进行加密,当输入具有重复字母的密钥时,它会发送错误消息并返回1 正如预期的那样,但它似乎只是停止了程序。我该如何解决这个问题?

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

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }
    string key = argv[argc - 1];
    for (int s  = 0; s < strlen(key); s++)
    {
        if (key[0] == tolower(key[s]) || key[0] == toupper(key[s]) )
        {
            printf("Key must consist of 26 alphabetic characters.");
            return 1;
        }
    }
    
    if (strlen(key) != 26)
    {
        printf("Usage: ./substitution key\n");
        printf("Key must consist of 26 alphabetic characters.\n");
        return 1;
    }

    int keylen = strlen(key);

    string plaintext = get_string("Enter the plaintext: ");

    char ciphertext [strlen(plaintext)];

    int move[strlen(plaintext)];
    
    printf("ciphertext: ");
    if (keylen == 26)
    {
        for (int counter  = 0; counter < strlen(plaintext); counter++)
        {
            if (plaintext[counter] >= 'a' && plaintext[counter] <= 'z')
            {
                move[counter] = (plaintext[counter]) - 97;
                ciphertext[counter] = key[move[counter]];
            }
            else if (plaintext[counter] >= 'A' && plaintext[counter] <= 'Z')
            {
                move[counter] = plaintext[counter] - 65;
                ciphertext[counter] =key[move[counter]];
            }
            else if (plaintext[counter] < 'A')
            {
                ciphertext[counter] = plaintext[counter];
            }
            else if (plaintext[counter] > 'z')
            {
                ciphertext[counter] = plaintext[counter];
            }
            else if (plaintext[counter] > 'Z' && plaintext[counter] < 'a')
            {
                ciphertext[counter] = plaintext[counter];
            }
        }
        
        for (int loop = 0; loop < strlen(plaintext); loop++)
        {
            if (plaintext[loop] >= 'a' && plaintext[loop] <= 'z')
            {
                printf("%c", tolower(ciphertext[loop]));
            }
            else if (plaintext[loop] >= 'A' && plaintext[loop] <= 'Z')
            {
                printf("%c", toupper(ciphertext[loop]));
            }
            else
            {
                printf("%c", ciphertext[loop]);
            }
        }
        printf("\n");
        return 0;
    }
    for (int i = 0; i < 27; i++)
    {
        if (key[i] < 'A' || key[i] > 'Z')
        {
            if (key[i] < 'a' || key[i] > 'z')
            {
                printf("Key must only contain alphabetic characters.");
                return 1;
            }
        }
    }
}

【问题讨论】:

  • 到底有什么问题?
  • 从 main 调用的 return 通常确实会结束执行。如果您希望返回更复杂的流程,请考虑制作更多功能。还要考虑循环中的继续和中断。

标签: c error-handling cs50


【解决方案1】:

你的代码有很多问题:

  • 您应该首先检查密钥是否有 26 个字符,然后您不需要多次计算 strlen(key)。

  • 初始循环仅将键中的字符与第一个字符大小写独立进行比较:这不足以评估没有重复的字母。

  • 在读取字符串进行加密之前,应测试密钥是否仅包含字母。该测试对于 ASCII 是正确的,但阅读起来有些混乱。此外,循环应该停止在 26,而不是 27。

  • 在计算字母的索引时,不应使用97 或65 等魔术常量。请改用'a' 和'A'。

  • move 数组似乎没用。 cyphertext 数组应为空终止符增加一个字节,并使用编码字节构造,包括大小写转换。

  • 键中的任何错误都会导致程序输出错误消息并返回1,main 函数会导致程序以错误状态退出。

这是修改后的版本:

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

int main(int argc, string argv[]) {
    int flag[26] = { 0 };
    unsigned char c;
    int index;

    /* check if letters are contiguous */
    assert('z' - 'a' == 25 && 'Z' - 'A' == 25);

    if (argc != 2) {
        printf("Usage: ./substitution key\n");
        return 1;
    }
    string key = argv[1];
    if (strlen(key) != 26) {
        printf("Usage: ./substitution key\n");
        printf("Key must consist of 26 alphabetic characters.\n");
        return 1;
    }
    for (int i = 0; i < 26; i++) {
        c = key[i];
        if (c >= 'a' && c <= 'b') {
            index = c - 'a';
        } else
        if (c >= 'A' && c <= 'Z') {
            index = c - 'A';
        } else {
            printf("Key must only contain alphabetic characters.");
            return 1;
        }
        if (flag[index]++) {
            printf("Key contains duplicate letter '%c'.\n", c);
            return 1;
        }
    }
    string plaintext = get_string("Enter the plaintext: ");
    char ciphertext[strlen(plaintext) + 1];
    
    for (int i = 0; (c = plaintext[i]) != '\0'; i++) {
        if (c >= 'a' && c <= 'z') {
            c = key[c - 'a'];
            c = tolower(c);
        } else
        if (c >= 'A' && c <= 'Z') {
            c = key[c - 'A'];
            c = toupper(c);
        }
        ciphertext[i] = c;
    }
    ciphertext[i] = '\0';

    printf("ciphertext: %s\n", ciphertext);
    return 0;
}

【讨论】:

    【解决方案2】:

    这不是错误,这是应该发生的。

    由于密钥字符串是命令行参数,因此如果在命令行级别遇到错误,程序应该结束。然后应该会出现一条错误消息来描述使用该命令的正确方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 2021-07-15
      相关资源
      最近更新 更多