Электронная таблица

Опубликовано Sep 8, 2011 в Тестовые проекты (2-3 часа) | 2 коммент.

, ,

Электронная таблица

Тестовое задание: электронная таблица

Цель данного задания: проверка навыков ООП и алгоритмического мышления.

Формат выполнения: Задание выполнялось исключительно в нашем офисе.  В распоряжении кандидатов был стандартный компьютер с установленными Visual Studio и MSDN. Результатом выполнения ожидалось консольное приложение.

Используемые библиотеки: можно использовать STL

Время выполнения первой стадии: от 1-го до 2.5 часов.

Вторая стадия опциональна и может быть выполнена кандидатом в домашних условиях.

Постановка задачи

Необходимо реализовать обработчик простой электронной таблицы по аналогии с Microsoft Excel в виде программы, выполняющейся из командной строки. Программа должна уметь обрабатывать следующие типы ячеек:

  • EmptyCell: пустая ячейка
  • IntegerCell: Неотрицательное целое число (помещается в dword 32 бита)
  • StringCell: Текстовые строки, которые начинаются с символа ‘
  • ReferenceCell: Строки-выражения, которые начинаются с символа ‘=’ и могут содержать Ссылки на другие ячейки. Состоят из одной латинской буквы и следующей за ней одной цифры.

Процесс обработки таблицы:

  1. Все выражения должны быть заменены на вычисленный результат.
  2. Ячейки с текстом должны быть вычислены как соответствующий текст без префикса ‘.
  3. Пустые ячейки и ячейки с типом IntegerCell должны остаться неизменными.
  4. Ячейки, содержащие ссылки, должны быть заменены соответствующими значениями. Ссылки могут ссылаться на другие ссылки.
  5. В случае любой ошибки вычисления формулы/ссылки, вычисляемая ячейка должна содержать ‘#error’.

Программа должна использовать только стандартные библиотеки и классы и не должна вызывать сторонние программы, библиотеки или системные компоненты.

Ввод и вывод

Программа получает описание таблицы с формулами из стандартного ввода, вычисляет ее и печатает полученный результат в стандартный вывод. Входные данные представлены таблицей, элементы строк которой разделены табуляциями (или запятой – на выбор).

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

Вывод должен содержать только ожидаемую информацию, включая сообщения об ошибках. Никакой другой информации в выводе не должно быть.

Пример входных данных: (3 строки, 4 столбца)

3

4

12         =C1    3   ‘Sample

=A1        =A2    =B3  ‘Spread

‘Test       4      5   ‘Sheet

 

Ожидаемый вывод:

12      3      3      Sample

12      12     4      Spread

Test    4      5      Sheet

 

Этап №1 (выполняемый в нашем офисе)

  • Входные данные читаются из двумерного массива текстовых значений (глобальная переменная).
  • Ссылки могут задаваться только как “= [A-Z – только одна буква], [0-9 – только одна цифра]”.

 

Этап №2

  • Входные данные читаются из std in
  • Ссылки могут быть типа =AA10

Наш пример решения для первого этапа этого задания на C++ можете посмотреть
по этой ссылке.


2 Коммент. : “Электронная таблица”

  1. Игорь says:
    //+++++++++++++++++Cell.h+++++++++++++++
    #pragma once
    #include <string>
     
    using std::ostream;
    using std::string;
     
    class Cell{
    public:
    	virtual void print(ostream& os) const{};
    };
     
    class EmptyCell : public Cell{
    public:
    	ostream& operator<< (ostream& os) const{
    		return os;
    	}
    };
     
    class IntegerCell : public Cell{
    	int value;
     
    public:
    	IntegerCell(const int v) : value(v) {}
    	void print(ostream& os) const{
    		os << value;
    	}
    };
     
    class StringCell : public Cell{
    	string value;
     
    public:
    	StringCell(const char* v) : value(v) {}
    	StringCell(const string v) : value(v) {}
    	void print(ostream& os) const{
    		os << value;
    	}
    };
     
    class ReferenceCell : public Cell{
    	Cell** cell;
     
    public:
    	ReferenceCell(Cell** cell) : cell(cell) {}
    	void print(ostream& os) const{
    		(*cell)->print(os);
    	}
    };
     
     
    //+++++++++++++++++ETable.h+++++++++++++++
    #pragma once
     
    #include "Cell.h"
     
    class ETable{
    	Cell** table;
    	size_t row, col;
     
    public:
    	ETable() : table(0), col(0), row(0) {};
    	~ETable();
     
    	void loadFromFile(const char* path);
    	void print(ostream& os) const;
    };
     
     
    //+++++++++++++++++ETable.cpp+++++++++++++++
    #include "ETable.h"
    #include <fstream>
     
    ETable::~ETable(){
    	if(table){
    		for(int i = 0; i < col; i++)
    			delete[] table[i];
    		delete[] table;
    	}
    }
     
    void ETable::loadFromFile(const char* path){
    	std::ifstream f(path);
    	if (!f.bad())
    	{
    		f >> col;
    		f >> row;
    		table = new Cell*[col * row];
     
    		char c;
    		for(int i = 0; i < col * row; i++)
    		{
    			f >> c;
    			switch(c)
    			{
    			case '\'':
    				char svalue[256];
    				f >> svalue;
    				table[i] = new StringCell(svalue);
    				break;
     
    			case '=':
    				char c1, c2;
    				int nr, nc;
    				f >> c1;
    				f >> c2;
    				if(c2 > '9') nr = c1 - 'A' + (c2 - 'A' + 1) * 26; 
    				else {
    					nr = c1 - 'A';
    					f.putback(c2);
    				}
    				f >> nc;
    				nc--;
    				if(nc < col && nr< row) table[i] = new ReferenceCell(&table[nc*row +nr]);
    				else table[i] = new StringCell("#error");
    				break;
     
    			case '0': case '1': case '2':
    			case '3': case '4': case '5':
    			case '6': case '7': case '8': case '9':
    				f.putback(c);
    				int ivalue;
    				f >> ivalue;
    				table[i] = new IntegerCell(ivalue);
    				break;
    			}
    		}
    		f.close();
    	}
    }
     
    void ETable::print(ostream& os) const{
    	for(int i = 0; i < col; i++){
    		for(int ii = 0; ii < row; ii++){
    			table[i * row + ii]->print(os);
    			os << " ";
    		}
    		os << std::endl;
    	}
    }
     
     
    //+++++++++++++++++main.cpp+++++++++++++++
    #include <iostream>
    #include "ETable.h"
     
    int main(){
    	ETable t1;
    	t1.loadFromFile("dat.txt");
    	t1.print(std::cout);
    }
    • Александр says:

      Ошибка в

      if(c2 > '9') nr = c1 - 'A' + (c2 - 'A' + 1) * 26;

      Код, как я понял, должен обрабатывать ссылки типа =AA3, =AC2 и тд. и вычислять номер столбца nr
      В данном случае при =AC2: nr = ‘A’ – ‘A’ + (‘C’ – ‘A’ + 1)*26 = 0 + (2+1)*26 = 78
      Хотя номер столбца AC: 28;

      Код станет правильным, если поменять местами с1 и с2:

      if(c2 > '9') nr = c2 - 'A' + (c1 - 'A' + 1) * 26;

Оставить комментарий

Ваш адрес email не будет опубликован.


*