【问题标题】:when program reads characters from file it also reads some trash当程序从文件中读取字符时,它也会读取一些垃圾
【发布时间】:2016-03-04 17:05:54
【问题描述】:

该程序从文件 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

【问题讨论】:

  • garbage in,garbage in,请正确缩进你的代码!
  • 哇。那些带有所有逗号的行 - 确定它有效,但它与“正常”相距甚远,很多人会打电话给你!
  • 这会给你一个 F:fclose(fp),fputs("memory alloc fails",stderr),exit(1);
  • 是的,我知道,我可以使用另一个数组,但是!它确实更容易看到我想要做什么,而且它也是查看程序如何工作的原型
  • 发布观察到的输出比描述它更有用:“它也读取一些奇怪的字符”。

标签: c file char


【解决方案1】:

问题很简单:

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

因此,将整个tablou_init0 循环到n 可能会产生随机输出,因为'\0' 之外的字节是不确定的,并且可能是有效但意外的指令。

修复很简单,将两个 for 循环更改为:

for (i = 0; i < lSize; i++)

从技术上讲,tablou_init 数组是不需要的,循环 buffer 的内容更简单、更安全。

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

【讨论】:

  • 这是一个愚蠢的问题,但它应该放在哪里?
  • 两个循环都应该改变
  • 谢谢你,为我节省了很多时间,我有点喜欢接受批评,因为我是一个业余爱好者,这肯定有助于我理解我做的一些错误))
  • 我有一个问题,如果我引入第二行文件读取文件失败,我应该添加更多内容吗?
  • 对不起,直言不讳,我明白这种风格不是你的,只是要注意它不优雅,容易出错。请接受答案并享受旅程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-17
相关资源
最近更新 更多