Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Чулов.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
829.35 Кб
Скачать
    1. Алгоритм расчетов в электронной таблице

Основное поле для ввода в ячейки реализовано через классы

Cell

SpreadsheetCompare

QTableWidget

Рассмотрим подробнее как реализовано создание самой таблицы.

В классе Spreadsheet объявляем число колонок и столбцов.

enum { MagicNumber = 0x7F51C883, RowCount = 999, ColumnCount = 26 }; - задаём магическое число, колонки и строки.

Давайте, рассмотрим куда мы попадаем при нажатии на ячейку таблицы. При описании алгоритма наши комментарии выделены курсивом.

QVariant Cell::data(int role) const

{

if (role == Qt::DisplayRole) {

if (value().isValid()) { - если значение попавшее в ячейку не содержит пометку QVariant::Invalid то возвращаем true

return value().toString(); возвращаем преобразованное значение в тип String

} else {

return "####"; - в другом случае заполняем ячейку решётками

}

} else if (role == Qt::TextAlignmentRole) { - если значение текстового типа возвращаем true

if (value().type() == QVariant::String) { -если значение value string

return int(Qt::AlignLeft | Qt::AlignVCenter); -Выравнивание текста

} else {

return int(Qt::AlignRight | Qt::AlignVCenter);

}

} else {

return QTableWidgetItem::data(role);

}

}

Давайте, рассмотрим куда попадает строка если в ней содержится формула.

QString Cell::formula() const

{

return data(Qt::EditRole).toString(); - возвращаем строку

}

QVariant Cell::value() const

{

if (cacheIsDirty) {

cacheIsDirty = false;

QString formulaStr = formula();

if (formulaStr.startsWith('\'')) { - если нет формулы

cachedValue = formulaStr.mid(1);

} else if (formulaStr.startsWith('=')) { -если есть формула

cachedValue = Invalid; -присваиваем invalid

QString expr = formulaStr.mid(1); -expr присваиваем formulaStr

expr.replace(" ", ""); - удаляем пробелы

if (expr.contains("sin") == true || expr.contains("cos") == true || expr.contains("tan") == true || expr.contains("ctg") == true ) { - если expr содержит sin или cos,tan,ctg тогда (пример для синуса)

while (expr[expr.indexOf("sin")+3] == QChar('(') && expr[expr.indexOf("(")+1] != QChar(')') ) – пока у нас есть синус ячейки

если у нас закрывающая скобка стоит после синуса

if(expr.indexOf(")") > expr.indexOf("sin") ) {

int i = 5;

QString token;

while (expr[expr.indexOf("sin")+i] != ')')

{

token += expr[expr.indexOf("sin")+i]; -

i++;

}

int column = expr[expr.indexOf("(")+1].toUpper().unicode() - 'A'; -преобразуем ячейку в числовой вид

int row = token.toInt()-1;

Cell *c = static_cast<Cell *>(

tableWidget()->item(row,column)); -переходим в ячейку

QVariant result;

if (c) result = c->value(); - если ячейка существует тогда присваиваем переменной result значение из ячейки.

result = sin(result.toDouble()); - синус из результата

expr.replace(expr.indexOf("sin"),expr.indexOf(")")-expr.indexOf("sin")+1,result.toString()); - заменяем sin(A1) на значение переменной result.

}

expr.append(QChar::Null); -добавляем \000

int pos = 0;

cachedValue = evalExpression(expr, pos); - присваиваем значение cachedValue

if (expr[pos] != QChar::Null) – если значение не в юникод формате

cachedValue = Invalid; - присваиваем invalid

} else {

bool ok; - объявляем переменную

double d = formulaStr.toDouble(&ok); -если строка перекодируется

if (ok) {

cachedValue = d; -присваиваем d

} else {

cachedValue = formulaStr; -присваиваем cachedValue значение formulaStr.

}

}

}

return cachedValue; - возвращаем значение cachedValue.

}

QVariant Cell::evalExpression(const QString &str, int &pos) const

{

QVariant result = evalTerm(str, pos); - присваиваем переменной result значение функции

while (str[pos] != QChar::Null) { - пока в строке не закончатся символы

QChar op = str[pos]; - присваиваем переменной op значение одного символа из массива строки str.

if (op != '+' && op != '-') –если у нас op не равен плюсу либо минусу

return result; - возвращаем результат

++pos;

QVariant term = evalTerm(str, pos); - присваиваем переменной term значение функции

if (result.type() == QVariant::Double – если тип переменной result и тип переменной term double то

&& term.type() == QVariant::Double) {

if (op == '+') { - если плюс

result = result.toDouble() + term.toDouble(); плюсуем

} else {

result = result.toDouble() - term.toDouble(); минусуем

}

} else {

result = Invalid; - иначе возвращаем invalid

}

}

return result;

}

QVariant Cell::evalTerm(const QString &str, int &pos) const

{

QVariant result = evalFactor(str, pos); - присваиваем значение переменной result

while (str[pos] != QChar::Null) { - пока не кончатся символы

QChar op = str[pos]; - переменной op присваиваем str[pos]

if (op != '*' && op != '/') – если op не ровна * или / тогда

return result; возвращаем result

++pos; - добавляем единицу к переменной pos

QVariant factor = evalFactor(str, pos); - переменной factor присваиваем значение функции evalFactor

if (result.type() == QVariant::Double

&& factor.type() == QVariant::Double) { - если тип result и factor double тогда

if (op == '*') {

result = result.toDouble() * factor.toDouble(); - если op равна * присваиваем переменной result выражение

} else {

if (factor.toDouble() == 0.0) {

result = Invalid;

} else {

result = result.toDouble() / factor.toDouble();

}

}

} else {

result = Invalid;

}

}

return result;

}

Реальный пример расчета максимальной дальности полёта с использованием тригонометрических функций привидён на Рис 7.

Рис 7 Расчётная таблица дальности полёта тела брошенного под углом горизонту