getch()、_sleep() 函数的正确用法

前段时间由于需要,写了一段代码,用到了函数 getch(),但是当时出错了,提示该标识符未被定义,一时无解。后来又有一个朋友,问我怎么将一个字符串中的字符以一种动态的方式进行输出,我当时告诉他的是使用 sleep() 函数,也没有细想,后来发现,根本不存在 sleep() 这个函数。这个糗可是出大发了!

在很多的官方的与非官方的教程中,getch() 都是定义在头文件 stdlib.h 中的,甚至还有的说,是在 stdio.h 中。比如下面的例子:

#include 
void main()
{
    puts("Hello World!");
    getch();
}

看着好像很高深莫测的样子,但是一看,嘿!getch() 函数可没有在 stdio.h 里面定义呢!
先不说别的,尝试编译,提示“test.cpp(5) : error C2065: ‘getch’ : undeclared identifier”,看来果真不是在 stdio.h 里。

那么 getch() 到底定义在哪里呢?

通过阅读 c++ 的头文件,可以发现,在 conio.h 中定义了如下内容:
CONIO.H

_CRTIMP int __cdecl _getch(void);

那我们现在再来试试,包含了 conio.h 文件后,又是一个怎么样的结果:

#include 
#include 
void main()
{
    puts("Hello World!");
    getch();
}

尝试编译,成功通过。在 cmd 里执行也通过。

看来,的确是尽信书不如无书。连教程都能出错。现在我们干掉了一个 getch(),可还剩下一个 sleep() 呢?前文说了,这个函数,在头文件里根本就不存在。那我们无论如何也是找不到这个函数的。不过,找不到它,我们还可以试着去找和它长的很像的其他的函数。

事实证明,在不借助网络,不借助 msdn 和其他任何操作手册的情况下,找一个函数最好的方法就是在头文件所在的文件夹中用 find。
C:\Program Files\Microsoft Visual Studio\VC98\Include> find *.h “sleep” /i
共搜索到如下结果:

//---------- MAPIWIN.H
void WINAPI     Sleep(DWORD dwMilliseconds);
//---------- STDLIB.H
_CRTIMP void __cdecl _sleep(unsigned long);
//---------- WINBASE.H
WINBASEAPI VOID WINAPI Sleep(DWORD dwMilliseconds);

可见,MapiWin.h 和 WinBase.h 中关于 Sleep() 函数的定义实际上是一样的。
测试过程我就略过了,当然我肯定是测试过,不过就不在这儿写了,现在,贴上应用 stdlib.h 中的 _sleep() 的代码。

//Using _sleep() declared in stdlib.h
#include 
#include 
void main()
{
    int i=6;
    for(;--i;_sleep(1000)) 
        printf("%d\r", i);
    printf("Boom!\n");
}

stdlib.h 中的 _sleep() 一帆风顺,可是 WinBase.h 中的 Sleep() 却有些不靠谱。经测试,在只包含 WinBase.h 的情况下无法编译成功。原因是一些自定义类型没有定义,例如 DWORD 和 HANDLE 一类。因为我查看了 WinBase.h 的内容,并没有定义这些类型,也没有包含含有这些类型的文件。那么现在该怎么办呢?

还记得有一个头文件 windows.h 吗?在该文件第 164 行(不同版本的可能有差别),有一处#include “winbase.h”,而且显然,windows.h 里面定义了各种的数据类型(#include “windef.h”),那么包含 windows.h,是否能够调用 Sleep() 了呢?经测试,答案是肯定的。这里就不详述测试的过程了,直接贴代码

//Using Sleep() declared in WinBase.h
//Including windows.h instead for more supportings.

#include 
//#include 
#include 

void main()
{
    int i=6;
    for(;--i;Sleep(1000)) printf("%d\r", i);
    printf("Boom!\n");
}

看来,有些时候,不是定义了函数,就可以使用的。

不过,在这里我还要多说一点是,虽然在实际的代码中,我们 #include 的是 windows.h 文件,但我们不能说 Sleep() 就是 windows.h 中定义的。毕竟,它只是在 windows.h 中又包含了 WinBase.h。

好了,来一个文末总结——

  1. getch() 函数定义在头文件 conio.h 中,函数声明为
    _CRTIMP int __cdecl _getch(void);

  2. _sleep() 函数定义在头文件 stdlib.h 中,函数声明为
    _CRTIMP void __cdecl _sleep(unsigned long);

  3. Sleep() 函数定义在头文件 WinBase.h 中,不过使用的时候应包含的是 windows.h 头文件而非 WinBase.h,函数声明为
    WINBASEAPI VOID WINAPI Sleep(DWORD dwMilliseconds);

你可能感兴趣的:(C++)