前几天买了《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. */ void err_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. */ void err_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. */ void err_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. */ void err_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. */ void err_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. */ void err_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 void err_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目录下面的内容了