Ошибка сегментации для числового ввода
Я пишу свою первую программу на C, и она доставляет мне много проблем. Это довольно просто; введите число, и результат будет соответствующим термином в последовательности Фибоначчи, где первый и второй термины равны 1. Первоначально он работал, пока я не поставил ничего, кроме числа, в качестве ввода; буквы или специальные символы вызвали ошибку сегментации. Чтобы исправить это, я попытался отклонить все нечисловые вводы, и так как я не мог найти функцию, чтобы сделать это, я сделал свой собственный. К сожалению, теперь он дает ошибку сегментации, когда задан числовой ввод, а все нечисловые входы читаются как 26.
Компилятор, gcc с педантичными предупреждениями, жалуется только на мои комментарии. Я использовал GDB, чтобы сузить ошибку сегментации:
return strtol(c, n, 10);
Любая помощь для выявления проблемы и ее избежания в следующий раз будет принята с благодарностью.
Код:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
calcTerm(); //Run calcTerm()
return 0; //Return value & exit
}
int fibTerm(int term)
{
//Declare Variables
int a = 0;
int b = 1;
int next;
int x;
//Calculate the sequence
for (x = 0; x <= (term - 2); x++)
{
next = a + b;
a = b;
b = next;
}
return next; //return the requested output
}
int calcTerm()
{
//declare variables
int in;
char rawIn[256];
char **n;
int out;
printf("Input the term you want to find:\n"); //request input
//get input
fgets(rawIn, 3, stdin);
//define variables
in = isNumeric(rawIn); /*strtol(rawIn, n, 10) works*/
out = fibTerm(in);
//print result
printf("Term %i " "is %i", in, out);
}
int isNumeric(char test[256])
{
//declare variables
char validChars[10] = "0123456789"; //valid input characters
char *c = test;
char **n;
if (strpbrk(test, validChars)) //if input contains only valid characters ?
{
return strtol(c, n, 10); //return the input as an integer
//segmentation fault; strtol_l.c: no such file
}
else
{
printf("Please only input numbers."); //error message
}
}
2 ответа
n
унифицирован и указывает на никуда. strtol
попытается записать в адрес памяти, указанный n
, который может быть где-нибудь в памяти, и он, вероятно, не указывает на область, где вам разрешено писать. Просто передайте туда нулевое значение (т.е. strtol(c, 0, 10)
).
Кстати, я бы попробовал использовать sscanf
разобрать номер; sscanf
возвращает число проанализированных токенов, поэтому, если вы получите ноль в качестве возвращаемого значения, число будет недействительным. Например:
const char* my_string = " 123";
const char* my_invalid_string = "spam spam spam";
int number;
sscanf(my_string, "%d", &number); // this should return 1
sscanf(my_invalid_string, "%d", &number); // this should return 0
И так как вы все равно читаете из стандартного ввода, вы можете пропустить сохранение строки в строке и затем вызвать sscanf
Вы можете просто использовать scanf
проанализировать стандартный ввод напрямую.
Вы получаете случайный вывод для ввода 1
потому что в fibTerm
цикл никогда не будет введен (for (x = 0; x <= (term - 2); x++)
с term == 1
). Следовательно, неинициализированный next
значение будет возвращено