目标是用连续重复n次或多次(n是从键盘输入的整数)的字符填充文件select json_agg(floor)
from (
select distinct floor
from rooms
where building_id = 23
) a
。
json_agg(distinct ...)
答案 0 :(得分:1)
这是因为您写的是long pos=ftell(ulaz);
而不是pos=ftell(ulaz);
。在do
的块中,您定义了一个新变量long pos= ...
,覆盖了外部的pos
变量,您稍后将其用于将位置重置为存储的值。
也许还有其他问题,但这是最明显的问题,与您的“ //此行是否有问题”结合在一起。
答案 1 :(得分:0)
除了@StephanLechner指出的可变阴影问题之外,您还在输入文件中使重复字符的识别和输出变得过于复杂。无需在读取循环内进行嵌套循环(除了输出重复的字符),也无需使用ftell
或fseek
。
采取状态循环方法
每当您处理诸如重复的字符计数(或除去空格等)之类的问题时,您所要做的全部工作将遍历输入的每个字符,并保持是否正在读取字符的当前“状态”。通过使用循环中的条件(通常称为“状态循环”方法)来重复字符并处理状态的任何变化
在您的情况下,您只需要维护(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_t
到unsigned
并将所有"%zu"
更改为"%u"
。