В windows испорчен writeln
Модератор: Модераторы
В windows испорчен writeln
Или у меня компиляторы собраны неправильно (такие уже скачал), или какие-то инноваторы прикрутили к writeln принудительную перекодировку отправляемого в консоль текста из cp866 в utf8. И если текст или консоль не в той кодировке, то происходит звиздец и лажа. И никак это вредительство не отключить. Есть ли для винды какая-то альтернатива writeln?
Это в какой версии так было? В последней версии 2.0.4 версии лазаруса для win64 writeln('12345 йцукен'); пытается в файл залезть и вызывает ошибку. Перезагрузка функции глючит, не та что нужно вызывается.
Сквозняк писал(а):В последней версии 2.0.4 версии лазаруса для win64 writeln('12345 йцукен'); пытается в файл залезть и вызывает ошибку.
Вы сначала уточните: у Вас тут речь идёт о консольном или о GUI приложении. А то разговор уже приобретает характер сломанного телефона...
- Снег Север
- долгожитель
- Сообщения: 3067
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
Код: Выделить всё
program project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
{$IFDEF WINDOWS}
Windows, {for setconsoleoutputcp}
{$ENDIF}
Classes, SysUtils, CustApp
{ you can add units after this };
type
{ TMyApplication }
TMyApplication = class(TCustomApplication)
protected
procedure DoRun; override;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure WriteHelp; virtual;
end;
{ TMyApplication }
procedure TMyApplication.DoRun;
var
ErrorMsg, s: String;
begin
// quick check parameters
ErrorMsg:=CheckOptions('h', 'help');
if ErrorMsg<>'' then begin
ShowException(Exception.Create(ErrorMsg));
Terminate;
Exit;
end;
// parse parameters
if HasOption('h', 'help') then begin
WriteHelp;
Terminate;
Exit;
end;
{ add your program here }
SetConsoleOutputCP(CP_UTF8);
writeln('12345 йцукен');
readln(s);
// stop program loop
Terminate;
end;
constructor TMyApplication.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
StopOnException:=True;
end;
destructor TMyApplication.Destroy;
begin
inherited Destroy;
end;
procedure TMyApplication.WriteHelp;
begin
{ add your help code here }
writeln('Usage: ', ExeName, ' -h');
end;
var
Application: TMyApplication;
begin
Application:=TMyApplication.Create(nil);
Application.Title:='My Application';
Application.Run;
Application.Free;
end.
Что я делаю не так?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Vadim писал(а):Сквозняк писал(а):В последней версии 2.0.4 версии лазаруса для win64 writeln('12345 йцукен'); пытается в файл залезть и вызывает ошибку.
Вы сначала уточните: у Вас тут речь идёт о консольном или о GUI приложении. А то разговор уже приобретает характер сломанного телефона...
Из окошка, из буттонклик вриттелн отправить. И скомпилировать так, как лазарус по умолчанию компилирует. Тогда и будет ошибка. Раньше, на вин32 этого бага не было. Под то, что нельзя сгенерировать баг из консолького приложения - не подписываюсь. Это надо дополнительно тестировать, будет баг при лишних опциях компиляции или нет. Вот протестируй и узнаешь. Это и в вайне работает и в реальной 64 бит семёрке.
Добавлено спустя 8 минут 23 секунды:
Снег Север писал(а):Код: Выделить всё
program project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
{$IFDEF WINDOWS}
Windows, {for setconsoleoutputcp}
{$ENDIF}
Classes, SysUtils, CustApp
{ you can add units after this };
type
{ TMyApplication }
TMyApplication = class(TCustomApplication)
protected
procedure DoRun; override;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure WriteHelp; virtual;
end;
{ TMyApplication }
procedure TMyApplication.DoRun;
var
ErrorMsg, s: String;
begin
// quick check parameters
ErrorMsg:=CheckOptions('h', 'help');
if ErrorMsg<>'' then begin
ShowException(Exception.Create(ErrorMsg));
Terminate;
Exit;
end;
// parse parameters
if HasOption('h', 'help') then begin
WriteHelp;
Terminate;
Exit;
end;
{ add your program here }
SetConsoleOutputCP(CP_UTF8);
writeln('12345 йцукен');
readln(s);
// stop program loop
Terminate;
end;
constructor TMyApplication.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
StopOnException:=True;
end;
destructor TMyApplication.Destroy;
begin
inherited Destroy;
end;
procedure TMyApplication.WriteHelp;
begin
{ add your help code here }
writeln('Usage: ', ExeName, ' -h');
end;
var
Application: TMyApplication;
begin
Application:=TMyApplication.Create(nil);
Application.Title:='My Application';
Application.Run;
Application.Free;
end.
Что я делаю не так?
А что так? Для простого посылания сообщения разводишь конструкторы-деструкторы, класс создаёшь, подтягиваешь кучу зависимостей. У writeln в документации таких условий для применения нет. Ты просто прячешь виндовый баг вынуждая лазарус обойти ошибку в коде. Причём обход происходит неявно, неизвестно что в этом обряде изгнания бага ценное, а что нет - зубрите по несколько экранов кода для того, что раньше выполнялось в одну строчку. Охрененная инновация. И ты ещё намекаешь, что ничего не ухудшилось.
Сквозняк писал(а):Из окошка, из буттонклик вриттелн отправить. И скомпилировать так, как лазарус по умолчанию компилирует. Тогда и будет ошибка. Раньше, на вин32 этого бага не было.
Из оконного приложения такое было всегда. Вне зависимости от битности. Вы ничего не путаете? Другое дело, если Вы пишете консольное приложение. В нём этот самый "файл" для вывода в консоль создаётся автоматически. В окошечном его нет и никогда не было. Так что абсолютно ничего не изменилось и не испортилось.
- Снег Север
- долгожитель
- Сообщения: 3067
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
Сквозняк писал(а):Для простого посылания сообщения разводишь конструкторы-деструкторы, класс создаёшь, подтягиваешь кучу зависимостей. У writeln в документации таких условий для применения нет.
Я просто делаю правильно. А если кто привык к халтуре, то он сам себе злобный буратино.
Vadim писал(а):Сквозняк писал(а):Из окошка, из буттонклик вриттелн отправить. И скомпилировать так, как лазарус по умолчанию компилирует. Тогда и будет ошибка. Раньше, на вин32 этого бага не было.
Из оконного приложения такое было всегда. Вне зависимости от битности. Вы ничего не путаете? Другое дело, если Вы пишете консольное приложение. В нём этот самый "файл" для вывода в консоль создаётся автоматически. В окошечном его нет и никогда не было. Так что абсолютно ничего не изменилось и не испортилось.
Не всегда так работает. В линуксе ошибки нет. А в виндовсе лазарус конкретно не указывает, оконное это приложение или консольное. Нет в тексте программы соответствующей директивы компилятора. К какому типу приложений отнесёт его ОС - это вопрос философский. Сейчас перетестил большое вин32 приложение, которое якобы графическое - там ошибки нет. А создал новое пустое - ошибка есть. То есть в винде понятие графического или консольного приложения размыто и ущербно и может самопроизвольно меняться в процессе роста или оптимизации программы.
Код: Выделить всё
procedure Writeln( Args: Arguments);
procedure WriteLn( var F: Text; Args: Arguments);Вот как распознающая система может перепутать эти две процедуры? У одной процедуры вводимый параметр типа "файл", а у другой - остальные. И при этом в винде они путаются. WriteLn читающая файлы однозначно должна получить переменную файлового типа, это на этапе компилирования уже должно быть понятно, но нет - это решается при выполнении, как в каком-нибудь питоне.
Добавлено спустя 2 минуты 18 секунд:
Снег Север писал(а):Сквозняк писал(а):Для простого посылания сообщения разводишь конструкторы-деструкторы, класс создаёшь, подтягиваешь кучу зависимостей. У writeln в документации таких условий для применения нет.
Я просто делаю правильно. А если кто привык к халтуре, то он сам себе злобный буратино.
Ты не по документации делаешь а тупо лепишь побольше хаков чтобы рандомом подцепить нужные зависимости. Виндовая версия фпс сделана по остаточному принципу и ты просто замазываешь баги.
- Снег Север
- долгожитель
- Сообщения: 3067
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
Сквозняк писал(а):Ты не по документации делаешь а тупо лепишь побольше хаков
Ну что за бред... Чтобы ты знал, это - дефолтный шаблон консольного приложения лазаря, который создается для нового проекта. В который я добавил ровно две строчки.
Т.е. это пример как правильно от самих разработчиков.
А проблемы рукожопых красноглазиков никого не волнуют.
Добавлено спустя 10 минут 20 секунд:
ЗЫ. Разработчики дают пример правильного конструирования кроссплатформенных приложений. Именно для того, чтобы всё работало строго одинаково под разными системами. А кто воображает, что "по документации" всё должно работать одинаково святым духом, тот э-э-э... не совсем гений...
"Консольность" приложения может быть указана явно в программе, а может - в свойствах проекта. Чтобы использовать Writeln, нужно проверить, чтобы было то или это. Ну и в юниксах тип приложений роли не играет. Просто в Windows в консольном приложении обязательно будет висеть окно консоли, которое будет в большинстве случаев мешать обычным пользователям, но очень полезно для отладки. А под иксами - это не надо, запустишь из консоли - будет идти вывод в консоль, иначе этот вывод будет теряться, что, собственно, и надо.
Сквозняк писал(а):Не всегда так работает. В линуксе ошибки нет.
Вы не можете ничего понять по той причине, что путаете понятия.
Да, сравнить их соблазнительно, но неправильно. Вам не приходило в голову, что несмотря на одинаковое название (writeln) реализация в разных ОС может быть разная?
Снег Север писал(а):Сквозняк писал(а):Ты не по документации делаешь а тупо лепишь побольше хаков
Ну что за бред... Чтобы ты знал, это - дефолтный шаблон консольного приложения лазаря, который создается для нового проекта. В который я добавил ровно две строчки.
Т.е. это пример как правильно от самих разработчиков.
А проблемы рукожопых красноглазиков никого не волнуют.
Добавлено спустя 10 минут 20 секунд:
ЗЫ. Разработчики дают пример правильного конструирования кроссплатформенных приложений. Именно для того, чтобы всё работало строго одинаково под разными системами. А кто воображает, что "по документации" всё должно работать одинаково святым духом, тот э-э-э... не совсем гений...
Рукожопые виндузятники совсем не в курсе что их "код" может выполняться и так и эдак.
Код: Выделить всё
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
writeln('12345 йцукен');
end;
end.При выполнении в лазарусе будет конечно баг. Но кто кроме рукожопых виндузятников сложный проект будет каждый раз так собирать?
Для запуска он соберётся как-нибудь так:
Код: Выделить всё
#сборка без бага при выполнении Writeln
rm *.o
rm *.ppu
rm *.obj
wine cmd.exe /c "C:lazarus-2.0.4-fpc-3.0.4-win64fpc3.0.4binx86_64-win64fpc.exe -FuC:lazarus-2.0.4-fpc-3.0.4-win64lclunitsx86_64-win64win32 -FuC:lazarus-2.0.4-fpc-3.0.4-win64lclunitsx86_64-win64 -FuC:lazarus-2.0.4-fpc-3.0.4-win64componentslazutilslibx86_64-win64 -FuC:lazarus-2.0.4-fpc-3.0.4-win64packagerunitsx86_64-win64 -dLCL -dLCLwin32 project1.lpr"И усё будет работать без этого вантузятного бага. Код один и тотже - где тут написано что в одном случае приложение консольное, а в другом неконсольное?
Добавлено спустя 15 минут 52 секунды:
Vadim писал(а):Сквозняк писал(а):Не всегда так работает. В линуксе ошибки нет.
Вы не можете ничего понять по той причине, что путаете понятия.Говорить то начали о винде, а тут вдруг раз, и ни с того ни с сего Линукс выполз. С чего это, интересно...
![]()
Да, сравнить их соблазнительно, но неправильно. Вам не приходило в голову, что несмотря на одинаковое название (writeln) реализация в разных ОС может быть разная?
А с того, что программа должна работать и там и там. И реализация writeln совсем не причём. В паскале имеется две таких процедуры с одинаковыми именами. В линуксе они не путаются, а в винде - путаются. Если путаются, то это баг. Также как в 64 битной винде происходит путаница при умножении на константу. Когда константа равна 120, то всё работает нормально, а когда 141 - у вас баг при компиляции! http://freepascal.ru/forum/viewtopic.php?f=1&t=42820
Можно сказать, что использование Round в том примере излишнее, но константы вместо чисел для того и используются в программах, чтобы их было удобно править в одном месте, а результат изменялся в куче исходников. А что получается в 64 битной винде? Есть какой-то коэффициент, сначала он равен 121.5 и всё нормально, потом его понадобилось сменить на 120 и тоже всё нормально, а потом сменился на 141 и в 64 битной винде баг. Сколько ни кричите, что это фича, но если объяснять что это правильная фича адептам других языков, то они скажут: ну и говно же ваши дельфи/паскаль.
Сквозняк писал(а):Если путаются, то это баг.
Вы сюда зря с этим обращаетесь.
Не сердитесь.
- Снег Север
- долгожитель
- Сообщения: 3067
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
Сквозняк писал(а): Если путаются, то это баг.
Путаются они только в вашей голове. В винде работает так, как должно работать. Поскольку паскаль и все его производные писались для доса/винды, а только много времени спустя портировались на другие платформы. Если вы в линуксе использовали какой-то местный хак, то никто вам никогда не обещал, что этот хак должен работать в винде.
