Vigenere 分段错误

Posted

技术标签:

【中文标题】Vigenere 分段错误【英文标题】:Vigenere segmentation fault 【发布时间】:2018-06-18 07:07:22 【问题描述】:
#include<stdio.h>
#include<cs50.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>


int main(int argc, char** argv)
      
      string p;
      int c;  
      if (argc >= 2)
      
          p = get_string("plaintext: ");
      
      if (argc != 2 || isalpha(argv[1][0]) == false)
      
          printf("ERROR\n");
          return 1;
      
      printf("ciphertext: ");
      string k = argv[1];
      int m = strlen(k);
      for(int i = 0,j = 0, n = strlen(p); i < n; i++)
      
        c = p[i] + k[j % m];
        if(isupper(k[j % m]))
        
            k[j % m] = k[j % m] - 'A';
        
        if(islower(k[j % m]))
        
            k[j % m] = k[j % m] - 'a';
        
        if(isalpha(p[i]) == false)
        
            printf("%c", p[i]);
        
        if(islower(p[i]) && islower(c))
        
            printf("%c", c);
            j++;
        
        if(isupper(p[i]) && isupper(c))
        
            printf("%c",c);
            j++;
        
        if(isupper(p[i]) && !isupper(c))
        
            c = ((c - 'A') % 26) + 'A';
            printf("%c", c);
            j++;
        
        if(islower(p[i]) && !islower(c))
        
            c = ((c - 'A') % 26) + 'A';
            printf("%c",c);
            j++;
        
        else(printf("%c",c));
        j++;
           
        printf("\n");
                  

我无法弄清楚我的代码有什么问题。当我尝试运行它时,我可以让它提示我输入明文,但如果我尝试更进一步,我会遇到分段错误。我相信这与我的 for 循环的开始有关?我不知道我是否正确声明了变量c。除此之外,我真的没有任何线索。

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
plaintext: hello
ciphertext: 
Breakpoint 1, main (argc=2, argv=0x7fffffffdf18) at vigenere.c:24
24            for(int i = 0,j = 0, n = strlen(p); i < n; i++)
(gdb) 
(gdb) n
26                  if(isupper(k[j % m]))
(gdb) 
30                  if(islower(k[j % m]))
(gdb) 
32                      k[j % m] = k[j % m] - 'a';
(gdb) 
35                  c = p[i] + k[j % m];
(gdb) 
37                  if(isalpha(p[i]) == false)
(gdb) 
41                  if(islower(p[i]) && islower(c))
(gdb) 
43                      printf("%c", c);
(gdb) 
h44                     j++;
(gdb) 
46                  if(isupper(p[i]) && isupper(c))
(gdb) 
51                  if(isupper(p[i]) && isupper(c) == false)
(gdb) 
57                  if(islower(p[i]) && islower(c) == false)
(gdb) 
65                      (printf("%c",c));
(gdb) 
h66                     j++;
(gdb) 
68                 
(gdb) 
24            for(int i = 0,j = 0, n = strlen(p); i < n; i++)
(gdb) 
26                  if(isupper(k[j % m]))
(gdb) 
30                  if(islower(k[j % m]))
(gdb) 
32                      k[j % m] = k[j % m] - 'a';
(gdb) 
35                  c = p[i] + k[j % m];
(gdb) 
37                  if(isalpha(p[i]) == false)
(gdb) 
41                  if(islower(p[i]) && islower(c))
(gdb) 
43                      printf("%c", c);
(gdb) 
g44                     j++;
(gdb) 
46                  if(isupper(p[i]) && isupper(c))
(gdb) 
51                  if(isupper(p[i]) && isupper(c) == false)

任何人都可以解释为什么即使 if 语句为假, h 也会打印两次?我能够解决这个问题,但我仍在努力弄清楚为什么 c 每次迭代都会输出不止一次。

【问题讨论】:

isalpha(argv[1]) ==> isalpha(argv[1][0]) 您尝试过什么调试问题?难道你不能用笔和纸运行算法,在程序中添加一些调试输出,然后一步一步检查有什么问题吗? 111 是什么 ASCII 字符?您必须查看图表才能知道它是'o',或者您可以使代码可读。反正它可能不是 ASCII。 您使用k[j % m] 开始循环您在以下行中调整k 中的字符。您还需要更多elses,因为c 有时会在循环中多次输出。这就是输出比输入长的原因(我之前的错误,它并不短)。 使用调试器。如果您不能或不愿意使用调试器,请在任何有趣的地方为每个有趣的值添加printf,并检查您的程序是否符合您的预期。使用调试器是更便宜的方式。 【参考方案1】:

您可能会在此处获得特定问题的答案,但如果您想解决它并学习一些东西(这就是 cs50 的重点),请执行以下步骤:

先尝试在没有任何帮助的情况下解决它,如果这不起作用,请执行后续步骤, 观看Zamyla's walkthrough 并尝试一步一步完成, 如果您有一个看起来太难的问题,请离开计算机,拿起笔和一张纸,分析您的程序应该做什么以及它实际做了什么, 学习使用调试器(在 cloud9 cs50 IDE 中,它位于屏幕右侧), 如果您的问题看起来真的,真的很难关闭计算机并用笔和一张纸上床睡觉,您会惊讶地发现躺着解决问题是多么容易:)

当您应用这些步骤并解决您的问题时,您将获得一些解决类似问题的技能,并且您会觉得自己很聪明:)

如果您是一个完全的编程初学者,那么您将面临一些非常棘手的问题(破解、拼写...),但是如果您应用这些步骤,您可以解决所有问题。我知道,因为我做到了,而且我不是专业的 C 程序员、超级聪明或其他什么,但我的“拼写器”解决方案现在排在前 10 位。 耐心点,祝你好运:)

【讨论】:

以上是关于Vigenere 分段错误的主要内容,如果未能解决你的问题,请参考以下文章

CS50 PSet 2:Vigenere 密码分段错误

是啥导致发生分段错误?

命令行参数分段错误(核心转储)

Vigenere python - 找不到子字符串错误

这段代码一次执行良好,另一次出现分段错误

Vigenere cs50 在缺少第二个参数时不会抱怨