当程序从文件中读取字符时,它也会读取一些垃圾

时间:2015-11-30 22:25:20

标签: c file char

该程序从文件RDLRDLLLL读入缓冲区,然后传输到char数组,最终将每个字符转换为伪代码。问题是:它还读取了一些奇怪的字符,所以我的问题是:问题在哪里?

#define n 100

void main() {
  int i;
  char tablou_init[n];

  FILE *fp;
  long lSize;
  char *buffer;

  fp = fopen("date.in", "r");
  if (!fp) perror("date.in"), exit(1);

  fseek(fp, 0L, SEEK_END);
  lSize = ftell(fp);
  rewind(fp);

  /* allocate memory for entire content */
  buffer = calloc(1, lSize + 1);
  if (!buffer) fclose(fp), fputs("memory alloc fails", stderr), exit(1);

  /* copy the file into the buffer */
  if (1 != fread(buffer, lSize, 1, fp)) fclose(fp), free(buffer), fputs(
      "entire read fails", stderr), exit(1);

  strcpy(tablou_init, buffer);

  for (i = 0; i < n; i++) {
    if (tablou_init[i] == 'R') printf("<program>\n");
    else if (tablou_init[i] == 'D') printf("<secventa de instructiuni>\n");
    else if (tablou_init[i] == 'L') printf("<consecutivitate de  descrieri>\n");
    else if (tablou_init[i] == 'T') printf("<tip>\n");
    else if (tablou_init[i] == 'I') printf("<lista de identificatori>\n");
    else if (tablou_init[i] == 'S') printf("<consecutivitate de instructiuni>\n");
    else if (tablou_init[i] == 'A') printf("<instructiunea de Atribuire>\n");
    else if (tablou_init[i] == 'F') printf("<instructiunea IF>\n");
    else if (tablou_init[i] == 'H') printf("<instructiune>\n");
    else if (tablou_init[i] == 'W') printf("<instructiunea WHILE>\n");
    else if (tablou_init[i] == 'i') printf("<identificator>\n");
    else if (tablou_init[i] == 'e') printf("<expresie>\n");
  }

  fclose(fp);
  free(buffer);
  for (i = 0; i < n; i++) {
    printf("%c", tablou_init[i]);
  }

}

program run

1 个答案:

答案 0 :(得分:2)

问题很简单:

您将文件内容读入buffer,然后将其复制到tablou_init。不检查潜在溢出是危险的,但是让我们假设文件实际上只包含几个字节:这些字节和尾随'\0'strcpy复制,但其余部分{ {1}}未初始化。

因此,将整个tablou_inittablou_init循环到0可能会产生随机输出,因为n之外的字节是不确定的,可能是有效但意外的指令。< / p>

修复很简单,将'\0'循环更改为:

for

从技术上讲,不需要for (i = 0; i < lSize; i++) 数组,循环遍历tablou_init的内容更简单,更安全。

使用buffer从输入文件中读取行将比您当前的方法更可靠:您无法使用fgets()可靠地计算文件大小。 C11 7.21.9.4说:对于文本流,其文件位置指示器包含未指定的信息,fseek函数可以使用该信息将流的文件位置指示器返回到ftell调用时的位置; 。您执行以文本模式打开流。这可能不是您的问题的解释,但这种方法不可移植。