Я пытаюсь прочитать строку из argv. Это должно быть что-то вроде математической функции, например "-x^2-5"
и т. д.
У меня есть что-то вроде этого:
void test(char *function){
int temp = 0;
for (int i = 0; i < strlen(function); i++){
if ((function[i] != '+') && (function[i] != ...){
// function[i] is a digit, but still as a char
temp = atoi(function[i]);
}
}
//...
}
int main(int argc, char **argv){
test(argv[1]);
//...
}
Это работает довольно хорошо до последнего круга цикла.
Если я использую printf("%c", function[i]);
, он говорит, что это 5
.
Но atoi(function[i])
дает segfault. Почему?
Включите предупреждения компилятора! function[i]
— это один char
, а не char*
. Таким образом, он неявно приводится к типу указателя и atoi
пытается читать с почти нулевого адреса памяти. Возможно, вы имели в виду &function[i]
или function + i
atoi(function[i])
на самом деле недействителен C, поэтому любой компилятор, пропускающий этот код, плох. Имейте в виду, что большинство основных компиляторов C по умолчанию работают в «плохом режиме». Вы должны добавить -std=c11 -pedantic-errors
, чтобы превратить их в компиляторы C. Также см. Проблемы «Указатель из целого числа/целое число из указателя без приведения».
Верно. Давайте сначала посмотрим на подпись atoi
.
int atoi(const char *str);
Теперь вы передаете ему function[i]
, а поскольку function
имеет тип char *
, function[i]
является char
. И ваш персонаж, скорее всего, не является правильным указателем персонажа.
Вместо этого вы хотите передать atoi
const char *
, который вы можете получить, позвонив atoi(&function[i]);
@xXxKaddiexXx Хотя, если бы я пытался анализировать подобные выражения, я бы рассмотрел возможность проведения «правильного» лексического анализа выражения, а затем использовал бы что-то вроде алгоритма «сортировочной станции» для создания дерева выражений из предоставленного пользователем выражение. Облегчает распознавание того, является ли символ оператором, переменной, такой как x, или литеральным значением, таким как 2. Также упрощается оценка.
Как уже сказал @sham1, atoi
ожидает, что его параметр будет строкой C, это массив символов с нулевым завершением, в то время как у вас есть один символ.
Но цифры особенные, потому что они должны иметь последовательные коды. Итак, если вы знаете, что символ (скажем, c
) — это цифра, его значение равно c - '0'
. Итак, вы можете написать:
if ((function[i] != '+') && (function[i] != ...){
// function[i] is a digit, but still as a char
temp = function[i] - '0'; // get the int value of a digit character
}
на самом деле это не сработало в моем случае. Я не уверен, пропустил ли я что-то важное в моем примере кода выше.
Помимо ошибки, указанной в других ответах, atoi
не имеет надежной обработки ошибок, поэтому это одна из функций стандартной библиотеки , которую никогда не следует использовать .
Просто забудьте, что вы когда-либо слышали о atoi
, и замените его на:
char* endptr;
int result = strtol(str,&endptr,10);
if (endptr == str)
{
// some conversion error
}
strtol
также может преобразовать начальную часть строки, если она содержит допустимые числа.
О нет, я этого не знал. Это сэкономило бы много времени xD. Спасибо :)
@xXxKaddiexXx В этом конкретном случае вы, по сути, предоставляете что-то, что не является строкой с нулевым символом в конце, поэтому strtol
вряд ли смог бы найти эту проблему.
Пожалуйста, проверьте
if (argc >= 2)
перед использованиемargv[1]
.