C 如何使用Unix系统调用打印文本文件的前10行?
我想编写自己版本的C 如何使用Unix系统调用打印文本文件的前10行?,c,linux,unix,C,Linux,Unix,我想编写自己版本的headUnix命令,但我的程序无法运行 我试图打印文本文件的前10行,但程序打印所有行。我通过命令行参数指定文件名和要打印的行数。我只需要使用Unix系统调用,如read()、open()和close() 代码如下: #include "stdlib.h" #include "stdio.h" #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #define BUFFER
head
Unix命令,但我的程序无法运行
我试图打印文本文件的前10行,但程序打印所有行。我通过命令行参数指定文件名和要打印的行数。我只需要使用Unix系统调用,如read()
、open()
和close()
代码如下:
#include "stdlib.h"
#include "stdio.h"
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFERSZ 256
#define LINES 10
void fileError( char*, char* );
int main( int ac, char* args[] )
{
char buffer[BUFFERSZ];
int linesToRead = LINES;
int in_fd, rd_chars;
// check for invalid argument count
if ( ac < 2 || ac > 3 )
{
printf( "usage: head FILE [n]\n" );
exit(1);
}
// check for n
if ( ac == 3 )
linesToRead = atoi( args[2] );
// attempt to open the file
if ( ( in_fd = open( args[1], O_RDONLY ) ) == -1 )
fileError( "Cannot open ", args[1] );
int lineCount = 0;
//count no. of lines inside file
while (read( in_fd, buffer, 1 ) == 1)
{
if ( *buffer == '\n' )
{
lineCount++;
}
}
lineCount = lineCount+1;
printf("Linecount: %i\n", lineCount);
int Starting = 0, xline = 0;
// xline = totallines - requiredlines
xline = lineCount - linesToRead;
printf("xline: %i \n\n",xline);
if ( xline < 0 )
xline = 0;
// count for no. of line to print
int printStop = lineCount - xline;
printf("printstop: %i \n\n",printStop);
if ( ( in_fd = open( args[1], O_RDONLY ) ) == -1 )
fileError( "Cannot open ", args[1] );
//read and print till required number
while (Starting != printStop) {
read( in_fd, buffer, BUFFERSZ );
Starting++; //increment starting
}
//read( in_fd, buffer, BUFFERSZ );
printf("%s \n", buffer);
if ( close( in_fd ) == -1 )
fileError( "Error closing files", "" );
return 0;
}
void fileError( char* s1, char* s2 )
{
fprintf( stderr, "Error: %s ", s1 );
perror( s2 );
exit( 1 );
}
#包括“stdlib.h”
#包括“stdio.h”
#包括
#包括
#包括
#定义缓冲区sz 256
#定义第10行
无效文件错误(字符*,字符*);
int main(int ac,char*args[]
{
字符缓冲区[BUFFERSZ];
int linesToRead=行;
int in_fd,rd_chars;
//检查参数计数是否无效
如果(ac<2 | | ac>3)
{
printf(“用法:头文件[n]\n”);
出口(1);
}
//检查n
如果(ac==3)
linesToRead=atoi(args[2]);
//尝试打开该文件
如果((in_fd=open(args[1],O_RDONLY))=-1)
文件错误(“无法打开”,参数[1]);
int lineCount=0;
//计数文件中的行数
while(读取(在缓冲区中,1)==1)
{
如果(*缓冲区=='\n')
{
lineCount++;
}
}
lineCount=lineCount+1;
printf(“行数:%i\n”,行数);
int起始=0,xline=0;
//xline=总计行-所需行
xline=行数-行存储AD;
printf(“xline:%i\n\n”,xline);
if(xline<0)
xline=0;
//要打印的行数的计数
int printStop=lineCount-xline;
printf(“打印停止:%i\n\n”,打印停止);
如果((in_fd=open(args[1],O_RDONLY))=-1)
文件错误(“无法打开”,参数[1]);
//阅读并打印至所需编号
同时(启动!=打印停止){
读取(in_fd,buffer,BUFFERSZ);
启动+++;//增量启动
}
//读取(in_fd,buffer,BUFFERSZ);
printf(“%s\n”,缓冲区);
如果(关闭(在fd中)=-1)
fileError(“关闭文件时出错”,即“”);
返回0;
}
无效文件错误(字符*s1,字符*s2)
{
fprintf(标准,“错误:%s”,s1);
perror(s2);
出口(1);
}
我做错了什么?非常奇怪的是,你打开文件,扫描它以计算总行数,然后继续回显第一行。在你开始回音之前,绝对不需要预先知道总共有多少行,这对你没有任何用处。但是,如果要执行此操作,则应在重新打开文件之前
close()
。对于您的简单程序,这是一个良好形式的问题,而不是正确功能的问题——您观察到的错误行为与此无关
您的计划的关键部分存在几个问题:
read()
调用的返回值。您必须检查它,因为它不仅告诉您是否存在错误/文件结尾,还告诉您实际读取了多少字节。不能保证在任何调用时都填充缓冲区,只有这样才能知道缓冲区的哪些元素随后包含有效数据。(预计数行在这方面对您没有任何帮助。)read()
s,并且显然假设每一个都只读取一行。这种假设是无效的read()
不会对行终止符进行任何特殊处理,因此可能会有跨多行的读取,以及只读取部分行的读取(可能在同一读取中同时读取)。因此,不能通过计算read()
调用来计算行数。相反,您必须扫描读取缓冲区中的有效字符,并计算其中的换行printf()
,就好像它是一个以null结尾的字符串一样,但不确保它实际上是以null结尾的read()
不适合您我很难相信你的说法,你的程序总是打印指定文件的所有行,但我可以相信它打印你正在测试的特定文件的所有行。如果文件足够短,整个文件都可以放入缓冲区,那么它可能会这样做。然后,您的程序可能会在第一次调用
read()
时将整个内容读入缓冲区(尽管不能保证这样做),然后在随后的每次调用中都不读取任何内容,返回-1并保持缓冲区不变。最后打印缓冲区时,它仍然包含文件的全部内容。次要:为什么在int main(int ac,char*args[])
中使用ac,args
而不是非常常见的argc,argv
?请查看源代码:在fileError中,调用peror
是错误的。fprintf可能修改了errno,您将得到意外的结果。倒带文件也是一个选项(而不是重新打开)lseek(fd,0L,SEEK\u SET)就可以了,IIRC.@John Bollinger现在你一定已经意识到我是C语言编程新手了。我很感激你的输入,但我仍然不确定如何修复和更改我的代码,以便通过打印前10行代码来正确运行我的程序。如果您能帮我修改代码,我将不胜感激。@bmalhi,我已经帮过您了。自己计算细节对你有好处。@JohnBollinger你能解释一下“扫描读取缓冲区中的有效字符并计算其中的换行符”是什么意思吗
//read and print till required number
while (Starting != printStop) {
read( in_fd, buffer, BUFFERSZ );
Starting++; //increment starting
}
//read( in_fd, buffer, BUFFERSZ );
printf("%s \n", buffer);