文件处理问题(初级)?

时间:2019-02-09 22:40:22

标签: c file

目标是用连续重复n次或多次(n是从键盘输入的整数)的字符填充文件select json_agg(floor) from ( select distinct floor from rooms where building_id = 23 ) a

json_agg(distinct ...)

2 个答案:

答案 0 :(得分:1)

这是因为您写的是long pos=ftell(ulaz);而不是pos=ftell(ulaz);。在do的块中,您定义了一个新变量long pos= ...,覆盖了外部的pos变量,您稍后将其用于将位置重置为存储的值。

也许还有其他问题,但这是最明显的问题,与您的“ //此行是否有问题”结合在一起。

答案 1 :(得分:0)

除了@StephanLechner指出的可变阴影问题之外,您还在输入文件中使重复字符的识别和输出变得过于复杂。无需在读取循环内进行嵌套循环(除了输出重复的字符),也无需使用ftellfseek

采取状态循环方法

每当您处理诸如重复的字符计数(或除去空格等)之类的问题时,您所要做的全部工作将遍历输入的每个字符,并保持是否正在读取字符的当前“状态”。通过使用循环中的条件(通常称为“状态循环”方法)来重复字符并处理状态的任何变化

在您的情况下,您只需要维护(1)读取的前一个字符来确定当前字符是否为重复,以及(2)重复计数。这样,您只有两种可能的状态需要处理:(1)当前字符是最后一个字符的重复,或者(2)不是。

打开并验证输入和输出文件已准备就绪,可以进行读写操作之后,可以进行重复检测和类似于以下操作:

    int c, last = 0;            /* current and last char read */
    size_t repeated, cnt = 1;   /* min repeated and repeat count */
    FILE *ulaz, *izlaz;         /* file pointers */
    ...
    while ((c = fgetc (ulaz)) != EOF) {     /* read each char */
        if (c == last)                      /* if equals last read */
            cnt++;                          /* increment count */
        else {  /* otherwise */
            if (cnt >= repeated)            /* if count >= min */
                while (cnt--)               /* loop count times */
                    fputc (last, izlaz);    /* writing last to out */
            cnt = 1;                        /* reset count */
        }
        last = c;   /* save c as last */
    }

循环的流程很简单。您从输入中读取了一个字符,检查它是否是重复字符,然后将当前字符另存为last

您如何回应每个州?

如果字符是重复字符,则只需增加重复计数(总是初始化1 -当发现重复时,将是字母的第二次出现)。如果字符不是重复字符,则必须检查累积的重复计数是否等于或超过要测试的最小值,如果是,则将该数量的last字符输出到输出文件中-始终将计数重置为1。而已。状态循环方法可以简化许多类似的类型问题。

其余的只是读取最小限制 [1] 作为用户输入,并在完成后关闭文件。需要注意的是,您应始终验证写入后关闭 ,以防止通过验证写入本身无法捕获的流错误。 fclose返回EOF将识别出此类错误,并且errno被相应地设置。

完全将其放入,您可以这样做:

#include <stdio.h>

int main (int argc, char **argv) {

    int c, last = 0;            /* current and last char read */
    size_t repeated, cnt = 1;   /* min repeated and repeat count */
    FILE *ulaz, *izlaz;         /* file pointers */

    if (argc < 3 ) {    /* validate at least two arguments given */
        fprintf (stderr, "error: insufficient input,\n"
                    "usage: %s infile outfile\n", argv[0]);
        return 1;
    }

    /* validate input and output files are open */
    if (!(ulaz = fopen (argv[1], "r")) || !(izlaz = fopen (argv[2], "w"))) {
        perror ("fopen-file");
        return 1;
    }

    /* prompt, read, validate minimum repeatee input */
    fputs ("enter the minimum repeat: ", stdout);
    if (scanf ("%zu", &repeated) != 1) {
        fputs ("error: invalid input.\n", stderr);
        return 1;
    }

    while ((c = fgetc (ulaz)) != EOF) {     /* read each char */
        if (c == last)                      /* if equals last read */
            cnt++;                          /* increment count */
        else {  /* otherwise */
            if (cnt >= repeated)            /* if count >= min */
                while (cnt--)               /* loop count times */
                    fputc (last, izlaz);    /* writing last to out */
            cnt = 1;                        /* reset count */
        }
        last = c;   /* save c as last */
    }
    fputc ('\n', izlaz);            /* tidy up with POSIX '\n' */

    fclose (ulaz);                  /* close input */
    if (fclose (izlaz) == EOF)      /* validate close after write */
        perror ("fclose-izlaz");

    return 0;
}

注意:,您应始终确保输出兼容POSIX,在输出的最后一行之后包含'\n',无论您编写输出文件还是将其应用于终端-没有人喜欢弄乱他们的提示)

示例输入文件

$ cat dat/repeat.txt
abbc dddde fgggh ijkllllmmmn oopqrs

使用/输出文件示例

最少2个字符:

$ ./bin/repeated_ulaz dat/repeat.txt dat/repeated_out-2.txt
enter the minimum repeat: 2

$ cat dat/repeated_out-2.txt
bbddddgggllllmmmoo

最少3个字符:

$ ./bin/repeated_ulaz dat/repeat.txt dat/repeated_out-3.txt
enter the minimum repeat: 3

$ cat dat/repeated_out-3.txt
ddddgggllllmmm

最少4个字符:

$ ./bin/repeated_ulaz dat/repeat.txt dat/repeated_out-4.txt
enter the minimum repeat: 4

$ cat dat/repeated_out-4.txt
ddddllll

仔细检查一下,如果还有其他问题,请告诉我。

脚注

[1] 如果您使用的旧版VS编译器无法处理size_t "%zu"格式说明符,请更改所有size_tunsigned并将所有"%zu"更改为"%u"