#c #function
#c #функция
Вопрос:
float Calculate(const string amp;query)
{
std::cout << "Query: " << query << "n";
unsigned int size = query.length();
char stack[70];
float res;
int m = 0;
for (int i = 0; i < size; i )
{
if (query[i] >= '0' amp;amp; query[i] <= '9')
{
stack[m] = query[i] - '0';
m ;
continue;
}
switch (query[i])
{
case ' ':
{
res = stack[m - 2] stack[m - 1];
break;
}
case '-':
{
res = stack[m - 2] - stack[m - 1];
break;
}
case '*':
{
res = stack[m - 2] * stack[m - 1];
break;
}
case '/':
{
res = stack[m - 2] / stack[m - 1];
break;
}
}
stack[m - 2] = res;
m--;
cout << "RES: " << res << "n";
}
return res;
}
Она вычисляет обратную польскую нотацию.
Когда я вызываю что-то вроде: Calculate("11 ")
это возвращает правильный результат: 2
.
Но, когда я передаю переменную после получения строки RPN:
string inputStr;
string outputStr;
cout << "Put exercisen";
getline(std::cin, inputStr);
outputStr = GetRPN(inputStr);
cout << "Output str :" << outputStr << ":n";
float res = Calculate(outputStr);
std::cout << res << "n";
Итак, когда я ввожу string: 1 1
, функция GetRPN
возвращает 11
, и я вижу это во втором cout. Но результат есть 0
!
Что бы это могло быть?
string GetRPN(string input)
{
vector <char> operation;
string outputStr; //output string, keep RPN
int stack_count = 0;
for(int i = 0; i < input.length(); i )
{
if(input[i] >= '0' amp;amp; input[i] <= '9')
{
outputStr = input[i];
}
else
{
if(operation.empty())
{
operation.push_back(input[i]);
stack_count ;
}
else if(operation[stack_count - 1] == ' ' || operation[stack_count - 1] == '-')
{
operation.push_back(input[i]);
stack_count ;
}
else if ((operation[stack_count - 1] == '*' || operation[stack_count - 1] == '/') amp;amp; (input[i] == '*' || input[i] == '/'))
{
outputStr = operation[stack_count - 1]; // move mark of operation to output str
operation.pop_back(); // delet last element from vector
operation.push_back(input[i]);// plus new operation mark to vector
stack_count ;
}
else if (operation[stack_count - 1] == '*' || operation[stack_count - 1] == '/')
{
outputStr = input[i];
}
}
}
for(int i = operation.size(); i >= 0; i--)
{
outputStr = operation[i]; // move all operation marks to otput str
}
return outputStr;
}
Комментарии:
1. Убедитесь, что у вас нет завершающих пробелов или других «мусорных» символов-пробелов, возвращающихся из GetRPN — вы можете распечатать длину.
2. Не уверен, что
GetRPN
делает, но это может оставить окончательноеn
илиr
в строке outputStr , которое не может быть сопоставлено вswitch (query[i])
, оставляяres
каким-то образом null…3. Ваш
Calculate()
выглядит нормально, и при идентичном вводе должен выдаваться тот же результат. Можете ли вы также опубликовать своюGetRPN()
функцию?4. Я никогда не знал, что
std::string
естьlenght()
функция-член, которая возвращает то же значение, что иsize()
.5. Заключительный цикл GetRPN выглядит подозрительно — вы не хотите начинать с i = operation.size()-1? Если у вас есть строка из 2 символов, вы хотите добавить только элементы 1 и 0, а не 2, 1 и 0. Однако это не объясняет, почему вы видите правильный вывод.
Ответ №1:
Ваш цикл здесь
for(int i = operation.size(); i >= 0; i--)
{
outputStr = operation[i]; // move all operation marks to otput str
}
не имеет никакого смысла. Очевидно, что вы пытаетесь получить доступ к вектору с недопустимым индексом. Недопустимо обращаться к элементу в момент, когда operation[i]
значение i
равно operation.size()
. Индекс находится вне диапазона.
Любая уважающая себя реализация немедленно сообщила бы об этой проблеме с утверждением. В любом случае, как я сказал в комментарии, подобные проблемы решаются путем отладки кода. Почему вы просите других людей отлаживать ваш код вместо того, чтобы делать это самостоятельно?
Ответ №2:
Если в вашей строке есть какие-либо пробелы или непечатаемые символы, вы в конечном итоге сохраните в stack
с отрицательным индексом, что перезапишет другие данные в вашем фрейме стека и может привести к тому, что что-нибудь произойдет.
Вам следует добавить некоторую проверку ошибок в Calculate
— переключатель должен иметь default
, который выводит разумное сообщение об ошибке, и вы должны проверить значение m
перед обращением к stack[m]
or stack[m-2]
, чтобы убедиться, что стек не переполняется (и вы должны напечатать разумную ошибку, если это произойдет.) Вы должны быть в состоянии передать ЛЮБУЮ случайную строку для вычисления и заставить ее сообщить вам, почему это недопустимое выражение RPN.