我有一个文件,我需要在两个给定字符z1和z2之间打印该部分。我知道第一个之后如何打印,但是我不知道在遇到z2时如何停止打印。
注意:wtf函数是从练习中编写的。
我尝试过if(niz == z2) {break;}
,但似乎不起作用
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void wtf() {
FILE *f = fopen("podatoci.txt", "w");
char c;
while((c = getchar()) != '#') {
fputc(c, f);
}
fclose(f);
}
int main() {
wtf();
getchar();
char c, z1, z2;
scanf("%c %c", &z1, &z2);
FILE *fo = fopen("podatoci.txt", "r");
char niz[80];
char *a;
while(fgets(niz, 80, fo) != NULL) {
printf("%s", strchr(niz, z1) + 1);
}
fclose(fo);
return 0;
}
我需要数组在遇到z2时停止打印。
答案 0 :(得分:1)
将用户输入的z1
和z2
之间的字符(如果有)定位在从文件读取的缓冲区中的关键是验证:
z1
(保存位置供以后使用); z2
存在于缓冲区的其余部分中(保存位置供以后使用);最后z2
不是缓冲区中z1
之后的下一个字符-意味着z1
和z2
之间至少存在1个有效字符。虽然您可以使用fgets
(我建议这样做),但是为了简化示例,让我们使用POSIX getline
以避免必须手动分配/重新分配以确保读取完整的行(无论如何)的长度)。如果您知道预先要从文件中读取的最大字符数,则只需使用固定大小的缓冲区并使用您选择的输入功能即可。
将一行中的所有字符读入缓冲区后,只需在缓冲区中找到z1
和z2
即可。 strchr
将在缓冲区中搜索是否存在每个字符,如果找到了该字符,则返回一个指针(如果找不到该字符,则返回NULL
)。在每种情况下,您只需保存strchr
返回的指针,这将为您留下一个指针(前1个字符)和(后1个字符)字符 之间 z1
和z2
。
(提示:如果您增加p1
,它将指向您想要的第一个字符)
然后,只需分配存储空间以容纳p1
和p2
之间的字符,然后使用memcpy
将字符复制到新存储空间(记住为 nul -终止结果缓冲区),然后再输出结果。同样,如果使用固定大小的缓冲区保存从文件读取的行,则第二个大小相等的缓冲区足以保存z1
和z2
之间的字符。
将其完全放在一起,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv) {
char z1, z2, /* user input characters */
*p1, *p2, /* pointers to bracket z1, z2 in buf */
*buf = NULL, /* buffer to hold line read from file */
*btwn = NULL; /* buffer to hold chars between z1, z2 */
size_t n = 0; /* allocation size (0 - getline decides) */
FILE *fp = NULL;
if (argc < 2 ) { /* validate filename provided as argument */
fprintf (stderr, "error: insufficient input, usage: %s <file>\n",
argv[0]);
return 1;
}
fp = fopen (argv[1], "r"); /* open file */
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
/* prompt, read/validate 2 non-whitespace characters entered */
fputs ("enter beginning and ending characters: ", stdout);
if (scanf (" %c %c", &z1, &z2) != 2) {
fputs ("(input canceled before 2 characters read)\n", stderr);
return 1;
}
if (getline (&buf, &n, fp) == -1) { /* read line from file into buf */
fprintf (stderr, "error: reading from '%s'.\n", argv[1]);
return 1;
}
fclose (fp); /* close file */
p1 = strchr (buf, z1); /* locate z1 in buf */
if (p1 == NULL) { /* validate pointer not NULL */
fprintf (stderr, "error: '%c' not found in buf.\n", z1);
return 1;
} /* locate/validate z2 found after z1 in buf */
else if ((p2 = strchr (p1, z2)) == NULL) {
fprintf (stderr, "error: '%c' not found after '%c' in buf.\n",
z2, z1);
return 1;
} /* validate z2 is not next char after z1 */
else if (p2 - p1 == 1) {
fprintf (stderr, "error: '%c' is next char after '%c' in buf.\n",
z2, z1);
return 1;
}
p1++; /* increment p1 to point to 1st char between z1 & z2 */
/* allocate mem for chars between p1 & p2 */
if ((btwn = malloc (p2 - p1 + 1)) == NULL) {
perror ("malloc-btwn");
return 1;
}
memcpy (btwn, p1, p2 - p1); /* copy characters between p1 & p2 */
btwn[p2 - p1] = 0; /* nul-terminate btwn */
printf ("between: '%s'\n", btwn); /* output results */
free (btwn); /* don't forget to free the memory you allocate */
free (buf);
}
示例输入/文件
$ cat ../dat/qbfox.txt
A quick brown fox jumps over the lazy dog.
使用/输出示例
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: j s
between: 'ump'
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: A f
between: ' quick brown '
错误顺序:
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: s j
error: 'j' not found after 's' in buf.
两个字符都不在buf中:
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: B z
error: 'B' not found in buf.
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: A B
error: 'B' not found after 'A' in buf.
z1
和z2
之间什么都没有:
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: w n
error: 'n' is next char after 'w' in buf.
(不要忘记在Linux上使用诸如valgrind
之类的工具来验证您的内存使用情况)
仔细检查一下,如果还有其他问题,请告诉我。