Console Mode Pascal/zh CN
│
Deutsch (de) │
English (en) │
español (es) │
suomi (fi) │
magyar (hu) │
日本語 (ja) │
русский (ru) │
slovenčina (sk) │
中文(中国大陆) (zh_CN) │
Pascal 控制台模式编程
在[[[Graphical User Interface|图形用户界面]](GUI)和集成开发环境(IDE)尚未流行时,很多人就已经开始编写 Pascal 程序了。还有许多人刚开始学习 Pascal 编程,需要能简单测试一下。另外还有些人则需要编写控制台或文本模式的应用程序,以便执行复杂的系统控制任务。
不用 Lazarus 进行控制台模式编程
虽然很多人愿意用 Lazarus IDE 编写控制台程序,但用任一文本编辑器编写代码,再用FPC 编译器进行编译,也是没问题的。假设程序名为 example.pas,则可以如下执行编译:
fpc example.pas
此外还可以用 fp IDE(有点类似以前的Turbo Pascal)。 后续内容主要介绍使用 Lazarus 编程。
用 Lazarus 进行控制台模式编程
Lazarus 为学习 Pascal 语言和开发文本模式程序提供了理想的环境。集成开发环境的所有功能均有提供,包括带语法高亮功能的源代码编辑器、访问已有程序库、复杂搜索和代码补全工具、语法检查。如果用不到带有可视化组件的Form,那 Lazarus 就不是必需的,但 Lazarus 的源代码编辑器依然是程序开发的绝佳环境。这样在开发过程中,不用离开编辑器即可编译和运行程序。
若要创建一个控制台模式的程序,请在主菜单选择“项目”->“新建项目”,然后选择“程序”或“控制台应用程序”。IDE 不会生成完整GUI程序关联的全部文件,也不会打开对象查看器,而会打开源代码编辑器并给出框架代码,等待输入。
项目类型:控制台应用程序
在 Lazarus 中选择这种项目类型,将会创建一个派生自 TCustomApplication 的新类。TCustomApplication 提供了很多常用功能,编写命令行程序会更为轻松。例如,检查命令行参数、编写帮助信息、检查环境变量、处理异常。所有 LCL 程序都自动拥有这些功能。
项目类型:程序
作为演示,下面给出一个十分简化的 Pascal 程序。在 IDE 中选择“程序”项目类型,IDE 会提供一些辅助功能。比如在添加其他单元时,IDE 会自动将该单元的名称加入uses部分。这是在项目选项中定义的。因此“程序”和“自定义程序”类型之间可以随时切换。
下面是给小白看的一个示例:
program Project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes;
begin
WriteLn('Hello World!');
ReadLn;
end.
Pascal 脚本
此外,还可以编写由InstantFPC动态编译的脚本,InstantFPC 是一个跨平台解决方案,能以脚本的形式运行(小型)Pascal 程序。shebang
#!/usr/bin/env instantfpc
即可像运行独立程序一样执行脚本。
运行程序
编译
程序(或程序片段)编写完成后,可从主菜单中选择“运行”->“构建”(或“快速编译”),或者点击按钮栏中的绿三角(运行),即可编译并运行。所有编译器信息(警告、进度或错误消息)都会在消息框中显示,幸运的话最终会显示一条消息:
'Project "Project1" successfully built.:)'
可是程序在哪里呢??!!
如果程序尚未保存过,那么 IDE 会将其放入临时目录(例如,在 Linux 下是 /tmp,在 Windows 下是 C:\temp,参见“工具/选项/环境/文件/项目构建测试的目录)。
如果项目已经保存过了,那么程序会在 project1.lpi 同目录下创建。
在控制台中运行
进入控制台(终端)窗口,用cd命令修改当前目录,键入程序名称,即可执行程序。在 Unix/Linux 中,如果程序位于当前目录,必须在程序名前面加上 ./,因为由 PATH 可能会找不到程序。
以下是 Linux/Unix 中的例子,程序存于 /tmp 下:
cd /tmp
./Project1
不过,在 Lazarus 编辑器和终端窗口之间不停地切换,可能很不方便。幸运的是,有一种机制允许在 Lazarus 中直接打开终端窗口。
在 IDE 中运行
在内部控制台:终端输出窗口中运行。
重定向输出。
在主菜单选择“运行->运行参数”,选中“使用开始(launching)应用程序”。第一次运行会执行编译、运行的步骤,可能会直接收到一条信息:
"xterm: Can't execvp /usr/share/lazarus//tools/runwait.sh: Permission denied".
这时需修改对应文件的权限(比如用 chmod +x 文件名 命令,或者用 Windows 的修改权限功能);可能需要以管理员身份才能修改权限。之后每次启动程序,都会出现一个控制台窗口,所有的文本输入/输出(如 readln、writeln 等)都会显示在该窗口中。
程序执行完毕后,屏幕上会显示“Press enter”。因此程序产生的输出都会保留在屏幕上,以供阅读;按下“回车”键将会关闭控制台窗口。
在 Linux 系统中,如果勾选“使用开始(launching)应用程序”后没有出现上述“xterm: Can't execvp /usr/share/lazarus//tools/runwait.sh: Permission denied”,请键入/usr/bin/xterm $(TargetCmdLine)
并勾选“使用开始(launching)应用程序”(几乎所有 Linux 系统都安装 xterm 了)。
很遗憾,这种运行模式不支持集成调试器。
在 IDE 中运行并重定向输出
若要看到写入 stdout 的结果且要使用集成调试器,可以将 stdout 重定向至一个文件,代码如下:
uses
baseunix;
var
OutputFile: text;
begin
Assign(OutputFile, 'Output.txt');
if FileExists(Filename) then begin
Append(OutputFile);
end
else begin
Rewrite(OutputFile); { 打开文件以供写入,清空原有内容 }
end;
ResultCode := fpdup(OutputFile, output);
if ResultCode < 0 then begin
raise Exception.CreateFmt('dup failed: %s', [ResultCode]);
end;
Close(OutputFile);
end.
Output.txt 可用“tail -f output.txt”命令查看,如果操作系统不提供“tail”程序则可用文本编辑器打开。
在 Lazarus 0.9.31 以上版本(仅限 Linux 系统)中,还可以用“查看”菜单下的“调试窗口/控制台输出”查看 stdout。
Unicode(UTF8)输出
若要控制台程序在 Windows Vista 以上版本(或更低版本)中显示 Unicode(UTF8)输出结果,可用SetConsoleOutputCP命令将控制台设为 UTF8 字符集。
关于 Lazarus 和 FPC 对 Unicode 的支持, 详见 LCL Unicode 支持。
例程如下:
program uniconsole;
{$mode objfpc}{$H+}
{$APPTYPE CONSOLE}
uses
{$IFDEF UNIX}
{$IFDEF UseCThreads}
cthreads,
{$ENDIF}
{Widestring manager needed for widestring support}
cwstring,
{$ENDIF}
{$IFDEF WINDOWS}
Windows, {for setconsoleoutputcp}
{$ENDIF}
Classes
;
var
UTF8TestString: string;
begin
{$IFDEF WINDOWS}
SetConsoleOutputCP(CP_UTF8);
{$ENDIF}
UTF8TestString:= 'rosé, водка and ούζο';
writeln ('plain: ' + UTF8TestString);
{显然这里不需要用到 UTF8ToConsole,其实 UTF8ToConsole 也无效。}
end.
在 Windows 控制台输出 CJK 文本
以下示例来自论坛成员Thaddy,演示了如何正确设置 Windows 控制台以支持 CJK 文本。
{$mode delphiunicode}{$H+}
{$codepage utf8}
uses Windows, SysUtils;
var
s3, s1, s2: string;
var
cfi: CONSOLE_FONT_INFOEX;
begin
cfi.cbSize := SizeOf(cfi);
cfi.nFont := 0;
cfi.dwFontSize.X := 0;
cfi.dwFontSize.Y := 20;
cfi.FontFamily := FF_DONTCARE;
cfi.FontWeight := FW_NORMAL;
// two fonts that support Chinese etc.
cfi.Facename := 'NSimSun';
// cfi.FaceName := 'SimSun-extB'; // 这是个光栅字体
SetTextCodePage(Output, CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), False, @cfi);
s1 := '春夏';
s2 := '秋冬';
s3 := s1+s2;
Writeln('s1=', s1,' s2=', s2, ' s3=', s3);
Readln;
end.
示例
只要是标准 Pascal 教材中的示例,均可用 Lazarus 编辑器进行试验,也可以编写自己的程序。最有用的是那些执行系统命令或运行其他程序的过程(这些外部程序可以是用 Pascal、C、Perl 编写的,也可以是 shell 或批处理脚本)。
执行 shell 命令
以下是执行自定义程序或系统自带程序的示例,不过是 Linux/Unix/macOS 系统特有的:
program TryShell;
uses
Classes, Unix;
var
S: LongInt;
begin
S := fpsystem('/bin/ls -la *.p*'); //lists .pp, .pas, .php, .png etc in current directory
WriteLn('Program exited with status : ', S)
end.
更新 FPC 和 Lazarus 的示例
还可以执行一些更复杂的命令。比如在签出 FPC 和 Lazarus 的 SVN 库(参见buildfaq)后,可通过以下调用从 SVN 存储库中获取 FPC 和 Lazarus 的最新源代码:
program LazUpdate;
uses
Classes, Unix;
var
S: LongInt;
begin
S := fpsystem('cd /usr/local/src/fpc/devel/fpc ; make clean');
S := fpsystem('cd /usr/local/src/fpc/devel/lazarus ; make clean');
S := fpsystem('cd /usr/local/src/fpc/devel ; svn update fpc >& ~/cvscheckout.log');
S := fpsystem('cd /usr/local/src/fpc/devel ; svn update lazarus >& ~/cvslaz.log' );
end.
请注意,以下命令:
fpsystem('cd /somedirectory');
紧跟着以下命令
fpsystem ('do something in that subdirectory');
无法生效,因为每次调用fpsystem()函数后,程序都会返回初始目录再执行;因此,通过fpsystem()调用 shell 命令时,需在一行中放入多条命令。(更准确的说法是:fpsystem 总是从当前目录开始执行)
不一定要把每条命令都写成一条 Pascal 语句;可以如下创建bash脚本文件(来自buildfaq):
#!/bin/sh
cd /usr/local/src/fpc/devel
cd fpc
make clean
cd ..
cd lazarus
make clean
cd ..
svn up fpc >& ~/cvscheckout.log
svn up lazarus >& ~/cvslaz.log
将其命名为 updatelaz.sh,然后不是直接用bash去调用,而是用 Pascal 程序去调用:
(* This can be compiled or used as a Pascal script *)
program LazUpdate1;
uses
Classes, Unix;
var
S: LongInt;
begin
S := fpsystem('updatelaz.sh')
end.