Ошибка сегментации при доступе к аргументу командной строки ~ CS50

#c #segmentation-fault #cs50

#c #ошибка сегментации #cs50

Вопрос:

я новичок в CS и занимался cs50. это был отличный опыт, поскольку я был специалистом по математике, и большинство концепций и заданий действительно хорошо нажимались.

я знаю, что часть процесса обучения заключается в том, чтобы самостоятельно устранять ваши ошибки, но после нескольких часов просмотра одной строки, которую я сузил, вызывает ошибку сегментации, я очень расстраиваюсь.

Я приложил свой код ниже. я потратил час на просмотр руководства по указателям, но все еще не могу понять, почему я могу передать argv[1] в свою функцию validateKey(), но не могу получить доступ к памяти, когда пытаюсь ее использовать.

Я видел, как опытные программисты заявляли, что крайне важно иметь возможность определить, где именно возникает ошибка сегментации, поэтому после отладки я заметил, что в любое время в программе, когда я пытаюсь получить доступ к argv [1] (будь то в main или local), доступ к памяти ограничен

очень ценю ваше время и поддержку!

         #include <cs50.h>
        #include <stdio.h>
        #include <string.h>
        #include <ctype.h>
        #include <stdlib.h>
        #include <math.h>
        
        int findIndex(char keyVal);
        void cipherText(string s, string key);
        bool validateKey(string s);
        
        string alphabet = "abcdefghijklmnopqrstuvwxyz";
        
        int main(int argc, char *argv[])
        {
        
            if (argc != 2)
            {
                printf("Usage ./substitution keyn");
                return (1);
            }
        
            int length = strlen(argv[1]);
        
            if (length != 26)
            {
                printf("Key must contain 26 charactersn");
                return (1);
            }
            else
            {
                if (validateKey(argv[1])) //allows to pass argv[1]
                {
                    string userText = get_string("plaintext: ");
                    cipherText(userText, argv[1]); //allows to pass
                    printf("n");
                    return (0);
                }
                else
                {
                    printf("Usage ./substitution keyn");
                    return (1);
                }
            }
        
        }
        
        bool validateKey(string s)
        {
        
            int n = strlen(s);
            int hash[n][1];
        
            for (int i = 0; i < n; i  )
            {
                int b;
        
                if (isdigit(s[i]))
                {
                    return false;
                }
                b = s[i];
        
                if (hash[b][0] == 1)
                {
                    return false;
                }
                else hash[b][0] = 1;
        
            }
            return true;
        }
        
        int findIndex(char keyVal)
        {
            for (int i = 0; i < 26; i  )
            {
                if (alphabet[i] == tolower(keyVal) || alphabet[i] == toupper(keyVal))
                {
                    return i;
                    break;
                }
            }
            return -1;
        }
        
        void cipherText(string s, string key)
        {
            printf("ciphertext: ");
        
            for (int i = 0, n = strlen(s); i < n; i  )
            {
                if (!(isalnum(s[i])) || isdigit(s[i]))
                {
                    printf("%c", s[i]);
                    continue;
                }
                int index = findIndex(s[i]);
                if (index < 0) break;
        
                if (isupper(s[i]))
                {
                    printf("%c", toupper(key[index])); //SEGMENTATIONF
                    continue;
                }
               else if (islower(s[i]))
               {
                    printf("%c", tolower(key[index]));
               }
               else printf("%c", s[i]);
            }
        }
 

Комментарии:

1. validateKey вызывает UB. Запустите его в своем отладчике, установите точку останова b = s[i]; , выполните один шаг по этой строке, посмотрите на значение b , затем рассмотрите размер hash и то, что вы собираетесь разыменовать.

2. Вы индексируете hash[b][0] = 1; , где b находятся данные из строки. Это не связано с длиной строки, используемой для определения массива int n = strlen(s); int hash[n][1]; , поэтому вы, вероятно, индексируете вне границ. Также обратите внимание, что вы тестируете массив, который вы не инициализировали, поэтому if (hash[b][0] == 1) он бесполезен.

3. @WhozCraig, флюгер: ценю немедленные ответы ваших ребят, очень полезные для новичка вроде меня. что касается validateKey, в моей голове эта функция будет принимать каждую букву из строки (ключ / строка должны содержать все уникальные символы), а b = s [i] приведет этот символ к его значению ASCII. и затем я сохранял каждое вхождение в hash[int(char)][XXX], поэтому, если у меня когда-либо был повторяющийся символ, я мог бы вернуть false и полностью выйти из программы

4. думаю, я пытался использовать его как HashMap, но теперь я вижу, что индексация, вероятно, испорчена

5. @WhozCraig if (hash [b] [] == 1) должен проверить, было ли уже появление этой буквы, почему это бесполезно? еще раз спасибо за помощь