Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
精确打印&;从文件扫描(C)_C_Arrays_Function_Char_Return - Fatal编程技术网

精确打印&;从文件扫描(C)

精确打印&;从文件扫描(C),c,arrays,function,char,return,C,Arrays,Function,Char,Return,使用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");

使用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);
}
第一个和第二个展示区不同

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

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()
的本地。尽可能避免使用全局变量。必要时,应将它们设置为文件中的
静态
,除非它们确实必须在源文件之间共享。然后,您需要遵循中的指导原则,以确保所有内容都是一致的

只有一个
scanArea()
m
n
c
仅在其中使用

那么,他们就没有理由不是本地人。事实上,如果您两次调用
scanArea()
,这些变量是全局变量这一事实将意味着在第二次调用时,索引将从一个超出边界的数组位置开始,并从那里开始变得更糟


工作代码 我将函数设置为静态的,直到证明它们需要在另一个源文件中可见为止。不是每个人都像我一样对这件事耿耿于怀

#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);
}
所有作品,除了我的第8行是完全空白的,所以现在我得到了13行,而不是12行

我无法解释你的空白第八行

我注意到文件名是重复的;文件名之类的重复会导致bug。理想情况下,应该修改代码,以便将要使用的文件名传递给读写函数,并且调用代码应该提供该名称。然而,这有点超出了当前问题的范围


还请注意,如果修改了
showArea()
以采用文件流参数(
void showArea(file*fp,int len,char p[len][len])
并且适当修改了I/O调用,则可以修改
printArea()
中的代码以打开文件,调用
showArea()
,然后关闭文件。

不要硬编码字符代码,使用
'\n'
而不是
10
printArea
假设每一行的长度都相同。
scanArea
只要看到新行,就会在数组中启动一个新行。您能在调用这两行的函数中显示数组的声明吗Actions?原始数组和结果数组中有什么?fprintf(out,“\n”)给出了相同的结果result@Jongware:请注意,文件是以文本文件的形式打开的(模式中无
b
),因此,I/O系统应该在输入时将CRLF行结尾映射到NL,在输出时将NL映射到CRLF。如果文件是以二进制模式打开的,则不会发生这种映射。所有工作都正常,但我的第8行完全为空,因此现在我得到了13行,而不是12行。只有一个扫描区域()和
m
n
c
仅在其中使用,因为您在Windows上工作,这可能是由于换行符之前的回车。但是,如果文件是以文本模式打开的,这不应该是问题所在。我无法重现将代码用于
扫描区域()的问题
使用您的
printArea()
代码,并组装一个简单的
main()
showArea()
@chux:fair comment;我认为是
返回0;
放错了位置,但是放错了位置会让您的观察结果保持正确。它还会泄漏文件流。
#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);
}
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