使用printArea()我想将一个数组打印到一个文件中, 使用scanArea()我想准确扫描这个文件并将其粘贴到我的数组中。
如果我做printArea()& scanArea()我应该得到与以前相同的结果?好吧,不。我有一些换行符。我的代码有什么想法吗?
int m = 0;
int n = 0;
int c = 0;
void printArea (int len, char p[][len])
{
FILE *out = fopen ("spielfeld.txt", "w");
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
fputc(p[i][j], out);
fputc(10, out);
}
fclose(out);
}
int scanArea (int len, char p[][len])
{
FILE *in = fopen ("spielfeld.txt", "r");
if (in == 0)
return 1;
else
{
while ((c=fgetc(in)) != EOF)
{
if ((c=fgetc(in)) == 10)
{
c++;
m++;
n = 0;
}
p[m][n] = (c=fgetc(in));
n++;
}
return 0;
}
fclose(in);
}
呼叫:
int len;
len = 12;
char arr[len][len];
showArea (len, arr);
printArea(len, arr);
scanArea (len, arr);
showArea (len, arr);
第一和第二个showArea不同。
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
1111
1111111
1111
1111111
1111
1111111
1111
1111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
答案 0 :(得分:0)
scanArea()
中的主循环存在问题。目前:
while ((c=fgetc(in)) != EOF)
{
if ((c=fgetc(in)) == 10)
{
c++;
m++;
n = 0;
}
p[m][n] = (c=fgetc(in));
n++;
}
循环条件读取一个字符。 if语句立即读取下一个字符,抛弃第一个字符。然后你读了另一个角色来分配给阵列,也放弃了第二个角色。这意味着你跳过三分之二的字符。当它是换行符时,你也会增加c
,这是奇怪的,没有意义。换行符应写为'\n'
而不是10。
你需要一些不那么热衷于阅读角色的东西:
while ((c = fgetc(in)) != EOF)
{
if (c == '\n')
{
m++;
n = 0;
}
else
p[m][n++] = c;
}
这仍然有点危险;它会将除换行符之外的任何数量的任何字符存储到数组中,而不用担心数组上的边界,无论是在一行还是在总行数上。但它不会跳过三分之二的数据。
在进一步审核时,我发现m
,n
和c
显示为全局变量;它们应该是scanArea()
的本地人。你应该尽可能避免使用全局变量。必要时,应在文件中将它们设为static
,除非它们必须在源文件之间共享。然后,您需要遵循How do I use extern
to share variables between source files中的指南,以确保一切都是一致的。
只有一个
scanArea()
和m
,n
和c
仅在那里使用。
然后没有理由让他们不在当地。实际上,如果你两次调用scanArea()
,那么这些变量是全局的这一事实意味着在第二次调用时,索引将从一个超出界限的数组位置开始,并从此开始变得更糟。
我创建函数static
,直到确认需要它们在另一个源文件中可见。并非所有人都像我一样对此持肛门保护。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void printArea(int len, char p[len][len])
{
FILE *out = fopen("spielfeld.txt", "w");
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
putc(p[i][j], out);
putc('\n', out);
}
fclose(out);
}
static int scanArea(int len, char p[len][len])
{
FILE *in = fopen("spielfeld.txt", "r");
if (in == 0)
return 1;
else
{
int m = 0;
int n = 0;
int c;
while ((c = getc(in)) != EOF)
{
if (c == '\n')
{
m++;
n = 0;
}
else if (n >= len || m >= len)
{
fprintf(stderr, "Accessing array out of bounds at p[%d][%d]\n", m, n);
exit(1);
}
else
p[m][n++] = c;
}
}
fclose(in);
return 0;
}
static void showArea(int len, char p[len][len])
{
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
putchar(p[i][j]);
putchar('\n');
}
}
int main(void)
{
int len = 12;
char arr[len][len];
memset(arr, '1', len * len);
puts("Before:");
showArea(len, arr);
printArea(len, arr);
scanArea(len, arr);
puts("After:");
showArea(len, arr);
}
在Mac OS X 10.10.1(使用GCC 4.8.1编译)上运行时,我得到输出:
Before:
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
After:
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
111111111111
所有作品,除了我的第8行都是完全空白的,所以现在我有13行而不是12行。
我不能说明你的第8行。
我注意到文件名重复了;重复文件名之类的东西会导致错误。理想情况下,应该修改代码,以便读取和写入函数传递要使用的文件的名称,并且调用代码应该提供该名称。但是,这有点超出了当前问题的范围。
另请注意,如果showArea()
被修改为采用文件流参数(void showArea(FILE *fp, int len, char p[len][len])
并且I / O调用已被适当修改,那么printArea()
中的代码可以修改为打开该文件,调用showArea()
,然后关闭该文件。