#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) должен проверить, было ли уже появление этой буквы, почему это бесполезно? еще раз спасибо за помощь