前几天买了《UNIX环境高级编程》这本书,想好好学习下linux的编程。谁知道看到第一个列出指定目录的内容的那个例子,其实就是shell中 ls 的内容,打好代码要运行时一直出问题。后来在网上找了挺多的解决方法,终于解决了。先把方法贴上。
先在终端里面输入 vi ls.c在里面编辑如下代码
#include "apue.h"
#include
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 /* for definition of errno */
#include /* 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
在运行程序
gcc ls.c
./a.out /home
就可以看到你home目录下面的内容了