【问题标题】:Writing my own Cat function in C用 C 编写我自己的 Cat 函数
【发布时间】:2015-05-05 23:30:30
【问题描述】:

嗨,我不知道如何在 C 中模拟我自己的 Cat 函数,我知道当没有设置参数并且我已经得到它时它是如何工作的,但我的问题是当我试图打开一个文件然后打印自己时...

到目前为止我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{  
    char *a1 = (char*) malloc (sizeof(char));
    int sz, fd,cont=0, cont1=0;
    char *b1 = (char*) malloc (sizeof(char));
    //char *a2 = (char*) malloc (sizeof(char));
    char * a2;
    char *b2 = (char*) malloc (sizeof(char));

    // NO PARAMETERS
    while (argc == 1){      
        sz=read(0, a1, 1);
        b1[cont]=a1[0];

        if(b1[cont]=='\n'){
            write(1,b1,cont);
            write(1,"\n",1);
            b1=NULL;            
        }

        cont=cont+1;
        b1=(char*) realloc(b1, sizeof(char)*cont);
      }

    // 1 PARAMETER (FILE)   /*Here is the problem*/
    if (argc > 1){

        fd=open(argv[1],O_RDONLY);
        a2=fgetc(fd);

        while (a2 != EOF){
            b2[cont1]=a2;
            cont1=cont1+1;
            b2=(char*) realloc (b2, sizeof(char)*cont1+1);
            a2=fgetc(fd);
        }

        write(1,b2,cont);
        b2=NULL;
        close(fd);  
    }

    return 0;
}

我该怎么办?

【问题讨论】:

  • 请更具体地说明您遇到的问题。究竟是什么破坏了?
  • 它给我看这个...o2.c:34:3: warning: passing argument 1 of ‘fgetc’ makes pointer from integer without a cast [enabled by default] a2=fgetc(fd); ^ ejercicio_evaluado2.c:34:5: warning: assignment makes pointer from integer without a cast [enabled by default] a2=fgetc(fd); ^ ejercicio_evaluado2.c:35:13: warning: comparison between pointer and integer [enabled by default] while (a2 != EOF){
  • 检查open 是否成功。 fgetc 返回一个int,而不是char*,并期望FILE* 作为参数,而不是int,使用fopen 或不使用fgetc
  • 没问题 @RetiredNinja 但是,我猜我需要 fgetc 才能使用 EOF
  • 你可以使用任何你喜欢的东西,但是你使用它不正确,因为警告显示你。

标签: c function eof cat fgetc


【解决方案1】:

如果您使用open()close(),则不能使用fgetc()。您需要使用fopen()fclose() 才能使用fgetc()

无论哪种方式,您都需要一个可以使用标准输入(拼写为 0stdin)或打开的文件(fdfp 是“文件”的常规名称)调用的函数描述符”和“文件指针”)。您也可以指定输出流。因此,例如,接口:

int cat_fd(int ifd, int ofd);
int cat_fp(FILE *ifp, FILE *ofp);

然后您的主程序使用标准输入和标准输出或打开的文件和标准输出调用您选择的函数。


此外,您还有:

char *a1 = (char*) malloc (sizeof(char));

忽略演员,这是一种昂贵的写作方式:

char a1[1];

您的循环一次读取一个字符。这对于来自&lt;stdio.h&gt; 的文件流来说是可以的,但如果您使用文件描述符,则对性能不利。您应该一次读取 4096 个字符的块。

int cat_fd(int ifd, int ofd)
{
    char buffer[4096];
    ssize_t nbytes;
    while ((nbytes = read(ifd, buffer, sizeof(buffer))) > 0)
    {
        if (write(ofd, buffer, nbytes) != nbytes)
            return -1;
    }
    return (nbytes < 0) ? -1 : 0;
}

您不需要动态内存分配;它只会让您感到困惑并在程序中浪费时间。 main() 函数中的代码看起来更像:

if (argc == 1)
{
    if (cat_fd(0, 1) != 0)
        fprintf(stderr, "failed to copy standard input\n");
}
else
{
    for (int i = 1; i < argc; i++)
    {
        int fd = open(argv[i], O_RDONLY);
        if (fd < 0)
            fprintf(stderr, "failed to open %s for reading\n", argv[i]);
        else
        {
            if (cat_fd(fd, 1) != 0)
                fprintf(stderr, "failed to copy %d to standard output\n", argv[i]);
            close(fd);
        }
    }
}

重写以使用cat_fp() 是读者的练习。您可能会发现 Tried and true simple file copying code in C 相关。

【讨论】:

  • 根据环境和操作系统,write(ofd, buffer, nbytes) 在各种非错误情况下返回的计数可能少于nbytes。您应该继续尝试write 缓冲区的其余部分,直到所有内容都已写入或返回错误。使用来自&lt;stdio.h&gt; 的标准流更加便携。
  • 如果你愿意,你可以这样做——理论上,这是必要的。我从来没有遇到过它的问题,但这并不是说没有可能发生这种情况的系统。如果标准输出是一个套接字,它可能更有可能,但是将标准输出安排为一个套接字需要一些小心。你的来电。而且我同意标准 I/O 功能至少同样简单且更便携。
  • 将标​​准输出设置为套接字需要注意标准输出将是套接字,例如当程序从 inetd 或类似服务运行时。同样,这同样适用于经常使用的管道——除非你知道内核用一个正好 4K 的缓冲区来缓冲它们。
  • 对于管道,您只需要写入不超过管道缓冲区大小,至少为 4k,IIRC。从inetd 运行需要一些小心。这不会发生在每个程序上,也不是偶然发生的。
  • 管道缓冲区可能容纳 4k 的 write 如果它是空的,但是下一个 write 呢?设备驱动程序呢? POSIX 非常清楚部分写入的可能性。忽略这一点是难以找到错误的根源。 IIRC 在 Windows 上的情况有所不同,因为 libc write 不是系统调用的直接映射:它执行许多隐藏任务,例如可选的行终止转换、信号重启等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-16
相关资源
最近更新 更多