
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.60] |
![]() |
|
Страницы: (6) « Первая ... 3 4 [5] 6 все ( Перейти к последнему сообщению ) |
Сообщ.
#61
,
|
|
|
Цитата DDim1000 @ Вы вкрячили непонятно что внутри namespace. Это и ни объявление функции, ни её реализация. Поэтому компилятор вас и не понял. system() или SetConsoleOutputCP() надо вызывать в main(). В добавок system() вам выдаст "мусор" в консоль "Active codepage xxxx", потому что это запуск команды cmd. Тогда уж system("chcp 65001 >nul"). |
![]() |
Сообщ.
#62
,
|
|
Ещё как вкусил. Главная проблема юникода не в много...символьности (UTF-16 тоже имеет суррогатные пары). Главная его проблема в том, что вместо того, чтобы разобраться с зоопарком мультикультурности и устранить связанные с ним неудобства, он его стандартизировал и т.с. эти неудобства узаконил.
Цитата Majestio @ Их никогда и не было. Но люди умели писать код в многобайтных кодировках. Проблема не в самой многобайтовости, а в отсутствии абстракции "символ". Это уже не к юникоду, конечно, а к std. Если уж ввели char8_t, префикс u8 и класс std::u8string, почему они по-прежнему отражают абстракцию "байт"?Да, пришли времена когда печатаемый символ может/должен занимать более одного байта Мне несложно написать свои алгоритмы и функции для "символов" и таскать их из проекта в проект. Более того, в C++11 сделали некий шаг в эту сторону, предоставив фасеты и классы. Пусть шаг и неудобный, т.к. отделён от самой абстракции "символ", но вот прошло 6 лет, а воз не то что и ныне там, а этот шаг в принципе отменён, и ничего не предоставлено взамен. Причём формулировка причины, типа, "ой, мы ниасилили сделать это безопасно с точки зрения обработки апшибков" и "ай-яй-яй, эти фасеты локале-независимы, поэтому им нечего делать в <locale>". Оттакъот. Юникоду 35 лет, к слову, и <locale> появился аж в C++98, в первой редакции Стандарта. |
![]() |
Сообщ.
#63
,
|
|
Не надо system(). Я ж упомянул программное средство:
![]() ![]() SetConsoleOutputCP(65001); |
Сообщ.
#64
,
|
|
|
Здравствуйте!
У меня снова возникла ошибка: "ссылка на неразрешенный внешний символ", другом проекте. ссылка на неразрешенный внешний символ "public: void __cdecl school::TabTest::run(void)" (?run@TabTest@school@@QEAAXXZ) в функции main. Еще такая ошибка: неразрешенных внешних элементов: 1 h-file: ![]() ![]() #pragma once #include <iostream> #include <sstream> #include <string> #include <vector> #include <locale> namespace school { // Класс-обертка для преобразования в строку class StringConverter { public: template<typename T> static std::wstring toString(T val); }; // Класс для работы со строками class MyString : public std::wstring { public: MyString(); MyString(std::wstring s); MyString(const wchar_t* s); MyString& operator=(const std::wstring& a); template<typename T> MyString& operator=(const T a); }; // Класс для работы с вектором template<typename T> class MyVector : public std::vector<T> { public: T& operator[](const size_t i); void resize(size_t new_size, const T& value = T()); }; // Класс для форматирования таблицы class TableFormatter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TableFormatter(size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header); void format(); private: void calculateMaxColumns(); void resizeRows(); void addRowNumbers(); void calculateColumnWidths(); void alignColumns(); void alignHeaders(); }; // Класс для вывода таблицы class TablePrinter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TablePrinter( size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header); void print(std::wostream& o); private: std::wstring createLine(); void printHeader(std::wostream& o); void printRows(std::wostream& o); }; // Основной класс таблицы class Tab { private: MyVector<MyVector<MyString>> m; MyVector<MyString> h; size_t CMAX = 0; public: Tab(); MyVector<MyString>& operator[](const size_t i); template<typename ... T> void head(T ... t); void formater(); friend std::wostream& operator<<(std::wostream& o, Tab& t); }; // Объявление дружественной функции std::wostream& operator<<(std::wostream& o, Tab& t); // Класс для тестирования class TabTest { public: void run(); }; } // namespace school cpp-file: ![]() ![]() #include "DataTable.h" #define l(v) std::wcout << #v << " = " << (v) << "\n"; // Класс-обертка для преобразования в строку class StringConverter { public: template<typename T> static std::wstring toString(T val) { return (std::wostringstream() << val).str(); } }; // Класс для работы со строками class MyString : public std::wstring { public: MyString() : std::wstring() {} MyString(std::wstring s) : std::wstring(s) {} MyString(const wchar_t* s) : std::wstring(s) {} MyString& operator=(const std::wstring& a) { return *static_cast<std::wstring*>(this) = a, *this; } template<typename T> MyString& operator=(const T a) { return *this = StringConverter::toString(a); } }; // Класс для работы с вектором template<typename T> class MyVector : public std::vector<T> { public: T& operator[](const size_t i) { if (i >= this->size()) this->resize(i + 1); return *(this->begin() + i); } void resize(size_t new_size, const T& value = T()) { std::vector<T>::resize(new_size, value); } }; // Класс для форматирования таблицы class TableFormatter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TableFormatter(size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header) : m(data), h(header), CMAX(cmax) { } void format() { calculateMaxColumns(); resizeRows(); addRowNumbers(); calculateColumnWidths(); alignColumns(); alignHeaders(); } private: void calculateMaxColumns() { for (const auto& e : m) if (CMAX < e.size()) CMAX = e.size(); } void resizeRows() { for (auto& e : m) if (CMAX > e.size()) e.resize(CMAX); if (CMAX > h.size()) h.resize(CMAX); } void addRowNumbers() { for (size_t r = 0; r < m.size(); ++r) { m[r][0] = StringConverter::toString(r + 1); } } void calculateColumnWidths() { std::vector<size_t> n(CMAX, 0); // Инициализация ширинами заголовков for (size_t i = 0; i < h.size() && i < CMAX; ++i) { n[i] = h[i].size(); } // Нахождение максимальных ширин for (size_t c = 0; c < CMAX; ++c) { for (size_t r = 0; r < m.size(); ++r) { if (n[c] < m[r][c].size()) n[c] = m[r][c].size(); } } // Выравнивание столбцов for (size_t c = 0; c < CMAX; ++c) { for (size_t r = 0; r < m.size(); ++r) { if (n[c] > m[r][c].size()) m[r][c].resize(n[c], ' '); } } // Выравнивание заголовков for (size_t c = 0; c < CMAX; ++c) { if (h[c].size() < m[0][c].size()) h[c].resize(m[0][c].size(), ' '); } } void alignColumns() {} // Заглушка для совместимости с логикой void alignHeaders() {} // Заглушка для совместимости с логикой }; // Класс для вывода таблицы class TablePrinter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TablePrinter( size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header) : CMAX(cmax), m(data), h(header) { } void print(std::wostream& o) { std::wstring line = createLine(); o << line << '\n'; printHeader(o); o << '\n' << line << '\n'; printRows(o); o << line << '\n' << '\n'; } private: std::wstring createLine() { std::wstring line; for (size_t c = 0; c < CMAX; ++c) { line += std::wstring(h[c].size() + 3, '='); } return line; } void printHeader(std::wostream& o) { for (size_t c = 0; c < CMAX; ++c) { o << ' ' << h[c] << " |"; } } void printRows(std::wostream& o) { for (const auto& r : m) { for (const auto& e : r) { o << ' ' << e << " |"; } o << '\n'; } } }; // Основной класс таблицы class Tab { private: MyVector<MyVector<MyString>> m; MyVector<MyString> h; size_t CMAX = 0; public: Tab() = default; MyVector<MyString>& operator[](const size_t i) { if (i >= m.size()) m.resize(i + 1); return *(m.begin() + i); } template<typename ... T> void head(T ... t) { (h.push_back(StringConverter::toString(t)), ...); } void formater() { TableFormatter formatter(CMAX, m, h); formatter.format(); } friend std::wostream& operator<<(std::wostream&, Tab&); }; std::wostream& operator<<(std::wostream& o, Tab& t) { t.formater(); TablePrinter printer(t.CMAX, t.m, t.h); printer.print(o); return o; } ///----------------------------------------------------------------------------| /// Тест. ///----------------------------------------------------------------------------: class TabTest { public: void run() { ///-----------------------| /// Создаём табулятор. | ///-----------------------: Tab tab; ///-----------------------| /// Заголовок. | ///-----------------------: tab.head(L"NN", L"Первый", L"Второй", 3); ///-----------------------| /// Как угодно заполняем. | ///-----------------------: tab[1][1] = 2020; tab[2][2] = "qwerty"; tab[4][3] = 3.14; tab[0][4] = L"Яша + Оля"; ///-----------------------| /// Вывод на экран/файл. | ///-----------------------: std::wcout << tab; tab[2][4] = 2025; tab[3][5] = 'A'; std::wcout << tab; } }; source.cpp: ![]() ![]() #include "DataTable.h" using namespace school; ///----------------------------------------------------------------------------| /// Старт. ///----------------------------------------------------------------------------: int main() { setlocale(0, ""); TabTest test; test.run(); return 0; } |
![]() |
Сообщ.
#65
,
|
|
Ну так класс TabTest объявлен в пространстве имён school. Тот, что определён в глобальном, то другой, получается, они не совпадают.
|
![]() |
|
|
Цитата Qraizer @ Ну так класс TabTest объявлен в пространстве имён school. Тот, что определён в глобальном, то другой, получается, они не совпадают. То есть, и заголовки и реализаци дожны находиться в одном прострастве имен? |
![]() |
|
|
Я разместил код в прострастве имен school, и у меня вылезло куча ошибо. Почемиу?
![]() ![]() #include "DataTable.h" namespace school { #define l(v) std::wcout << #v << " = " << (v) << "\n"; // Класс-обертка для преобразования в строку class StringConverter { public: template<typename T> static std::wstring toString(T val) { return (std::wostringstream() << val).str(); } }; // Класс для работы со строками class MyString : public std::wstring { public: MyString() : std::wstring() {} MyString(std::wstring s) : std::wstring(s) {} MyString(const wchar_t* s) : std::wstring(s) {} MyString& operator=(const std::wstring& a) { return *static_cast<std::wstring*>(this) = a, *this; } template<typename T> MyString& operator=(const T a) { return *this = StringConverter::toString(a); } }; // Класс для работы с вектором template<typename T> class MyVector : public std::vector<T> { public: T& operator[](const size_t i) { if (i >= this->size()) this->resize(i + 1); return *(this->begin() + i); } void resize(size_t new_size, const T& value = T()) { std::vector<T>::resize(new_size, value); } }; // Класс для форматирования таблицы class TableFormatter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TableFormatter(size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header) : m(data), h(header), CMAX(cmax) { } void format() { calculateMaxColumns(); resizeRows(); addRowNumbers(); calculateColumnWidths(); alignColumns(); alignHeaders(); } private: void calculateMaxColumns() { for (const auto& e : m) if (CMAX < e.size()) CMAX = e.size(); } void resizeRows() { for (auto& e : m) if (CMAX > e.size()) e.resize(CMAX); if (CMAX > h.size()) h.resize(CMAX); } void addRowNumbers() { for (size_t r = 0; r < m.size(); ++r) { m[r][0] = StringConverter::toString(r + 1); } } void calculateColumnWidths() { std::vector<size_t> n(CMAX, 0); // Инициализация ширинами заголовков for (size_t i = 0; i < h.size() && i < CMAX; ++i) { n[i] = h[i].size(); } // Нахождение максимальных ширин for (size_t c = 0; c < CMAX; ++c) { for (size_t r = 0; r < m.size(); ++r) { if (n[c] < m[r][c].size()) n[c] = m[r][c].size(); } } // Выравнивание столбцов for (size_t c = 0; c < CMAX; ++c) { for (size_t r = 0; r < m.size(); ++r) { if (n[c] > m[r][c].size()) m[r][c].resize(n[c], ' '); } } // Выравнивание заголовков for (size_t c = 0; c < CMAX; ++c) { if (h[c].size() < m[0][c].size()) h[c].resize(m[0][c].size(), ' '); } } void alignColumns() {} // Заглушка для совместимости с логикой void alignHeaders() {} // Заглушка для совместимости с логикой }; // Класс для вывода таблицы class TablePrinter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TablePrinter( size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header) : CMAX(cmax), m(data), h(header) { } void print(std::wostream& o) { std::wstring line = createLine(); o << line << '\n'; printHeader(o); o << '\n' << line << '\n'; printRows(o); o << line << '\n' << '\n'; } private: std::wstring createLine() { std::wstring line; for (size_t c = 0; c < CMAX; ++c) { line += std::wstring(h[c].size() + 3, '='); } return line; } void printHeader(std::wostream& o) { for (size_t c = 0; c < CMAX; ++c) { o << ' ' << h[c] << " |"; } } void printRows(std::wostream& o) { for (const auto& r : m) { for (const auto& e : r) { o << ' ' << e << " |"; } o << '\n'; } } }; // Основной класс таблицы class Tab { private: MyVector<MyVector<MyString>> m; MyVector<MyString> h; size_t CMAX = 0; public: Tab() = default; MyVector<MyString>& operator[](const size_t i) { if (i >= m.size()) m.resize(i + 1); return *(m.begin() + i); } template<typename ... T> void head(T ... t) { (h.push_back(StringConverter::toString(t)), ...); } void formater() { TableFormatter formatter(CMAX, m, h); formatter.format(); } friend std::wostream& operator<<(std::wostream&, Tab&); }; std::wostream& operator<<(std::wostream& o, Tab& t) { t.formater(); TablePrinter printer(t.CMAX, t.m, t.h); printer.print(o); return o; } ///----------------------------------------------------------------------------| /// Тест. ///----------------------------------------------------------------------------: class TabTest { public: void run() { ///-----------------------| /// Создаём табулятор. | ///-----------------------: Tab tab; ///-----------------------| /// Заголовок. | ///-----------------------: tab.head(L"NN", L"Первый", L"Второй", 3); ///-----------------------| /// Как угодно заполняем. | ///-----------------------: tab[1][1] = 2020; tab[2][2] = "qwerty"; tab[4][3] = 3.14; tab[0][4] = L"Яша + Оля"; ///-----------------------| /// Вывод на экран/файл. | ///-----------------------: std::wcout << tab; tab[2][4] = 2025; tab[3][5] = 'A'; std::wcout << tab; } }; }; Прикреплённая картинка
|
Сообщ.
#68
,
|
|
|
Вам же Qraizer сказал.
Объявление и реализация должны быть в одном namespace. в cpp файле так же должно быть указано namespace school { Тут должна быть вся реализация и объявления классов } Зы. Таки все объявления классов StringConverter, MyString, MyVector и т.д. я бы перенес в .h Выглядит очень некрасиво. |
Сообщ.
#69
,
|
|
|
Цитата sharky72 @ Вам же Qraizer сказал. Объявление и реализация должны быть в одном namespace. А у меня разве не в одном namespace? |
Сообщ.
#70
,
|
|
|
Цитата DDim1000 @ Цитата sharky72 @ Вам же Qraizer сказал. Объявление и реализация должны быть в одном namespace. А у меня разве не в одном namespace? Неа. Я не вижу namespace school {) в cpp и внутри все что должно ему принадлежать .h ![]() ![]() namespace mynamespace { class classname { void method1(); void method2(); } void function(); } .cpp ![]() ![]() namespace mynamespace { void classname::method1(){} void classname::method2(){} void function(){} } |
![]() |
|
|
![]() |
Сообщ.
#72
,
|
|
Так не нужно же дублировать определения. Отдельно, в .cpp, определять нужно только то, что в .h было только объявлено. (В свою очередь в .h определять нужно типы и inline, остальное должно быть только объявлено, а определено в .cpp)
|
Сообщ.
#73
,
|
|
|
Ну я же не вижу где находится ваш класс Tab и судя по ошибке его нет в данном namespace. Не говоря о том что по скрину MyString и MyVector, StringConverter определены как в .h так и в .cpp поэтому ошибка двойного определения С2011
Не надо выкладывать скрины. Либо выкладывайте проект, либо заворачивайте в /code. С телефона смотреть не всегда удобно, не говоря о том что скрин показывает только часть кода. Как должны выглядеть объявление и реализация я вам написал. |
![]() |
Сообщ.
#74
,
|
|
Например, класс TabTest не содержит inline методов, поэтому определён правильно: метод TabTest::run() только объявлен. Но определение в .cpp должно быть только для метода:
![]() ![]() namespace school { /* ... */ ///----------------------------------------------------------------------------| /// Тест. ///----------------------------------------------------------------------------: void TabTest::run() { /* ... */ } } Добавлено P.S. Если ранее писал на Джаве (Шарпы, мэйби?), то в Плюсах так тоже можно, но не приветствуется. Только в отдельных случаях |
Сообщ.
#75
,
|
|
|
Я так понял, что у меня пробле с загаловками? Потому что в одном файле все работает.
Source.cpp: ![]() ![]() #include <iostream> #include <sstream> #include <string> #include <vector> #include <locale> #define l(v) std::wcout << #v << " = " << (v) << "\n"; // Класс-обертка для преобразования в строку class StringConverter { public: template<typename T> static std::wstring toString(T val) { return (std::wostringstream() << val).str(); } }; // Класс для работы со строками class MyString : public std::wstring { public: MyString() : std::wstring() {} MyString(std::wstring s) : std::wstring(s) {} MyString(const wchar_t* s) : std::wstring(s) {} MyString& operator=(const std::wstring& a) { return *static_cast<std::wstring*>(this) = a, *this; } template<typename T> MyString& operator=(const T a) { return *this = StringConverter::toString(a); } }; // Класс для работы с вектором template<typename T> class MyVector : public std::vector<T> { public: T& operator[](const size_t i) { if (i >= this->size()) this->resize(i + 1); return *(this->begin() + i); } void resize(size_t new_size, const T& value = T()) { std::vector<T>::resize(new_size, value); } }; // Класс для форматирования таблицы class TableFormatter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TableFormatter(size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header) : m(data), h(header), CMAX(cmax) { } void format() { calculateMaxColumns(); resizeRows(); addRowNumbers(); calculateColumnWidths(); alignColumns(); alignHeaders(); } private: void calculateMaxColumns() { for (const auto& e : m) if (CMAX < e.size()) CMAX = e.size(); } void resizeRows() { for (auto& e : m) if (CMAX > e.size()) e.resize(CMAX); if (CMAX > h.size()) h.resize(CMAX); } void addRowNumbers() { for (size_t r = 0; r < m.size(); ++r) { m[r][0] = StringConverter::toString(r + 1); } } void calculateColumnWidths() { std::vector<size_t> n(CMAX, 0); // Инициализация ширинами заголовков for (size_t i = 0; i < h.size() && i < CMAX; ++i) { n[i] = h[i].size(); } // Нахождение максимальных ширин for (size_t c = 0; c < CMAX; ++c) { for (size_t r = 0; r < m.size(); ++r) { if (n[c] < m[r][c].size()) n[c] = m[r][c].size(); } } // Выравнивание столбцов for (size_t c = 0; c < CMAX; ++c) { for (size_t r = 0; r < m.size(); ++r) { if (n[c] > m[r][c].size()) m[r][c].resize(n[c], ' '); } } // Выравнивание заголовков for (size_t c = 0; c < CMAX; ++c) { if (h[c].size() < m[0][c].size()) h[c].resize(m[0][c].size(), ' '); } } void alignColumns() {} // Заглушка для совместимости с логикой void alignHeaders() {} // Заглушка для совместимости с логикой }; // Класс для вывода таблицы class TablePrinter { private: MyVector<MyVector<MyString>>& m; MyVector<MyString>& h; size_t& CMAX; public: TablePrinter( size_t& cmax, MyVector<MyVector<MyString>>& data, MyVector<MyString>& header) : CMAX(cmax), m(data), h(header) { } void print(std::wostream& o) { std::wstring line = createLine(); o << line << '\n'; printHeader(o); o << '\n' << line << '\n'; printRows(o); o << line << '\n' << '\n'; } private: std::wstring createLine() { std::wstring line; for (size_t c = 0; c < CMAX; ++c) { line += std::wstring(h[c].size() + 3, '='); } return line; } void printHeader(std::wostream& o) { for (size_t c = 0; c < CMAX; ++c) { o << ' ' << h[c] << " |"; } } void printRows(std::wostream& o) { for (const auto& r : m) { for (const auto& e : r) { o << ' ' << e << " |"; } o << '\n'; } } }; // Основной класс таблицы class Tab { private: MyVector<MyVector<MyString>> m; MyVector<MyString> h; size_t CMAX = 0; public: Tab() = default; MyVector<MyString>& operator[](const size_t i) { if (i >= m.size()) m.resize(i + 1); return *(m.begin() + i); } template<typename ... T> void head(T ... t) { (h.push_back(StringConverter::toString(t)), ...); } void formater() { TableFormatter formatter(CMAX, m, h); formatter.format(); } friend std::wostream& operator<<(std::wostream&, Tab&); }; std::wostream& operator<<(std::wostream& o, Tab& t) { t.formater(); TablePrinter printer(t.CMAX, t.m, t.h); printer.print(o); return o; } ///----------------------------------------------------------------------------| /// Тест. ///----------------------------------------------------------------------------: class TabTest { public: void run() { ///-----------------------| /// Создаём табулятор. | ///-----------------------: Tab tab; ///-----------------------| /// Заголовок. | ///-----------------------: tab.head(L"NN", L"Первый", L"Второй", 3); ///-----------------------| /// Как угодно заполняем. | ///-----------------------: tab[1][1] = 2020; tab[2][2] = L"qwerty"; tab[4][3] = 3.14; tab[0][4] = L"Яша + Оля"; ///-----------------------| /// Вывод на экран/файл. | ///-----------------------: std::wcout << tab; tab[2][4] = 2025; tab[3][5] = L'A'; std::wcout << tab; } }; ///----------------------------------------------------------------------------| /// Старт. ///----------------------------------------------------------------------------: int main() { setlocale(0, "ru"); TabTest test; test.run(); return 0; } |