- 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));
}
Скорее всего, этот код вам покажется странным, поэтому я его выкладываю. Хотя я его говнокодом не считаю и он мне даже нравится.
AliceGoth 17.07.2012 01:27 # 0
fdw = open(argv[2], O_RDWR|O_CREAT |O_SYNC|O_TRUNC, 0600);
bormand 17.07.2012 05:34 # +4
sayidandrtfm 17.07.2012 06:28 # 0
gammaker 17.07.2012 10:31 # +1
sayidandrtfm 17.07.2012 13:05 # +2
Там и оставайтесь. Портировать не обязательно.
gammaker 17.07.2012 15:25 # +3
sayidandrtfm 17.07.2012 15:32 # +1
ИМХО: помимо 2k и ХPюши, про всё остальное не чокаясь.
gammaker 17.07.2012 15:45 # +2
eth0 17.07.2012 17:59 # +3
rat4 17.07.2012 20:12 # +5
sayidandrtfm 19.07.2012 15:29 # +2
rat4 19.07.2012 16:05 # +1
govnomonad 18.07.2012 03:57 # 0
остальные редакции лень искать
gammaker 18.07.2012 10:30 # +1
defecate-plusplus 17.07.2012 07:32 # +8
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 * и т.д.
gammaker 17.07.2012 10:58 # 0
2. Эта функция используется внутри класса файла. Пользователь пользуется классами File::Reader и File::Writer, в которых всё читабельно.
3. Да, наверное, надо сделать static. Только оптимизировать производительность здесь и на таких мелочах нет смысла.
4. Name - это константный член класса, в котором хранится путь к файлу. (string&) - это приведение к неконстантной ссылке - способ изменения константы - такая хитрая реализация свойств только для чтения.
5. defecate-STL. Своё мне больше нравится.
defecate-plusplus 17.07.2012 11:31 # 0
2. раз пользователь пользуется чем то иным, вот это иное сюда и надо спокойно передать
4. это говнокод
и да, разницу в передаче аргументов по копии и по ссылке ведь понимаешь?
gammaker 17.07.2012 15:19 # 0
2. В "ином" коде нет ничего интересного.
4. Он запрятан внутрь, а снаружи он только улучшает код, позволяя избавиться от кучи геттеров.
Мой класс string использует счётчик ссылок и копируется только при записи.
defecate-plusplus 17.07.2012 15:33 # 0
если у тебя нет сеттера, тогда какая разница? выглядит плохо
> Мой класс string использует счётчик ссылок
т.е. на operator [] возвращает объект MyStringCharRef, как в кутэ?
gammaker 17.07.2012 15:44 # 0
Что лучше: использовать геттер engine->GetObjectCount() или обращаться напрямую engine->ObjectCount? ObjectCount объявлена как const int, но трюк с приведением к ссылке позволяет устанавливать его. Используется он только внутри класса Engine.
>т.е. на operator [] возвращает объект MyStringCharRef, как в кутэ?
Нет, он только для чтения. Устанавливает конкретный символ функцией SetChar.
TarasB 17.07.2012 15:50 # +1
Правка: это вопрос.
gammaker 17.07.2012 16:00 # 0
defecate-plusplus 17.07.2012 16:00 # 0
компилятор с++ в случае будет юзать не константный operator []
потому в stl строки не страдают ерундой с COW, обеспечивая минимальный интерфейс общего назначения (ну и плюс в стандарте 98/03 никто не обговаривал средства обеспечения атомарности), а для QT, где объекты строк за свою жизнь тысячи раз куда то копируются из ядра на экран, не западло переписать класс строки, чтобы по operator [] возвращать специальный объект "символ", на модификации которого тот уже будет считать ссылки и копировать родительскую строку
TarasB 17.07.2012 16:05 # 0
gammaker 17.07.2012 16:18 # 0
defecate-plusplus 17.07.2012 16:19 # 0
засуммонь борманда
всё, что я вижу в сорцах
т.е. это не даст передать как QChar & куда-нибудь
bormand 17.07.2012 16:44 # 0
Именно так.
Во-первых QChar юникодный и в char все равно не влезет, разве что в wchar_t.
Во-вторых, как правильно заметил defecate++, в QChar& он тоже не кастуется.
В третьих - а оно нужно? У QString удобный интерфейс и посимвольное обращение к строкам требуется редко.
bormand 17.07.2012 12:24 # +3
No comments. Во время чтения этой строки у меня возник необъяснимый приступ агрессии.
defecate-plusplus 17.07.2012 12:55 # +2
с опытом как-нибудь придёт - время лечит
gammaker 17.07.2012 14:52 # +1
bormand 17.07.2012 17:01 # +2
Как сказал мудрый человек - "программист на фортране может писать на любом языке... как на фортране".
Перенести все идиомы c# в c++ (да и в обратную сторону тоже) не получится - совершенно другая архитектура, и большая часть портированного кода будет смотреться как нечто инородное (если не как говно)...
Если для ваших задач удобнее c#, то вы приняли совершенно правильное решение, перейдя на него.
gammaker 17.07.2012 18:27 # 0
Только я с C++ и начинал. От C# и D я потом всего этого нахватался и захотел перевести на C++.
TarasB 17.07.2012 17:54 # +3
defecate-plusplus 17.07.2012 18:08 # 0
в сравнении с выводом напрямую
TarasB 17.07.2012 18:12 # +1
roman-kashitsyn 17.07.2012 18:13 # +2
defecate-plusplus 17.07.2012 18:13 # 0
когда то давно пробегала ссылка на сравнение sscanf, atof, istream и boost::spirit::qi
не могу найти
TarasB 17.07.2012 18:26 # 0
bormand 17.07.2012 18:58 # +1
P.S. Посравнивал на простеньком примере с числом, хекс числом выровненным под 8 знакомест, и строкой скорости вывода. fprintf самый быстрый. ofstream раз в 5 медленее. QTextStream еще в 4 раза медленее (что в принципе логично - у него все-таки кодек из юникода на выхлопе).
defecate-plusplus 17.07.2012 20:41 # +1
http://bit.ly/LwiPpv
gammaker 17.07.2012 18:28 # 0
defecate-plusplus 17.07.2012 19:56 # +5
в разы
gammaker 18.07.2012 10:38 # 0
Да, stringstream медленнее sprintf в разы.
cout медленнее printf\puts при выводе готовой строки в десятки раз! По крайней мере, в студии. Возьмите строчку подлиннее и сами попробуйте.
bormand 18.07.2012 11:22 # +1
std::cout << bigString << std::endl;
3.80с на вывод миллиона строк
printf("%s\n", bigString);
1.02c на вывод миллиона строк
Парой постов выше тестировал на более-менее сложном примере - число, шестнадцатеричное число, и строка - iostream был раз в 5 медленее fprintf.
Ну т.е не десятки раз это, а разы.
gammaker 18.07.2012 11:31 # 0
bormand 18.07.2012 11:42 # 0
Виртуалку поднимать, экспресс эдишн качать... лень короче.
> Сейчас ещё раз попробую, чтобы время замерить...
Оки, скинь тогда код, на котором будет проведено тестирование. Откомпилю его в gcc для сравнения.
defecate-plusplus 18.07.2012 11:50 # 0
without locale
cout: 545 milliseconds
printf: 8 milliseconds
with locale
cout: 566 milliseconds
printf: 461 milliseconds
код:
http://pastebin.com/6wsFawWy
gammaker 18.07.2012 15:14 # 0
У меня этот код даёт в среднем 6100 мс. Если раскомментировать (2) и закомментировать (1), то - 61 мс. Разница в 100 раз!
gammaker 18.07.2012 15:17 # 0
bormand 18.07.2012 15:45 # +1
bormand 18.07.2012 15:38 # +2
(1) 0.000000835
(2) 0.000000882
http://ideone.com/sf3FK
bormand 18.07.2012 15:47 # 0
(1) 0.000835
(2) 0.000882
Вот такой будет правильный результат.
defecate-plusplus 18.07.2012 15:56 # 0
bormand 18.07.2012 15:59 # 0
Ну оно и не выводит 14 килобайт в течении 6100мс ;)
defecate-plusplus 18.07.2012 16:15 # +3
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
bormand 18.07.2012 16:51 # 0
А можно еще для полноты картины замерить вывод с перенаправлением в файл (ну или в NUL, /dev/null) на тех же машинах?
defecate-plusplus 18.07.2012 17:15 # +1
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М
bormand 18.07.2012 17:20 # +1
Читеры... Интересно как они отличают /dev/null от настоящего файла. Не по имени же?
sayidandrtfm 17.07.2012 13:02 # +2
http://mosobzor.com/moswar/news/49d9dc30788acd0742d9cbf859ebe794.jpg
gammaker 17.07.2012 15:09 # 0
bormand 17.07.2012 17:52 # 0
1) Разрывает шаблон с++никам, привыкшим, что const поля никто не меняет.
2) Неоднородность. В случае с акцессорами есть простые правила. К примеру в Qt: w->text() - получить текст, w->setText() установить текст. Это правило нарушают разве что в случае, когда работают с POD структурами. В вашем же случае часть полей будет read-only, и их будут использовать как w->text, часть полей будет read-write, к которым будут лезть напрямую, а часть полей все-равно потребует нетривиальных геттеров и\или сеттеров. Чтобы определить, какой из вариантов нужен для обращения к конкретному свойству придется читать документацию (или подсказку в IDE).
3) Самое печальное - если вдруг понадобится превратить поле в акцессор или даже сменить его тип - придется рефакторить все точки, в которых используется поле. В пределах мелкого проекта - терпимо. А в большом, состоящем из нескольких программ и библиотек... ну вы поняли ;)
gammaker 17.07.2012 18:18 # −2
Это как бы не мои проблемы. Специально для них можно использовать readonly, определив его как #define readonly const.
>а часть полей все-равно потребует нетривиальных геттеров и\или сеттеров
Их я пытался минимизировать. Например, делал их доступными, но создавал private копии, по которым можно определить, изменилось ли значение. Если это не получается, можно написать свой класс свойств, но на C++ это получится решение с костылями и будет работать не всегда правильно. Поэтому я не стал пытаться это делать.
3. Движок занимает чуть меньше 10000 строк. При переходе на C# он станет гораздо меньше, потому что велосипеды можно будет выкинуть. Хотя там и не надо будет так мудрить, там есть нормальные свойства. Вот это будет облегчение!
bormand 17.07.2012 18:29 # +2
Хочется взять и... ну вы поняли.
> Хотя там и не надо будет так мудрить, там есть нормальные свойства.
Верно. Раз задача небольшая, удобно переписывается на c#, и идеи, заложенные в c# вам ближе - пишите на c#, никто вас за это не осудит.
USB 17.07.2012 22:11 # +1
Ну да, пока задача маленькая - можно писать на крестах, хотя все равно дохрена времени потратишь, а если большая, то на крестах проект просто развалится, так что сразу нужно было на C# переходить.
roman-kashitsyn 17.07.2012 07:59 # 0
Если уж писать велосипед, то по мне лучше сделать open статической функцией-членом, возвращающей объект File.
То, что у файла может сменится хэндл, тоже не радует. Ну и упомянутые уже флажки - sucks.
gammaker 17.07.2012 11:12 # 0
>То, что у файла может сменится хэндл, тоже не радует.
Он может только обнулиться при закрытии файла, а меняться не может.
rat4 17.07.2012 11:40 # +2
Поделил на ноль.
gammaker 17.07.2012 15:23 # 0
А про деление на ноль я не понял.
sayidandrtfm 17.07.2012 15:34 # 0
rat4 17.07.2012 15:47 # 0
Зачем закрывать ещё не открыты файл? О_о
gammaker 17.07.2012 15:50 # 0
roman-kashitsyn 17.07.2012 17:38 # 0
gammaker 17.07.2012 18:20 # +1
P.S. почему когда я пишу ответ, у меня иногда спрашивают проверочный код с картинки, а иногда нет?
eth0 17.07.2012 20:22 # +2
gammaker 17.07.2012 20:51 # 0
sayidandrtfm 17.07.2012 21:18 # 0
gammaker 17.07.2012 22:08 # 0
Fai 17.07.2012 08:51 # 0
vistefan 17.07.2012 13:16 # +1
bormand 17.07.2012 13:31 # 0
guest 17.07.2012 14:31 # +4
bormand 17.07.2012 16:28 # 0
gammaker 17.07.2012 16:46 # +1
http://govnokod.ru/7688
bormand 17.07.2012 17:03 # +2
USB 17.07.2012 22:14 # 0
roman-kashitsyn 17.07.2012 23:01 # 0
gammaker 17.07.2012 23:04 # 0
USB 17.07.2012 23:07 # 0
(UINT_MAX-1) - это какой элемент? Предпоследний?
gammaker 18.07.2012 10:14 # 0
TarasB 18.07.2012 12:06 # +1