未初始化的char数组的行为

时间:2016-09-02 16:55:36

标签: c arrays

我编写了一个使用fread练习的程序。我正在将命令传递给popen并使用fread读取输出并存储到未初始化的char数组中。最后,我打印数组的内容以及将其写入另一个文件。打印(stdout中的输出)工作正常但是当我检查文件的内容时,它在实际输出后有很多垃圾。有什么理由在stdout中运行良好吗? 这是我的代码:

#include <stdio.h>

void fread_s(char *res, int res_size,char *cmd)
{
    char *r;
    int size;
    FILE *fp=popen(cmd,"r");
    if(fp==NULL)
            return;
    size=fread(res,res_size,1,fp);
    pclose(fp);
}

int main()
{
    char cmd[500];
    fread_s(cmd,sizeof(cmd),"ls -lh i*");
    puts(cmd);
    FILE *fp=fopen("opfile","a+");
    if(fp==NULL)
            return;
    fwrite(cmd,sizeof(cmd),1,fp);
}

3 个答案:

答案 0 :(得分:4)

您看到的char数组不会因空终止而产生不必要的副作用。变化:

size=fread(res,res_size,1,fp);

size=fread(res,res_size,1,fp);
res[size] = '\0';

另外,请确保res_size小于sizeof(cmd)。否则,您可能会size sizeof(cmd),因此

res[size] = '\0';

将使用越界索引修改数组。

更改

fread_s(cmd,sizeof(cmd),"ls -lh i*");

fread_s(cmd,sizeof(cmd)-1,"ls -lh i*");

或更改

size=fread(res,res_size,1,fp);

size=fread(res,res_size-1,1,fp);

答案 1 :(得分:2)

代码有size=fread(res,res_size,1,fp),但不使用size,表示读取的元素数。

即使读取的数据包含嵌入的空字符,以下内容仍然有效。

// Return the number of elements read
size_t fread_s(char *res, int res_size,char *cmd) {
  char *r;
  size_t size;
  FILE *fp = popen(cmd,"r");
  if (fp == NULL) {
    return 0;
  }
  size = fread(res,res_size,1,fp);
  pclose(fp);
  return size;
}

只写有效数量的元素。

int main(void) {
    char cmd[500];
    size_t size = fread_s(cmd,sizeof(cmd),"ls -lh i*");

    // puts(cmd);
    fwrite(cmd, size, 1, stdout);

    FILE *fp=fopen("opfile","a+");
    if(fp==NULL) {
            return -1; // Add value to return
    }
    fwrite(cmd, size, 1, fp);
    fclose(fp); // add fclose
}

答案 2 :(得分:1)

在标准输出中写入时,使用puts编写字符串。该字符串不会以空值终止,但puts很有可能在垃圾字符中包含空字符。可能会打印一些垃圾,但不是全部,因为可以吸引零。

(这个问题非常像那个问题,只是看到了:C Language: popen() with fread()?

当您写入文件时,您将获得整个500个字符,包括垃圾字符(500个字符)

要获得相同的行为(但仍有一些可能的垃圾):

fwrite(cmd,strlen(cmd),1,fp);

fputs(cmd,fp);

但是在读取popen的输出后,您必须为null终止字符串。