linux下运行《UNIX环境高级编程》的第一个程序时源码编译出错的处理方法

来源:互联网 发布:saas软件模式 编辑:程序博客网 时间:2024/04/30 00:21

前几天买了《UNIX环境高级编程》这本书,想好好学习下linux的编程。谁知道看到第一个列出指定目录的内容的那个例子,其实就是shell中 ls 的内容,打好代码要运行时一直出问题。后来在网上找了挺多的解决方法,终于解决了。先把方法贴上。

先在终端里面输入 vi ls.c在里面编辑如下代码

#include "apue.h"#include <dirent.h>           int main(int argc, char *argv[])   {           DIR                             *dp;           struct dirent   *dirp;                   if (argc != 2)                   err_quit("usage: ls directory_name"); //请输入文件名                  if ((dp = opendir(argv[1])) == NULL)                   err_sys("can't open %s", argv[1]);  //不能打开文件         while ((dirp = readdir(dp)) != NULL)                   printf("%s\n", dirp->d_name);                   closedir(dp);           exit(0);   }   

再保存退出.进行编译  如gcc ls.c会出现如下的错误。

ls.c:1:19: apue.h: No such file or directory
ls.c: In function `main':
ls.c:13: error: `NULL' undeclared (first use in this function)
ls.c:13: error: (Each undeclared identifier is reported only once
ls.c:13: error: for each function it appears in.)


解决方法:

因为apue.h是作者自定义的一个头文件,包括程序所需的常用头文件及出错处理函数。所以因该将它放入系统头文件中(Linux下是 /usr/include),这样gcc编译器就可以找到它了。所以先去作者提供网站http://www.apuebook.com/apue2e.html下的 Suorce code 下 的src.2e.tar.gz包,然后解压至电脑中的某个目录,比如我的是在/home/xxx(你的登录名)/下,然后进入解压目录apue.2e,修改Make.defines.linux中的WKDIR=/home/xxx/apue.2e,为WKDIR=/home/user/apue.2e,这就是我们将要make的工作目录,然后再进入std目录,用vi打开linux.mk,将里面的nawk全部改为awk

接下里拷贝apue.h到系统默认头文件目录中(这个目录是/usr/include)

首先要先却换到root用户 

然后把apue.2e/include下的apue.h拷贝到 /usr/include
运行下面的命令 #cp /home/xxx/apue.2e/include/apue.h /usr/include

回到ls.c文件在的目录运行程序

会出现下面的错误:
: undefined reference to `err_quit'
: undefined reference to `err_sys'

解决办法:
因为err_quit跟err_sys是作者自己定义的错误处理函数,需要单独定义头文件

在/usr/include 下新建一个名为myerr.h的文件

里面的内容为

#include "apue.h"#include <errno.h>      /* for definition of errno */#include <stdarg.h>     /* ISO C variable aruments */static void err_doit(int, int, const char *, va_list);/** Nonfatal error related to a system call.* Print a message and return.*/voiderr_ret(const char *fmt, ...){    va_list     ap;    va_start(ap, fmt);    err_doit(1, errno, fmt, ap);    va_end(ap);}/** Fatal error related to a system call.* Print a message and terminate.*/voiderr_sys(const char *fmt, ...){    va_list     ap;    va_start(ap, fmt);    err_doit(1, errno, fmt, ap);    va_end(ap);    exit(1);}/** Fatal error unrelated to a system call.* Error code passed as explict parameter.* Print a message and terminate.*/voiderr_exit(int error, const char *fmt, ...){    va_list     ap;    va_start(ap, fmt);    err_doit(1, error, fmt, ap);    va_end(ap);    exit(1);}/** Fatal error related to a system call.* Print a message, dump core, and terminate.*/voiderr_dump(const char *fmt, ...){    va_list     ap;    va_start(ap, fmt);    err_doit(1, errno, fmt, ap);    va_end(ap);    abort();        /* dump core and terminate */    exit(1);        /* shouldn't get here */}/** Nonfatal error unrelated to a system call.* Print a message and return.*/voiderr_msg(const char *fmt, ...){    va_list     ap;    va_start(ap, fmt);    err_doit(0, 0, fmt, ap);    va_end(ap);}/** Fatal error unrelated to a system call.* Print a message and terminate.*/voiderr_quit(const char *fmt, ...){    va_list     ap;    va_start(ap, fmt);    err_doit(0, 0, fmt, ap);    va_end(ap);    exit(1);}/** Print a message and return to caller.* Caller specifies "errnoflag".*/static voiderr_doit(int errnoflag, int error, const char *fmt, va_list ap){    char    buf[MAXLINE];   vsnprintf(buf, MAXLINE, fmt, ap);   if (errnoflag)       snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s",         strerror(error));   strcat(buf, " ");   fflush(stdout);     /* in case stdout and stderr are the same */   fputs(buf, stderr);   fflush(NULL);       /* flushes all stdio output streams */}


接下来在ls.c里面引用#include<myerr.h>就好了

在运行程序
gcc ls.c 

./a.out /home

就可以看到你home目录下面的内容了

3 1
原创粉丝点击