Ошибка сегментации Виженера

#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)

кто-нибудь может объяснить, почему h печатается дважды, хотя оператор if ложен? Мне удалось решить проблему, но я все еще пытаюсь понять, почему c будет выводить более одного раза для каждой итерации.


person sanjay    schedule 18.06.2018    source источник
comment
Что вы пытались отладить проблему? Не могли бы вы запустить алгоритм с ручкой и бумагой, добавить в программу несколько отладочных выходных данных и шаг за шагом проверить, что не работает?   -  person Nico Haase    schedule 18.06.2018
comment
После исправления упомянутой мной ошибки и использования scanf, поскольку у меня нет CS50, я запустил программу с аргументом qwerty и ввел строку antidisestablishmentarianism, она выводит TM[]ZJSawwUttzzbewwyyPcdZeeSbyydewwd, которая длиннее введенного текста. То же самое, но введенный текст был one two, а вывод - HML, что короче введенного текста. Кроме того: не используйте магические числа, такие как 65, используйте 'A' и т. д.   -  person Weather Vane    schedule 18.06.2018
comment
разве 65 не должно работать? потому что это 'A' в десятичной диаграмме ASCII.   -  person sanjay    schedule 18.06.2018
comment
И какой символ ASCII 111? Вы должны посмотреть на диаграмму, чтобы узнать, что это 'o', или вы можете сделать код читаемым. В любом случае это может быть не ASCII.   -  person Weather Vane    schedule 18.06.2018
comment
Последовательно печатает код c (printf("%x ", (unsigned int)(unsigned char)c);) и проблемы должны стать очевидными...   -  person Serge Ballesta    schedule 18.06.2018
comment
Кто-нибудь из вас, ребята, видит какие-либо проблемы с циклом for?   -  person sanjay    schedule 18.06.2018
comment
Вы запускаете цикл, используя k[j % m] до настройки символа в k в следующих строках. Вам также нужно еще несколько else, потому что c иногда выводится в цикле более одного раза. Вот почему выход длиннее, чем вход (мой плохой раньше, он не был короче).   -  person Weather Vane    schedule 18.06.2018
comment
Большое спасибо! мой код наконец работает. Спасибо за ваше время, я очень ценю это.   -  person sanjay    schedule 18.06.2018
comment
... используя больше else, вам не придется повторять уже сделанные тесты, что сделает код более эффективным и простым для понимания. Всякий раз, когда вы выводите c, следующий код должен быть в блоке else. Это закроет дыры в логике потока.   -  person Weather Vane    schedule 18.06.2018
comment
Мой код работает, но не могли бы вы объяснить, почему c выводит больше раз для некоторых циклов. Я не понимаю, зачем это делается. это как-то связано с синтаксисом?   -  person sanjay    schedule 18.06.2018
comment
Используйте отладчик. Если вы не можете или не хотите использовать отладчик, добавьте printf для каждого интересующего значения в любом интересном месте и проверьте, выполняет ли ваша программа то, что вы ожидаете. Использование отладчика является менее затратным способом.   -  person harper    schedule 18.06.2018
comment
Добро пожаловать в Stack Overflow! Пожалуйста, отредактируйте свой вопрос, чтобы показать нам, какую отладку вы выполнили. Я ожидаю, что вы запустили свой минимально воспроизводимый пример в Valgrind или аналогичном средстве проверки и исследовали его с помощью отладчика. такие как GDB, например. Убедитесь, что вы также включили полный набор предупреждений компилятора. Что инструменты сказали вам, и какую информацию они упускают? И прочтите статью Эрика Липперта Как отлаживать небольшие программы. .   -  person Toby Speight    schedule 18.06.2018
comment
у кого-нибудь есть идеи, почему h печатается дважды? То же самое происходит и с остальными буквами.   -  person sanjay    schedule 20.06.2018
comment
Если вы хотите знать, что делает ваш код, используйте осмысленные имена для переменных. Я хочу помочь, но жонглирование p,c,m,i,j,n причиняет боль моему мозгу   -  person Braca    schedule 23.06.2018
comment
У вас есть еще одна ошибка. Вы проверяете только первый символ аргумента ключевого слова. Вы должны перебрать все символы и проверить их с помощью isalpha()   -  person Braca    schedule 23.06.2018


Ответы (1)


Здесь вы можете получить ответ на свою конкретную проблему, но если вы хотите решить ее и чему-то научиться (в этом суть cs50), выполните следующие действия:

  • Сначала попробуйте решить ее без посторонней помощи, если это не сработает, выполните следующие шаги,
  • Посмотрите пошаговое руководство Замилы и попробуйте выполнить его шаг за шагом,
  • Если у вас есть проблема, которая кажется вам слишком сложной, отойдите от компьютера, возьмите ручку и лист бумаги и проанализируйте, что должна делать ваша программа и что она делает на самом деле.
  • Научитесь пользоваться отладчиком (в IDE cloud9 cs50 он находится в правой части экрана),
  • Если ваша проблема кажется действительно-действительно сложной, выключите компьютер и ложитесь спать с ручкой и листком бумаги, вы удивитесь, насколько легче решать проблемы лежа :)

Когда вы примените эти шаги и решите свою проблему, вы приобретете некоторые навыки для решения подобных проблем, и вы почувствуете себя умнее :)

Если вы совсем новичок в программировании, впереди вас ждут действительно сложные проблемы (взлом, правописание...), но если вы примените эти шаги, вы сможете решить их все. Я знаю, потому что я знал, и я не являюсь опытным программистом на C, супер-умным или кем-то еще, но мое решение для «орфографии» теперь в десятке лучших.
Наберитесь терпения и удачи :)

person Braca    schedule 21.06.2018