该程序从文件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]);
}
}
答案 0 :(得分:2)
问题很简单:
您将文件内容读入buffer
,然后将其复制到tablou_init
。不检查潜在溢出是危险的,但是让我们假设文件实际上只包含几个字节:这些字节和尾随'\0'
由strcpy
复制,但其余部分{ {1}}未初始化。
因此,将整个tablou_init
从tablou_init
循环到0
可能会产生随机输出,因为n
之外的字节是不确定的,可能是有效但意外的指令。< / p>
修复很简单,将'\0'
循环更改为:
for
从技术上讲,不需要for (i = 0; i < lSize; i++)
数组,循环遍历tablou_init
的内容更简单,更安全。
使用buffer
从输入文件中读取行将比您当前的方法更可靠:您无法使用fgets()
可靠地计算文件大小。 C11 7.21.9.4说:对于文本流,其文件位置指示器包含未指定的信息,fseek函数可以使用该信息将流的文件位置指示器返回到ftell调用时的位置; 。您执行以文本模式打开流。这可能不是您的问题的解释,但这种方法不可移植。