Reputation: 378
I have a file and i need to print the part between two given characters z1 and z2. I know how to print after the first one but i have no idea how to stop printing when z2 is met.
NOTE: The wtf function is written from the exercise.
I've tried if(niz == z2) {break;}
but it doesn't seem to work
#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;
}
I need the array to stop printing when it hits z2.
Upvotes: 1
Views: 149
Reputation: 84579
The key to locating the characters (if any) between z1
and z2
entered by the user within a buffer read from a file is to validate:
z1
exists in the buffer (saving the location for later use);z2
exists in the remaining section of the buffer (saving the location for later use); and finallyz2
is not the next character after z1
in the buffer - meaning that at least 1 valid character exists between z1
and z2
.While you can use fgets
(and I would suggest it), to simplify the example, let's use POSIX getline
to avoid having to allocate/reallocate manually to insure a complete line is read (regardless of the length). If you know the maximum number of characters you will read from the file in advance, then you can simply use a fixed size buffer and use the input function of your choice.
After reading all characters in a line into your buffer, it is then a simple matter of locating z1
and z2
within the buffer. strchr
will search the buffer for the existence of each character returning a pointer within the buffer if the character is found (or NULL
if the character is not found). You simply save the pointer returned by strchr
in each case which leaves you with a pointer (1-char before) and (1-char after) the characters between z1
and z2
.
(hint: if you increment p1
it will point to the first character you want)
Then it is just a matter of allocating storage to hold the characters between p1
and p2
and using memcpy
to copy the characters to the new storage (remembering to nul-terminate the resulting buffer) before outputting your results. Again, if using a fixed size buffer to hold the line read from the file, then a second buffer of equal size is sufficient to hold the characters between z1
and z2
.
Putting it altogether you could do something similar to:
#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);
}
Example Input/File
$ cat ../dat/qbfox.txt
A quick brown fox jumps over the lazy dog.
Example Use/Output
$ ./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 '
Error in order:
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: s j
error: 'j' not found after 's' in buf.
Either character not in 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.
Nothing between z1
and z2
:
$ ./bin/findcharsbtwn ../dat/qbfox.txt
enter beginning and ending characters: w n
error: 'n' is next char after 'w' in buf.
(don't forget to validate your memory use with a tool such as valgrind
on Linux)
Look things over and let me know if you have further questions.
Upvotes: 1