Помогите пожалуйста найти ошибку в программе.
В этой программе более одной ошибки. Кроме того, есть места, не являющиеся ошибкой, но сильно некрасивые.
ifstream fin2("strings.txt");
По условию файл называется string.txt.
Вы изменили мой цикл чтения скобок, добавив в него еще один fin >> c. Видимо, вас к этой мысли привела вот эта часть условия: "В последующих k строках даны
через пробел пары символов". Если это так, то вы неправы. Стандартные операторы чтения из потока >> пропускают все начальные пробельные символы (пробелы, табуляции, перевод строки). Иными словами, никакого дополнительного fin>>c в цикле не нужно, иначе вы будете совершенно неправильно читать информацию из файла types.txt.
string s;
while (!fin2.eof()){
c = fin2.get();
s.push_back(c);
}
Некрасивое посимвольное чтение файла, лучше было бы читать его как минимум построчно. В любом случае данный вариант содержит ошибку, которая опасна тем, что может проявиться не всегда. Проблема в том, что флаг конца файла для eof() устанавливается только в результате неуспешной операции чтения из этого файла. В результате получается такое: вы прочитаете последний символ из файла и добавите его к строке. Потом проверите eof(). Поскольку предыдущая операция чтения была успешной, eof() вернет false даже несмотря на то, что мы уже в конце файла. Потом вы пытаетесь прочитать еще один символ из файла. Результат этой операции не определен, в переменной 'c' может оказаться любой мусор. Этот мусор вы добавляете к строке s. И вот только после этого eof() вернет true и вы выйдете из цикла. Так что этот вариант цикла будет всегда дополнять строку одним лишним символом, который будет иметь неопределенное значение. Существуют разные способы избавиться от этой проблемы. Один способ (не очень хороший) - это вынести первое чтение символа перед цикл while, переставив заодно местами операторы внутри цикла:
string s;
c = fin2.get();
while(!fin2.eof()) {
s.push_back(c);
c = fin2.get();
}
Но решение в стиле C++ вообще не прибегает к eof():
string s;
while (fin2 >> c) {
s += c;
}
Пока успешна операция ввода - добавляем символ к строке. Здесь я заодно использовал += вместо push_back, т.к. для типа string это нагляднее. Кроме того, из-за указанного выше свойства оператора >> это решение пропускает при вводе все пробелы. Для контроля скобочной правильности строки это несущественно.
Что касается основного цикла проверки скобочной правильности:
- после того, как вы обработали очередную скобку внутри цикла по i, вы можете использовать оператор break, чтобы сразу перейти к следующей итерации цикла по j;
- когда стек пуст его длина равна нулю а не единице, поэтому проверку if((stack.size()-1)==0) надо заменить на if(stack.size() == 0), а опытные программисты вообще написали бы тут if(stack.empty()).
- вы пишете NO когда стек пуст и это правильно. Но что происходит когда на вершине стека неправильная скобка, т.е. когда проверка if(para(stack[stack.size()-1])==s[j]) не срабатывает? В этом случае тоже должно писаться NO, но у вас этого нет. Доступ к последнему элементу лучше делать через stack.back(). На самом деле эти две проверки должны быть скомбинированы в одну с помощью логического ИЛИ: когда стек пуст ИЛИ на вершине стека плохая скобка:
if(stack.empty() || (para(stack.back()) !=s[j])) { пишем NO } else { вытолкнуть скобку из стека }.
- вместо того, чтобы сравнивать парную скобку для stack.back() с s[j] можно сравнить stack.back() с парной скобкой для s[j]. Но ведь s[j] == ket[
i], поэтому парной скобкой для нее будет bra[
i] и функция para становится вообще не нужной.
Наконец, после окончания основного цикла вы пишете YES если стек пуст (только опять у вас неправильная проверка на длину стека равную 1), но где вывод NO если стек не пуст? Ваш цикл после минимума исправлений:
vector<char> stack;
for(int j = 0; j < s.size(); ++j){
for(int i = 0; i < k ; i++){
if(bra[i]==s[j]){
stack.push_back(s[j]);
break; // обработали скобку и переходим к следующему символу строки s
}
if(ket[i]==s[j]){
if(stack.empty() || (stack.back() != bra[i])){
cout << "NO";
getch();
return 0;
}
stack.pop_back();
break; // обработали скобку и переходим к следующему символу строки s
}
}
}
if(stack.empty()){
cout << "YES";
} else {
cout << "NO";
}