LINUX.ORG.RU
Ответ на: комментарий от lazyklimm

А вы в сам iostream заглядывали? Угадайте, какими методами он пользуется для записи и чтения файла?

Я думаю для вас будет сюрпризом узнать, что (например содержимое c++io.h выглядит примерно так:

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  typedef __gthread_mutex_t __c_lock;

  // for basic_file.h
  typedef FILE __c_file;

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

А __c_file используется в basic_file.h и так далее и поехали. Что же это получается? STL не C++?!

invy ★★★★★
()
Ответ на: комментарий от dave

По сути, дотнетовский код джитится до нативного.

Он даже джитится до оптимизированного нативного. Но как это может влиять на скорость IO - загадка.

unfo ★★★★★
()
Ответ на: комментарий от red_eyed_peguin

У меня 2ГБ оперативки, так что переполнять пока нечего. Как будет гигабайт 8 хотя бы, тогда и похожу по граблям.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от lazyklimm

Нет, стоп, c++io.h - «полностью сишиный за исключением инклудов»? А если я в своей программе напишу (вот надо мне своё собственное IO с блэкджэком и шлюхами):

class FileIO {
 FILE *m_file;
public:
 FileIO(string &filename);
 open();
 close();
 reverse();
};
Это какой язык? Си? или Си++? А если я для IO буду использовать WinAPI? Как-нибудь так:
class FileIO {
 HANDLE hFile;
...
}
Это какой язык? CWinApi++?

invy ★★★★★
()
Ответ на: комментарий от invy

полностью сишиный за исключением инклудов

namespace

вот надо мне своё собственное IO с блэкджэком и шлюхами

а так ли тебе оно надо?

Это какой язык? CWinApi++?

C++, только зачем?

lazyklimm ★★★★★
()
Ответ на: комментарий от vaino

Прикрутите ещё валидацию каждого октета, игнорирование суррогатных пар, соответствие длины символа закодируемому юникоду и выход за пределы юникода :)

gatsu
()
Ответ на: комментарий от lazyklimm

namespace

то есть если бы в коде vaino был namespace britisch_scientiest_suck { }, то это был бы настоящий Си++?

а так ли тебе оно надо?
только зачем?

А это уже другой вопрос. Смысл в том, что Си++ отдельно, а библиотеки отдельно. Ограничивать себя только использованием стандартной библиотеки (тем более неправильным, как у «учёных») не есть умно и тем более не есть правильно. А экстраполировать всё это на качества Си++ - это уже идиотизм.

invy ★★★★★
()
Ответ на: комментарий от invy

то есть если бы в коде vaino был namespace britisch_scientiest_suck { }, то это был бы настоящий Си++

нет. Это был бы C, завернутый namespace.

код c++io.h (без namespace) можно трактовать и как плюсовый и как сишный.

а в коде vaino сплошняком используются сишные функции, для которых есть плюсовые аналоги/обёртки - зачем-то их делали же, верно?

Да, если бы C++ оставался на уровне «с с классами» - никаких претензий бы не было.

Ограничивать себя только использованием стандартной библиотеки не есть умно и тем более не есть правильно.

они же вроде написали, что специально сравнивали именно стандартные либы

тем более неправильным, как у «учёных»

ну, это верно. Кстати, я весь тред не читал: кто-нибудь уже написал «правильный» вариант с использованием стандартной библиотеки?

lazyklimm ★★★★★
()
Ответ на: комментарий от encyrtid

Это как написать весь алгоритм на асме, запихать в asm { } и утверждать что код сишный.

Говно ваша аналогия.

andreyu ★★★★★
()
Ответ на: комментарий от lazyklimm

ок, а это тогда на каком языке будет?

#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>

using namespace std;

static const char u8len[ 256 ] =
{
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,  3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
};

int main()
{
	char char_buf[ 8 ];
	char ch;
	char clen;
	char *utf8;
	char *line;
	int j;

	for( size_t k = 0 ; k < 20 ; ++k )
	{
		fstream fs;
		fs.open("text.txt",  fstream::in | fstream::out);

		fs.seekg(0, ios::end);;
		int count = fs.tellg();
		fs.seekg(0, ios::beg);

		char *text_buf = (char*) malloc( count );
		char *line_buf = (char*) malloc( count );
		char *el = line_buf + count;

		line = el;

		fs.read(text_buf, count);

		for( int i = 0 ; i < count ; ++i )
		{
			ch = text_buf[ i ];
			if( ch == '\n' )
			{
				int len = el - line;
				memcpy( text_buf + i - len, line, len );
				line = el;
			}
			else
			{
				clen = u8len[ (unsigned char) ch ];
				if( !clen )
				{
					*--line = ch;
				}
				else
				{
					++clen;
					utf8 = text_buf + i + clen;
					for( j = 0 ; j < clen ; ++j )
						*--line = *--utf8;

					i += clen - 1;
				}
			}
		}

		fs.seekp(0, ios::beg);
		fs.write(text_buf, count);
		fs.close();
		free( text_buf );
		free( line_buf );
	}
}
сравнение производительности можете провести собвтеннолично ;)

invy ★★★★★
()
Ответ на: комментарий от invy

у меня так даже быстрее выходит... вроде бы.

invy ★★★★★
()
Ответ на: комментарий от lazyklimm

а в коде vaino сплошняком используются сишные функции, для которых есть плюсовые аналоги/обёртки - зачем-то их делали же, верно?

да, чтоб, например, не маятся с ручным выделением/освобождением/реаллокацией памяти, и это здорово облегчает жизнь и уменьшает размер кода, в данном примере необходимости в их использовании не было - т.к. все делалось над статичными по размеру буферами в рамках одной функции

vaino
()
Ответ на: комментарий от encyrtid

С чего бы вдруг?

Пусть это будет вашим домашним заданием.

andreyu ★★★★★
()
Ответ на: комментарий от invy

сравнение производительности можете провести собвтеннолично ;)

Нужно заменить

char *text_buf = (char*) malloc( count );
char *line_buf = (char*) malloc( count );

на

std::vector<char> text_buf;
text_buf.resize(count);
std::vector<char> line_buf;
line_buf.resize(count);

или хотя бы на

char* text_buf = new char[count];
char* line_buf = new char[count];
andreyu ★★★★★
()
Ответ на: комментарий от andreyu

А потом vector <wstring> textbuf(count), чтобы у нас честный юникод был, потом ещё пару изменений. В результате получим код, аналогичный по смыслу и тормозам тому, что приведён по ссылке.

yurikoles ★★★
()
Ответ на: комментарий от yurikoles

Я это понял когда пытался «допортировать на С++» алгоритм, предложенный vaino.

yurikoles ★★★
()
Ответ на: комментарий от yurikoles

fs.read не умеет читать в вектор, fial.

&buf.front(), не за что

vaino
()
Ответ на: комментарий от gatsu
uint32_t next_char(const char ** text){
	static const unsigned char utf8_bytes[32]={
		1,//0,//skip control symbols
		1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,//0x1f-0x7f,
		0,0,0,0,0,0,0,0,//continuation
		2,2,2,2,
		3,3,
		4,
		0//bad symbol!!!		
	};//
	static const unsigned char utf8_data_bits[32]={
		7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
		6,6,6,6,6,6,6,6,
		5,5,5,5,
		4,4,
		3,
		0
	};
	//this /\ /\ /\ may be optimised, maybe...
	//we don't need precise conversion or error handling, 
	//so just make bad utf8 text invisible
	char * iter=*text;	
	unsigned char index=0x1f & (iter[0]>>3);
	unsigned int bytes=utf8_bytes[index]; 
	uint32_t result=0;
	char * newtext=text+bytes;
	
	while(*iter && bytes)
	{
		uint32_t tmp=iter[0];//get next char
		tmp&=(1<<utf8_data_bits[index])-1;//remove non-data bits
		result=(result<<utf8_data_bits[index])|tmp;
		index=0x1f & (iter[1]>>3);
		++iter;
		--bytes;
	}
	if(result>=0x10FFFF)result=0;
	if(result>=0xD800 || result<=0xDFFF)result=0;
        if(bytes)return 0;
	*text=iter;
	return result;
}

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

и это С++, g++ потверждае!

ckotinko ☆☆☆
()
Ответ на: комментарий от ckotinko
unsigned char index=0x1f & (iter[0]>>3);
unsigned int bytes=utf8_bytes[index];

Интересная (и краткая) реализация, не встречал такой.

Однако, по-прежнему есть недоработки:

1) Пооктетовой проверки нет. В случае битого/пропущенного октета твой парсер возможно захавает октеты, которые принадлежат другим символам (и так может по цепочке пропустить полтекста). Например, 0xC0, 0xD0, 0x9A, полужирным выделена валидная часть.

2) Валидации соответствия длины символа закодированному юникоду нет. Это тоже важно, представь себе что будет, если закодировать "." или «/» не в соответствующий ASCII, а в многооктетовый символ :)

gatsu
()
Ответ на: комментарий от gatsu

Однако, по-прежнему есть недоработки

проверил только что битый файл в utf8 с mono - он его портит, и даже если перевернуть строки четное кол-во раз, то файл не идентичен исходному, так что данные проверки можно и нужно добавить, но:

а) на скорость это скажется мало, т.к. в случае с С++ большая часть времени идет на malloc/free( в случае с кешированным в ОЗУ файлом ), и кстати тут явно можно улучшить
б) это уже выйдет за рамки задачи - альтернативная реализация тут ведет себя тоже некорректно

vaino
()
Ответ на: комментарий от yurikoles

А потом vector <wstring> textbuf(count), чтобы у нас честный юникод был, потом ещё пару изменений. В результате получим код, аналогичный по смыслу и тормозам тому, что приведён по ссылке.

Каким образом vector <wstring> textbuf(count) добавит тормоза? Если вы говорите о «еще паре изменений» - то это лично ваша проблема.

andreyu ★★★★★
()
Ответ на: комментарий от yurikoles

fs.read не умеет читать в вектор, fial.

Ну-ну. Походу это вы не знаете, что такое вектор.

andreyu ★★★★★
()

C++ не годится

Тоже мне новость...

Hertz ★★★★★
()
Ответ на: комментарий от invy

Не работает. Надо отметить, что итт вообще ни одного рабочего вариант на плюсах предоставлено не было. Что какбе символизирует.

anonymous
()
Ответ на: комментарий от anonymous
#include <algorithm>
#include <fstream>
using namespace std;

int main()
{
	wifstream fi( "text.txt" );
	fi.imbue( locale("en_US.UTF-8") );

	wstring s, txt;
	while( fi >> s )
	{
		reverse( s.begin(), s.end() );
		txt += s;
		txt.push_back( '\n' );
	}

	wofstream fo( "text.txt" );
	fo.imbue( locale("en_US.UTF-8") );
	fo << txt;
}

работает медленней кода «не на плюсах», но при этом в разы быстрее кода на C#

vaino
()
Ответ на: комментарий от anonymous

Видимо, перезаписать строки в обратном направлении на плюсах - это тема для Ph.D

anonymous
()
Ответ на: комментарий от tailgunner

Полагаю, дело все в том, что я запускал в офтопике под cygwin. Но, извините, это смешно, когда подобные проблемы совместимости вылазят на столь тривиальной задаче.

anonymous
()
Ответ на: комментарий от anonymous

Полагаю, дело все в том, что я запускал в офтопике под cygwin

Полагаю, дело в том, что у тебя Cygwin неправильно сконфигурирован.

это смешно, когда подобные проблемы совместимости вылазят на столь тривиальной задаче.

На моей машине .NET-приложение вообще не запустится. У этого вашего .NET такие смешные проблемы совместимости.

tailgunner ★★★★★
()
Ответ на: комментарий от drBatty

да, кому нефиг делать проверьте плз без крестов

файл rev.c можно взять здесь

·   buf = xmalloc(bufsiz * sizeof(wchar_t));

·   do {
·   ·   if (*argv) {
·   ·   ·   if ((fp = fopen(*argv, "r")) == NULL) {
·   ·   ·   ·   warn(_("%s: open failed"), *argv );
·   ·   ·   ·   rval = EXIT_FAILURE;
·   ·   ·   ·   ++argv;
·   ·   ·   ·   continue;
·   ·   ·   }
·   ·   ·   filename = *argv++;
·   ·   }

·   ·   while (fgetws(buf, bufsiz, fp)) {
·   ·   ·   len = wcslen(buf);

·   ·   ·   /* This is my hack from setpwnam.c -janl */
·   ·   ·   while (buf[len-1] != '\n' && !feof(fp)) {
·   ·   ·   ·   /* Extend input buffer if it failed getting the whole line */
·   ·   ·   ·   /* So now we double the buffer size */ 
·   ·   ·   ·   bufsiz *= 2;

·   ·   ·   ·   buf = xrealloc(buf, bufsiz * sizeof(wchar_t));

·   ·   ·   ·   /* And fill the rest of the buffer */
·   ·   ·   ·   if (!fgetws(&buf[len], bufsiz/2, fp))
·   ·   ·   ·   ·   break;

·   ·   ·   ·   len = wcslen(buf);
·   ·   ·   }

·   ·   ·   t = buf + len - 1 - (*(buf+len-1)=='\r' || *(buf+len-1)=='\n');
·   ·   ·   for ( ; t >= buf; --t) {
·   ·   ·   ·   if (*t != 0)
·   ·   ·   ·   ·   putwchar(*t);
·   ·   ·   }
·   ·   ·   putwchar('\n');
·   ·   }

·   ·   fflush(fp);
·   ·   if (ferror(fp)) {
·   ·   ·   warn("%s", filename);
·   ·   ·   rval = EXIT_FAILURE;
·   ·   }
·   ·   if (fclose(fp))
·   ·   ·   rval = EXIT_FAILURE;
·   } while(*argv);

·   free(buf);

мне с шарпом не сравнить, ибо этого дерьма нет и не будет на моих системах.

drBatty ★★
()

яплакал:

Note that this is, of course, in Release mode and without a debugger attached. Just for fun, let's see what happens in the typical «F5» scenario: debugging the Debug build.

C++: 13653 ms (that's 13,6 seconds, yes!) C#: 59 ms

This is consistent with other benchmarks I did in the past: C# is relatively unaffected by being built in Debug mode and having a debugger attached; C++ presents extreme discrepancies in that regard.

13 секунд! апписдинэть! Ну ещё-бы, если компилятор MSVC при каждой аллокации пихает в новую строчку кучу фигни, что-бы утечки памяти ловить, и в версии STL аллокации для КАЖДОЙ строки, а в версии C# аллокаций всего ОДНА. Это даже такой ламо как я (ибо не юзал уже давно MSVS) понимает...

Кстати, что этот маздайный высер (прошу прощения у дам, но данное крео иначе не назвать) делает на моём ЛОРе?

drBatty ★★
()
Ответ на: комментарий от anonymous

А при чем тут .net, если речь о шарпе?

Есть компиляторы шарпа в нативный код, не требующий рантайма .NET (Mono - тоже реализация .NET)?

tailgunner ★★★★★
()
Ответ на: комментарий от drBatty

Кстати, что этот маздайный высер (прошу прощения у дам, но данное крео иначе не назвать) делает на моём ЛОРе?

Неужели ты еще не понял, что такое Karapuz?

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

а это у создателей креатива надо спросить. Вот что они пишут по этому поводу:

That, repeated multiple times and benchmarked.

The approach for .NET: File.ReadAllLines(), a for loop over the result, Array.Reverse, and File.WriteAllLines. That's the way I would write this procedure normally; it's as simple as possible, and I can't think of an obvious way of making it more efficient.

The approach for C++: C++ has std::reverse which is the equivalent of Array.Reverse (but more generic), however, it doesn't have an equivalent of File.Read/Write-AllLines. I searched a bit online to see what was considered the standard approach, and eventually settled on opening an ifstream, reading the file line by line into a vector of strings using std::getline, and outputting it to an ofstream using the operator <<.

вот так вот...

drBatty ★★
()
Ответ на: комментарий от drBatty

проверьте

во-первых огрызок проверять неинтересно, во-вторых сразу можно сказать - работать на оригинальных тестовых данных не будет

vaino
()
Ответ на: комментарий от tailgunner

спасибо, понял. Просто лично меня мало волнуют проблемы какой-то проприентарной реализации какого-то ненужного г-на.

Кстати, может мне кто расскажет, как часто и ЗАЧЕМ используется reverse() в продакшене?

drBatty ★★
()
Ответ на: комментарий от vaino

блжд! Какой «огрызок»? Это стандартная линуксовая команда rev(1).

REV(1)                    BSD General Commands Manual                   REV(1)

NAME
     rev — reverse lines of a file or files

SYNOPSIS
     rev [file ...]

DESCRIPTION
     The rev utility copies the specified files to the standard output, reversing the order of characters in
     every line.  If no files are specified, the standard input is read.

AVAILABILITY
     The rev command is part of the util-linux package and is available from ftp://ftp.ker‐
     nel.org/pub/linux/utils/util-linux/.

BSD                             March 21, 1992                             BSD
drBatty ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.