为什么这次打印是以前的输出?

问题描述 投票:0回答:2

我正在研究我的cat linux命令的实现。目前,它可以在命令之后没有参数传递时从标准输入中读取并从顺序读取多个文件但是当参数传递' - '时,在某些情况下从标准输入读取之前打印先前的输出。

例如,如果你传递 - file1.txt - file2.txt - 作为参数,一切都按预期工作。它从标准输入读取,输出file1.txt的内容,再次从stdin读取,依此类推。但是,如果我删除第一个' - ',换句话说,如果第一个参数是一个文件,它输出file1.txt的内容然后,从标准输入读取,然后打印第二个文件的内容然后,而不是阅读从之前的stdin开始,第一次从stdin读取它再次输出第二个文件的内容然后输入,之后它才开始正常运行。

这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 1024

void readStdin(){
  char buffer[BUF_SIZE];
  while(fgets(buffer, BUF_SIZE, stdin)){ //reads from the standard input and prints the input
    char *content = malloc(sizeof(char*)*BUF_SIZE);
    if(content == NULL){ //failed to allocate memory
      exit(1);
    }
    strcat(content, buffer);
    //printf("buffer: %s", buffer);
    //printf("content: %s", content);
    printf(content);

    memset(&content[0], 0, sizeof(*content));
    free(content);

    //printf("bufferEND: %s", buffer);
    //printf("contentEND: %s", content);
  }
}

void readArgs(int argc, char* argv[]){
  FILE* fp;
  char ch;
  for (int i=1; i<argc; i++){
    if (*argv[i] == '-'){
      readStdin();
      clearerr(stdin);
    }

    //else if ()
    else {
      fp = fopen(argv[i], "r");
      if (fp==NULL){ //in case the file doesn't exist
        printf("%s: No such file or directory\n", argv[i]);
        exit(1);
      }
      while ((ch=fgetc(fp)) != EOF){
        putchar(ch);
      }
  //    fflush(stdin);

      fclose(fp);
    }
  }
}

int main(int argc, char* argv[]){
  if (argc<2){
    readStdin();
    return 0;
  }
  readArgs(argc, argv);
  return 0;
}

任何提示?

编辑:如果我传递另一个文件后跟另一个' - ',在以上述错误的方式从stdin读取后,不仅它与behvaves相同,但它不会打印前一个输出的第一个字符

c file-io stdin
2个回答
0
投票

这里的代码期望' - '作为参数

if (*argv[i] == '-'){
  readStdin();
  clearerr(stdin);
}

你的程序只在接收' - '作为参数时调用readStdin(),否则输出参数文件。

当您传递- file1.txt - file2.txt -时,这些是5个参数(包括程序名称的6个)告诉您的程序“read,output file1.txt,read,output file2.txt,read” 因此,当您删除第一个-时,您也删除了第一个“读取”,而您告诉您的程序“输出file1.txt,读取,输出file2.txt,读取”


0
投票

在这个网站名称的优良传统中,我怀疑你正在覆盖堆栈。当您使用malloc()分配内存时,它是未初始化的,这意味着它可以包含任何内容。因此,当你执行strcat(内容,缓冲区)时,它将在content []中的最后一个非空字符之后附加buffer []的内容,但是无法知道最后一个非空字符将在何处是。它可能很容易超出内容[]的最后一个字节。欢迎来到C世界

在反射时,content []在堆上,所以你不会覆盖堆栈,但是我将文本留在这里,因为你真的应该修复它们使用内容[]的方式。

此代码还存在其他一些问题,可能是因为您习惯使用其他语言。例如,printf(content)不是一个好主意,因为printf()的第一个参数被解释为格式字符串。如果文件中的数据包含类似“%X”的内容,其中X是printf格式说明符,则printf()会将其解释为其格式化语言的一部分。这可能会导致崩溃并且也是安全漏洞的常见来源,因为制作输入的人可以使用格式说明符来读取/写入内存中的任意位置。

通常在C中,奇怪或非确定性行为是由于内存处理错误造成的。您可能想要安装'valgrind'工具,它可以帮助您找到这样的东西。

另外我不明白你为什么要通过内容[]浏览整个malloc / strcat / memset / free的东西。只是直接打印缓冲区[]会更简单,但是你可能对未来的数据有什么计划吗?

© www.soinside.com 2019 - 2024. All rights reserved.