回 目 录
上 一 章 下 一 章

# 第二章：从Hello World 程序开始

  欢迎来到NCURSES的世界。在我们踏上学习NCURSES的路途之前，让我们先写一个小程序，来了解一下NCURSES的执行结构。

### 2.1 编译包含NCURSES函数的程序

  如果要调用NCURSES库中的函数，你必须在代码中加载ncurses.h文件，就是在C或C++程序中添加“#include ”这一行。然后在连接程序中标记出NCURSES。（注：NCURSES库已经包含了“stdio.h”）

    #include <ncurses.h>
    .
    .
    .
    compile and link: gcc <程序文件> -lncurses

例1：Hello World !!!程序

    #include <ncurses.h>

    int main()
    {
    	initscr();					/* 初始化，进入NCURSES模式	  		*/
    	printw("Hello World !!!");		/* 在虚拟屏幕上打印Hello, World!!!		*/
    	refresh();					/* 将虚拟屏幕上的内容写到显示器上，并刷新*/
    	getch();					/* 等待用户输入					*/
    	endwin();					/* 退出NCURSES模式		  		*/
    	return 0;
    }

### 2.2 示例剖析（Dissection）

  这个程序在显示器屏幕上打印“Hello World !!!”后等待用户按任意键退出。这个小程序展示了如何初始化并进入curses模式、处理屏幕操作和退出curses模式。让我们逐行的分析这个小程序：
2.2.1 关于 initscr() 函数

  initscr()函数将终端屏幕初始化为curses模式。它用来清除屏幕上所有的字符，使屏幕变为空白，等待下一部处理。所以在调用其它的NCURSES函数前，都要先调用initscr()函数初始化屏幕。这个函数初始化了curses系统并且为当前屏幕，也就是一个叫做被“stdscr”的窗口以及其它的数据结构分配内存。在以前的计算机上曾经出现过一个非常极端的例子：因为系统中的可用内存太小，以至于initscr()函数无法分配足够的内存给相关的数据结构，从而导致curses系统初始化失败。我们将在以后的章节中详细介绍如何定制屏幕的初始化模式。
2.2.2 神秘的refresh() 函数

  第二行的printw函数用于把字符串“Hello，World！！！”输出到虚拟的屏幕上。这个函数用法上和printf()函数很像。但是区别在于，printw函数把字符串输出到被称作“stdscr”的虚拟坐标（0,0）上。从显示的结果来看，坐标（0,0）在屏幕的左上角上。

  现在该说说这个神秘的refresh()函数了。在我们使用printw函数打印“Hello World！！！”时，实际上这个数据被打印到一个叫作“stdscr”的虚拟窗口上，没有被直接输出到屏幕上。printw()函数的作用是不断将一些显示标记和相关的数据结构写在虚拟显示器上，并将这些数据写入stdscr的缓冲区内。所以，为了显示这些缓冲区中的数据我们必须使用refresh（）函数告诉curses系统将缓冲区的内容输出到屏幕上。

  这种机制可以使程序员不断在虚拟屏幕上写入数据，而调用refresh（）函数时让一切看起来似乎是一次完成的。因为refresh（）函数只核查窗口和数据中变动的部分，这种富有弹性的设计提供了一个高效的反馈机制。但是这有时很打击初学者的积极性。因为对于初学者来说忘记在输出后调用refresh()函数是很恼人的错误。不过不用担心，因为很多人也经常犯这样的错误。
2.2.3关于endwin()函数(About endwin())

  最后，别忘了要结束curses显示模式才可以返回到普通字符行模式。否则，在程序结束后你的终端可能会运转得不正常。endwin()函数释放了curses子系统和相关数据结构的内存，使你的终端回到普通字符模式。这个函数必须是在你完成所有的curses操作以后才可以调用。（译者注：如果你在endwin()函数后再调用curses的函数。很显然，那些语句不会执行。说到这里，顺便提醒一下。如果你的程序不能正常地显示东西了。请务必看看initscr()函数和endwin()函数是不是在不该被调用的地方调用了。）

  说到这里，顺便提醒一下。如果你的程序不显示东西了。请务必看看initscr()函数和endwin()函数是不是在不该被调用的地方调用了！
回 目 录
上 一 章 下 一 章