- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
void File::open(string file, bool readAccess, bool writeAccess, bool append)
{
Close();
(string&)Name=file;
const char* const modes[2][2][2]={{{null, "rb"}, {"wb", "w+b"}}, {{null, null}, {"ab", "a+b"}}};
if(modes[append][writeAccess][readAccess]==null) return InternalError("Создание файла с неверными параметрами!");
handle=fopen(Name.CStr(), modes[append][writeAccess][readAccess]);
if(handle==null) throw NotFoundException(string::Format("Файл <^> не найден!")(file));
}
Скорее всего, этот код вам покажется странным, поэтому я его выкладываю. Хотя я его говнокодом не считаю и он мне даже нравится.
fdw = open(argv[2], O_RDWR|O_CREAT |O_SYNC|O_TRUNC, 0600);
Там и оставайтесь. Портировать не обязательно.
ИМХО: помимо 2k и ХPюши, про всё остальное не чокаясь.
остальные редакции лень искать
2) std::stream(name, std::ios_base::out|std::ios_base::bin|st d::ios_base::app) vs fopen(name, "a+b") vs myfile.open(name, false, true, true) сравни читабельность
3) modes - почему не статик?
4) зачем нужно аргументу file добавлять еще одно имя Name
5) я уж не говорю о своих классах строки, враппером над FILE * и т.д.
2. Эта функция используется внутри класса файла. Пользователь пользуется классами File::Reader и File::Writer, в которых всё читабельно.
3. Да, наверное, надо сделать static. Только оптимизировать производительность здесь и на таких мелочах нет смысла.
4. Name - это константный член класса, в котором хранится путь к файлу. (string&) - это приведение к неконстантной ссылке - способ изменения константы - такая хитрая реализация свойств только для чтения.
5. defecate-STL. Своё мне больше нравится.
2. раз пользователь пользуется чем то иным, вот это иное сюда и надо спокойно передать
4. это говнокод
и да, разницу в передаче аргументов по копии и по ссылке ведь понимаешь?
2. В "ином" коде нет ничего интересного.
4. Он запрятан внутрь, а снаружи он только улучшает код, позволяя избавиться от кучи геттеров.
Мой класс string использует счётчик ссылок и копируется только при записи.
если у тебя нет сеттера, тогда какая разница? выглядит плохо
> Мой класс string использует счётчик ссылок
т.е. на operator [] возвращает объект MyStringCharRef, как в кутэ?
Что лучше: использовать геттер engine->GetObjectCount() или обращаться напрямую engine->ObjectCount? ObjectCount объявлена как const int, но трюк с приведением к ссылке позволяет устанавливать его. Используется он только внутри класса Engine.
>т.е. на operator [] возвращает объект MyStringCharRef, как в кутэ?
Нет, он только для чтения. Устанавливает конкретный символ функцией SetChar.
Правка: это вопрос.
компилятор с++ в случае будет юзать не константный operator []
потому в stl строки не страдают ерундой с COW, обеспечивая минимальный интерфейс общего назначения (ну и плюс в стандарте 98/03 никто не обговаривал средства обеспечения атомарности), а для QT, где объекты строк за свою жизнь тысячи раз куда то копируются из ядра на экран, не западло переписать класс строки, чтобы по operator [] возвращать специальный объект "символ", на модификации которого тот уже будет считать ссылки и копировать родительскую строку
засуммонь борманда
всё, что я вижу в сорцах
т.е. это не даст передать как QChar & куда-нибудь
Именно так.
Во-первых QChar юникодный и в char все равно не влезет, разве что в wchar_t.
Во-вторых, как правильно заметил defecate++, в QChar& он тоже не кастуется.
В третьих - а оно нужно? У QString удобный интерфейс и посимвольное обращение к строкам требуется редко.
No comments. Во время чтения этой строки у меня возник необъяснимый приступ агрессии.
с опытом как-нибудь придёт - время лечит
Как сказал мудрый человек - "программист на фортране может писать на любом языке... как на фортране".
Перенести все идиомы c# в c++ (да и в обратную сторону тоже) не получится - совершенно другая архитектура, и большая часть портированного кода будет смотреться как нечто инородное (если не как говно)...
Если для ваших задач удобнее c#, то вы приняли совершенно правильное решение, перейдя на него.
Только я с C++ и начинал. От C# и D я потом всего этого нахватался и захотел перевести на C++.
в сравнении с выводом напрямую
когда то давно пробегала ссылка на сравнение sscanf, atof, istream и boost::spirit::qi
не могу найти
P.S. Посравнивал на простеньком примере с числом, хекс числом выровненным под 8 знакомест, и строкой скорости вывода. fprintf самый быстрый. ofstream раз в 5 медленее. QTextStream еще в 4 раза медленее (что в принципе логично - у него все-таки кодек из юникода на выхлопе).
http://bit.ly/LwiPpv
в разы
Да, stringstream медленнее sprintf в разы.
cout медленнее printf\puts при выводе готовой строки в десятки раз! По крайней мере, в студии. Возьмите строчку подлиннее и сами попробуйте.
std::cout << bigString << std::endl;
3.80с на вывод миллиона строк
printf("%s\n", bigString);
1.02c на вывод миллиона строк
Парой постов выше тестировал на более-менее сложном примере - число, шестнадцатеричное число, и строка - iostream был раз в 5 медленее fprintf.
Ну т.е не десятки раз это, а разы.
Виртуалку поднимать, экспресс эдишн качать... лень короче.
> Сейчас ещё раз попробую, чтобы время замерить...
Оки, скинь тогда код, на котором будет проведено тестирование. Откомпилю его в gcc для сравнения.
without locale
cout: 545 milliseconds
printf: 8 milliseconds
with locale
cout: 566 milliseconds
printf: 461 milliseconds
код:
http://pastebin.com/6wsFawWy
У меня этот код даёт в среднем 6100 мс. Если раскомментировать (2) и закомментировать (1), то - 61 мс. Разница в 100 раз!
(1) 0.000000835
(2) 0.000000882
http://ideone.com/sf3FK
(1) 0.000835
(2) 0.000882
Вот такой будет правильный результат.
Ну оно и не выводит 14 килобайт в течении 6100мс ;)
results:
--------------
win7 msvc 9.0 sp1 /O2, invoking from cmd.exe:
without locale
cout : 4278 milliseconds
printf : 162 milliseconds
after locale
cout : 4711 milliseconds
printf : 3541 milliseconds
--------------
linux 2.6.9 g++ 3.4.6 -O2, invoking from native console
(linux is guest OS virt. by oracle virtualbox on host machine win7)
without locale
cout : 548 milliseconds
printf : 580 milliseconds
after locale
cout : 489 milliseconds
printf : 512 milliseconds
код: http://pastebin.com/qgX1QDZi
зы:
используя putty в качестве терминала на том же линуксе получается вообще
without locale
cout : 18 milliseconds
printf : 25 milliseconds
after locale
cout : 27 milliseconds
printf : 25 milliseconds
так что оставляет лишь вопросы реализация микрософтом printf без установки глобальной локали
ну и даже под виртуалкой (хоть и с современной виртуализацией), родной линуксовый терминал в 10 раз быстрее cmd.exe
А можно еще для полноты картины замерить вывод с перенаправлением в файл (ну или в NUL, /dev/null) на тех же машинах?
string length 10M
---------
win32, output to NUL
without locale
ofstream: 69436 microseconds
fprintf : 65772 microseconds
after locale
ofstream: 69005 microseconds
fprintf : 64979 microseconds
---------
linux, output to real file
without locale
ofstream: 33588 microseconds
fprintf : 68873 microseconds
after locale
ofstream: 50673 microseconds
fprintf : 50930 microseconds
---------
и самое необычное:
linux, output to /dev/null
without locale
ofstream: 122 microseconds
fprintf : 4700 microseconds
after locale
ofstream: 23 microseconds
fprintf : 4961 microseconds
подозрительно похоже, что в /dev/null поток сам оптимизирует и ничего не делает при выводе в него, в отличие от fprintf
потому что на строке 1G вышло
ofstream: 67 microseconds
fprintf : 626281 microseconds
что неправильно
тест с /dev/null онлайн бесплатно - см http://liveworkspace.org/code/a379ba5525d7117d9da974fe98c934fc
для него уменьшил размер строки до 100М
Читеры... Интересно как они отличают /dev/null от настоящего файла. Не по имени же?
http://mosobzor.com/moswar/news/49d9dc30788acd0742d9cbf859ebe794.jpg
1) Разрывает шаблон с++никам, привыкшим, что const поля никто не меняет.
2) Неоднородность. В случае с акцессорами есть простые правила. К примеру в Qt: w->text() - получить текст, w->setText() установить текст. Это правило нарушают разве что в случае, когда работают с POD структурами. В вашем же случае часть полей будет read-only, и их будут использовать как w->text, часть полей будет read-write, к которым будут лезть напрямую, а часть полей все-равно потребует нетривиальных геттеров и\или сеттеров. Чтобы определить, какой из вариантов нужен для обращения к конкретному свойству придется читать документацию (или подсказку в IDE).
3) Самое печальное - если вдруг понадобится превратить поле в акцессор или даже сменить его тип - придется рефакторить все точки, в которых используется поле. В пределах мелкого проекта - терпимо. А в большом, состоящем из нескольких программ и библиотек... ну вы поняли ;)
Это как бы не мои проблемы. Специально для них можно использовать readonly, определив его как #define readonly const.
>а часть полей все-равно потребует нетривиальных геттеров и\или сеттеров
Их я пытался минимизировать. Например, делал их доступными, но создавал private копии, по которым можно определить, изменилось ли значение. Если это не получается, можно написать свой класс свойств, но на C++ это получится решение с костылями и будет работать не всегда правильно. Поэтому я не стал пытаться это делать.
3. Движок занимает чуть меньше 10000 строк. При переходе на C# он станет гораздо меньше, потому что велосипеды можно будет выкинуть. Хотя там и не надо будет так мудрить, там есть нормальные свойства. Вот это будет облегчение!
Хочется взять и... ну вы поняли.
> Хотя там и не надо будет так мудрить, там есть нормальные свойства.
Верно. Раз задача небольшая, удобно переписывается на c#, и идеи, заложенные в c# вам ближе - пишите на c#, никто вас за это не осудит.
Ну да, пока задача маленькая - можно писать на крестах, хотя все равно дохрена времени потратишь, а если большая, то на крестах проект просто развалится, так что сразу нужно было на C# переходить.
Если уж писать велосипед, то по мне лучше сделать open статической функцией-членом, возвращающей объект File.
То, что у файла может сменится хэндл, тоже не радует. Ну и упомянутые уже флажки - sucks.
>То, что у файла может сменится хэндл, тоже не радует.
Он может только обнулиться при закрытии файла, а меняться не может.
Поделил на ноль.
А про деление на ноль я не понял.
Зачем закрывать ещё не открыты файл? О_о
P.S. почему когда я пишу ответ, у меня иногда спрашивают проверочный код с картинки, а иногда нет?
http://govnokod.ru/7688
(UINT_MAX-1) - это какой элемент? Предпоследний?