Всем доброго времени суток. На связи Алексей Гулынин. В данной статье я хотел бы рассказать о форматировании вывода в C# . При создании консольных приложений мы часто пользуемся статическим методом WriteLine() из класса Console . Напишем простой пример, который выводит информацию о человеке (имя, фамилия, возраст). С амый простой вариант вывода данной строки выглядит следующим образом:
string name = «Ivan» ;
string surname = «Ivanov» ;
Выводить в таком виде строки бывает неудобно. Существует перегруженная форма метода WriteLine() :
В данной форме аргументы разделяются запятой, а не знаком конкатенации строк «+». Вся форматирующая строка состоит символов, которые будут выводиться на экран в неизменном виде и спецификаторов формата, которые указываются в фигурных скобках. На их место будут подставляться аргументы, которые идут через запятую.
Также при выводе можно указывать ширину полей, при этом неиспользуемые части полей будут заполнены пробелами:
Что такое ascii символы. ascii что это такое? Таблица ascii c++. C ++ Для начинающих. Урок #62
Также форматировать вывод можно с помощью спецификатора «t». Приведу классический пример таблицы результатов возведения числе в квадрат и куб:
for ( int i = 1; i < 10; i++)
Console.WriteLine( «tt» , i, Math.Pow(i,2), Math.Pow(i, 3));
Наиболее распространенная задача: это ограничить количество символов после запятой у десятичных типов. В данном случае это можно сделать следующим образом:
Console.WriteLine( «10 / 3 = » , 10.0 / 3.0);
Console.WriteLine( «10 / 3 = » , 10.0 / 3.0);
В данном случае будет выведено всего 3 знака после запятой. Символ «#» обозначает разряды чисел. Шаблон «» указывает методу WriteLine() , что необходимо отобразить два десятичных разряда в дробной части выводимого значения.
- Замер времени работы кода
- Форматированный вывод в C#
- Интерфейсы IEnumerable и IEnumerator
- Тернарный оператор
- Генерация одинаковых чисел RANDOM
- Вывод таблицы в консоль
- Методы расширения
- Вычитание массивов
- Удаление пустых элементов из массива
- Замена определенного текста в файле .txt
- Split, разделение строки на массив
- Сравнение собственных классов
- Сотрировка списка по нескольким полям
- Cортировка в GridView по нескольким столбцам
- Случайная Дата
- Добавление сниппетов в VS
- Count или Count()
- Parse или TryParse
- Асинхронные методы в GUI
- Using + IDisposable
- If в одну строку
- Форматирование DateTime
- Метод уничтожения объекта (Object.Finalize)
- Сохранение методов в словаре, что бы использовать их как команды
- Проверка на null
- Откинуть цифры после запятой c#
Источник: webhamster.ru
Простейшие формы ввода данных в Excel за пару секунд – без применения VBA!
4.2. Вычисление и вывод данных в виде таблицы
Простейшими примерами применения операторов цикла на практике являются программы вычисления значений функций при изменяющихся значениях аргумента и вывода данных в виде таблиц с заголовками. В качестве аргумента обычно выступает Ю. Е. Алексеев, А. В. Куров «Практикум по программированию на языке C в среде VS C++» Оглавление
73 переменная, изменяющаяся в цикле по требуемому закону. Она может быть как дополнительным, так и основным параметром в циклах for , while и do while . При работе с вещественными данными необходимо иметь в виду, что их значения могут представляться с ошибкой, что эти ошибки могут зависеть от типа переменных, накапливаться при выполнении арифметических операций и приводить к непредусмотренному программистом выполнению программы. Рассмотрим два фрагмента программы вывода таблицы значений аргумента и функции, где аргумент — дополнительный параметр в цикле является вещественной переменной с именем Х: 1) float X,H,Xk; //Все переменные типа float . . . X=0.0; H=1.0/3.0; Xk=5.0/3.0;; //==1.6(6) while (X <=Xk) < printf( «n%6.2f %8.2f» , X,sin(X)); X=X+H; >Результат выполнения: 0.00 0.00 0.33 0.33 0.67 0.62 1.00 0.84 1.33 0.97 2) H=1.0/3.0; X=-H; Xk=5.0/3.0; do < X=X+H; printf( «n%6.2f %8.2f» , X,sin(X)); >while (X!=Xk); Ю. Е. Алексеев, А. В. Куров «Практикум по программированию на языке C в среде VS C++» Оглавление
74 Казалось бы, оба фрагмента выведут на экран таблицы значений синуса для аргумента Х, изменяющегося от 0 до 5/3 включительно с шагом 1/3. Но в действительности первый фрагмент не выведет значения 5/3 и sin(5/3), а второй не обеспечит завершение выполнения цикла при Х равном 5/3, так что цикл продолжит выполняться и при больших значениях Х. Во избежание подобных ситуаций следует вместо проверок вещественных данных на равенство использовать проверки на < (меньше) и/или >(больше) с некоторым достаточно малым запасом, превышающим точность представления чисел данного типа и не нарушающим логику работы программы. Например, рассмотренные фрагменты программы можно изменить так 1) float X,H,Xk; //Все переменные типа float . . . X=0.0; H=1.0/3.0; Xk=5.0/3.0+H/2.0; while (X Результат выполнения: 0.00 0.00 0.33 0.33 0.67 0.62 1.00 0.84 1.33 0.97 1.67 1.00 2) H=1.0/3.0; X=-H; //Запас в H/2.0 больше ошибки Ю. Е. Алексеев, А. В. Куров «Практикум по программированию на языке C в среде VS C++» Оглавление
75 //представления вещественных чисел Xk=5.0/3.0-H/2.0; do < X=X+H; printf( «n%6.2f %8.2f» , X,sin(X)); >while (X
Для этого потребуется заранее вычислить, сколько раз цикл должен выполняться, воспользовавшись формулой N = X 1 − X 0 + 1, H где N – искомое число повторений цикла, X0 и X1 – начальное и конечное значения аргумента, H – шаг изменения аргумента, а cкобки ] [ в формуле обозначают округление. Округление вещественного числа можно получить, добавив к нему 0,5 и применив к результату библиотечную функцию ceil (она возвращает наименьшее целое, не меньшее аргумента), или вычев из него 0,5 и применив к результату библиотечную функцию floor (она возвращает наибольшее целое, не большее аргумента). Дополним условие задачи требованием сохранения значений аргумента и функции в массивах и вычисление очередного значения аргумента не методом накопления суммы, а умножением параметра цикла на шаг приращения аргумента. Так как в нашем случае Х0=0, Х1=5/3 и H=1/3 , фрагмент программы с циклом for будет следующим float X,H,Xk; //Все переменные типа float float x[6], y[6]; //Мссивы для сохранения значений //аргумента и функции int i,N; . . . Ю. Е. Алексеев, А. В. Куров «Практикум по программированию на языке C в среде VS C++» Оглавление
Источник: studfile.net
Вывод табличных данных в консоль, файл или MS Excel в стиле потоков C++
В заметке предлагается набор классов C++ (работоспособность проверена в VS2008 и VS 2013; используется только С++03 и STL) для вывода в поток std::ostream данных с табличным форматированием. Распространяется «As Is».
st ; for (int i = 0; i
Результат будет выглядеть так:
Уже в процессе подготовки заметки нашел похожий проект bprinter (подробного сравнения не проводил; прослеживается зависимость от Boost::Spirit, что не всегда удобно), который является аналогом моего файла
StreamTable.h
#ifndef __STREAM_TABLE_H #define __STREAM_TABLE_H #undef max #undef min #include #include #include #include //стратегия формирования единой таблицы #define CRLF «n» //стратегия построчной выгрузки таблицы //#define CRLF std::endl /** * Прямоугольная таблица с разделителями строк и столбцов * Синтаксис как у потоков C++ */ class StreamTable < public: std::ostream &os_; StreamTable(std::ostream >virtual ~StreamTable() <> virtual std::ostream return os_; >//отображать внешние границы? void MakeBorderExt(bool on) < borderExtOn_ = on; >//символ разделителя строк void SetDelimRow(bool delimOn, char delimRow = ‘ ‘) < delimRowOn_ = delimOn; if (delimRowOn_) delimRow_ = delimRow; else if (!delimColOn_) MakeBorderExt(false); >//символ разделителя столбцов void SetDelimCol(bool delimOn, char delimCol = ‘ ‘) < delimColOn_ = delimOn; if (delimColOn_) delimCol_ = delimCol; else if (!delimRowOn_) MakeBorderExt(false); >int AddCol(int colWidth, bool visible = true) < colWidth_.push_back(colWidth); visible_.push_back(visible); return colWidth_.back(); >void SetVisible(int col, bool flg) < visible_[col — 1] = flg; >void SetCols(int colCount, int colWidth = 0) < Clear(); for (int ic = 0; ic < colCount; ic++) < AddCol(colWidth); >> virtual void Clear() < colWidth_.clear(); visible_.clear(); colIndex_ = 0; firstCell_ = 1; >void AddEmptyRow() < for (int ic = 0; ic < (int)colWidth_.size(); ic++) < *this > template StreamTable operator StreamTable private: bool borderExtOn_; bool delimRowOn_; char delimRow_; bool delimColOn_; char delimCol_; std::vector colWidth_; bool firstCell_; std::vector visible_; template void Push(const T if (firstCell_) < if (borderExtOn_) MakeRowBorder(); firstCell_ = 0; >if (visible_[colIndex_]) < DelimCol(); os_.width(colWidth_[colIndex_]); os_.fill(‘ ‘); os_ if (++colIndex_ == (int)colWidth_.size()) < DelimCol(); if (delimRowOn_) MakeRowBorder(); else os_ > void MakeRowBorder() < os_ > os_ void DelimCol() < if (delimColOn_ (borderExtOn_ || colIndex_)) os_ //запрет на копирование StreamTable ); >; #endif // __STREAM_TABLE_H
Класс StreamTable позволяет построчно выводить табличные данные в формате потоков С++. Принимает в конструкторе ссылку на std::ostream, так что помимо std::cout (по-умолчанию) можно осуществлять запись в файл, передав std::ofstream StreamTable.h» void TestStreamTable1() < StreamTable st(std::cout); st.AddCol(5); st.AddCol(15); st.AddCol(10); st.AddCol(10); //разкомментировать, если столбцы имеют одинаковую толщину //st.Clear(); //st.SetCols(4, 10); //st.SetVisible(1, false);//столбцы можно скрывать st.MakeBorderExt(true); st.SetDelimRow(true, ‘-‘);//st.SetDelimRow(false);//без символов-разделителей строк st.SetDelimCol(true, ‘|’);//st.SetDelimCol(false);//без символов-разделителей строк //заголовок и значения выводятся одинаково st ; for (int i = 0; i < nr; i++) < st >
Для возможности использования StreamTable для выгрузки в MS Excel был реализован специальный поток excelstream и вспомогательный класс для работы с MS Excel:
Файл MSExcel.h
#pragma once #include #import «C:Program Files (x86)Common FilesMicrosoft SharedOffice12MSO.DLL» rename(«RGB»,»_RGB») rename(«DocumentProperties», «_DocumentProperties») rename(«SearchPath»,»_SearchPath») #import «C:Program Files (x86)Common FilesMicrosoft SharedVBAVBA6VBE6EXT.OLB» #import «C:Program Files (x86)Microsoft OfficeOffice12EXCEL.EXE» rename(«DialogBox»,»_DialogBox») rename(«RGB»,»_RGB») rename(«CopyFile», «_CopyFile») rename(«ReplaceText», «_ReplaceText») no_auto_exclude #define THROW(msg) throw std::exception(msg); /** * */ class ExcelLoader < public: virtual ~ExcelLoader() < Close(); >Excel::_ApplicationPtr excel_; Excel::_WorksheetPtr sheet_; Excel::RangePtr range_; //отвязываение от Excel, чтобы решение о закрытии и сохранении принял пользователь void Detach() < if (!excel_) return; range_.Detach(); range_ = 0; sheet_.Detach(); sheet_ = 0; excel_.Detach(); excel_ = 0; ::CoUninitialize(); >//закрывает без сохранения ранее открытую книгу через LoadExcel void Close() < if (!excel_) return; try < excel_->DisplayAlerts[0] = false; excel_->Quit(); excel_->DisplayAlerts[0] = true; Detach(); //todo: с MS Excel 2010 обнаружилось, что CoUninitialize не всегда закрывает процесс std::system(«taskkill /F /IM Excel.exe»); //ожидаем закрытия процесса EXCEL while (FindWindow(«XLMAIN», NULL)) <>; > catch (_com_error THROW(er.ErrorMessage()); >> //сохраняет ранее открытую книгу через LoadExcel void Save() < if (!excel_) return; excel_->DisplayAlerts[0] = false; try < excel_->Save(); > catch (_com_error THROW(er.ErrorMessage()); >excel_->DisplayAlerts[0] = true; > //инстанцирует Excel и открывает лист с индексом ws_index (>= 1) в книге fname void LoadExcel(const std::string if (FAILED(::CoInitialize(NULL))) THROW(«CoInitialize failure»); if (FAILED(excel_.CreateInstance(«Excel.Application»))) < std::stringstream ss; ss excel_->Visible[0] = TRUE; Excel::_WorkbookPtr book = excel_->Workbooks->Open(fname.c_str()); if (!book) THROW(std::string(«Can’t open «).append(fname).append(«: Workbooks->Open method failed»).c_str()); sheet_ = excel_->ActiveSheet; if (ws_index < 1 || excel_->Sheets->Count < ws_index) THROW(«ws_index_ must be in [1, Sheets.Count]»); sheet_ = excel_->Sheets->Item[ws_index]; if (!sheet_) THROW(«Failed to get a pointer to the active sheet»); range_ = sheet_->Cells; if (!range_) THROW(«Failed to get a pointer to the cells on the active sheet»); > >;
Файл ExcelStream.h
#pragma once #include #include «MSExcel.h» typedef char CharT; typedef std::char_traits TraitsT; class excel_stringbuf : public std::basic_stringbuf < public: static const char colDelim = ‘t’; static const char rowDelim = ‘n’; virtual ~excel_stringbuf() < sync(); >void SetRange(Excel::RangePtr pRange, int irow_offset, int icol_offset) < rng_ = pRange; //запись будем производить из верхнего левого узла листа irow_ = irow_offset; icol_offset_ = icol_offset; icol_ = icol_offset; >Excel::RangePtr GetRange() const < return rng_; >int return irow_; >int return icol_; >int sync() < output_string(str().c_str()); str(std::basic_string());//очистка текстового буфера return 0; > protected: Excel::RangePtr rng_; int irow_; int icol_offset_; int icol_; //в отличие от библиотечной isspace не учитывает пробел в качестве разделителя bool IsSpace(char c) const < return (c == colDelim) || (c == rowDelim) || (c == ‘r’); >/** * Записывает строку s в файл Excel. * При этом признаком перехода к следующему столбцу является символ ‘t’, * а к следующей строке — ‘n’. * Пример: строка вида «1t2n3t4 5» будет записана в виде * (1,1) = 1 * (1,2) = 2 * (2,1) = 3 * (2,2) = 4 5, * где (i,j) — координаты ячейки * todo: добавить обработку переполнения количества строк/столбцов */ void output_string(const std::string >; void excel_stringbuf::output_string(const std::string //плавающий указатель на символы строки, отличные от пробельных (n t) std::string::const_iterator be = s.begin(); std::string::const_iterator en = s.end(); std::string::const_iterator it = be; while (it != en) < bool dump = false; bool isTab = false; bool isEnd = false; //если встретился символ перевода столбца или строки определяем, //необходимо ли произвести запись в текущую ячейку (iRow, iCol) if (*it == colDelim) < isTab = true; dump = !IsSpace(*be); >else if (*it == rowDelim) < isEnd = true; dump = !IsSpace(*be); >else < //как только встретился не разделительный символ, выставить на него be if (IsSpace(*be)) be = it; if (it + 1 == en) < //прочли последний символ и он не пробельный dump = true; //при записи в ячейку предполагается, что //it указывает на разделительный символ it = en; >> if (dump) < //записать в текущую ячейку часть строки из промежутка [be, it) const std::string rng_->Item[irow_][icol_] = _variant_t(item.c_str()); > //обновляем координаты положения в файле следующей строки if (isTab) < icol_++; be = it; >else if (isEnd) < irow_++; icol_ = icol_offset_; be = it; >if (it == en) < //достигли конца строки break; >else it++; > > /** * Класс для записи в Excel с синтаксисом как у STL потоков */ class excelstream : public std::basic_ostream < public: excelstream(Excel::RangePtr buf_) < buf_.SetRange(rng, irow_offset, icol_offset); >virtual ~excelstream() < flush(); >private: excel_stringbuf buf_; >;
Внимание, поскольку в MSExcel.h используется #import, то для компиляции необходимо прописать актуальные пути к MSO.DLL, VBE6EXT.OLB, EXCEL.EXE в соответствии с установленной версией MS Office.
Поток excelstream в составе StreamTable работает таким образом, что его буфер парсит строку выгрузки, в которой символ ‘t’ интерпретируется как переход к столбцу вправо, а ‘n’ — как символ перехода на следующую строку. Пример ниже аналогичен TestStreamTable2 по результату и показывает принцип формирования такой строки.
Файл со всеми примерами main.cpp
В заключение отмечу, что в отношении excelstream не проверялась его работа как полиморфного указателя на std::ostream, поэтому в этой части класс следует дорабатывать.
Источник: habr.com