Reputation: 193
After reading documentation, Stack answers and C standard, I still seem not to get something.
I wanted to redirect the output to the certain file and then compare the output with the predicted result; I'm going to indicate the main issue using comments
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SEQ 120
void printer() {
for (int i = 0; i < 5; i++) {
printf("%d0 ", i);
for (int j = 0; j < 6; j++) {
printf("0%d ", j);
}
printf("\n");
}
printf("\n");
}
void check_string() {
FILE* pointer = freopen("./check_str_out", "w", stdout);
char* storage = malloc(MAX_SEQ);
char* test_results[] = {"00 00 01 02 03 04 05 \n", "10 00 01 02 03 04 05 \n",
"20 00 01 02 03 04 05 \n", "30 00 01 02 03 04 05 \n", "40 00 01 02 03 04 05 \n", "\n"};
int counter = 0;
printer();
freopen("/dev/tty", "w", stdout);
FILE* output = fopen("./check_str_out", "r"); //It was added in the new version
printf("sth\n");
while (fgets(storage, MAX_SEQ, output)) { //previous: while (fgets(storage, MAX_SEQ, pointer))
printf("sth2\n");
printf("count: %d, stor: %s, test: %s, comp: %d\n", counter, storage, test_results[counter], strcmp(storage, test_results[counter])); //E) strcmp(storage, test_results[counter++])
counter++;
}
free(storage);
fclose(output);
}
int main(void) {
check_string();
return 0;
}
The question is: why did this code not work when I used pointer
? Why did I have to open the file? Now everything is correct. I've tested also with:
FILE* pointer = freopen("./check_str_out", "w+", stdout);
in order to check, whether it is a matter of mode, but it didn't work.
For clarity: it doesn't print the while loop if there is pointer in fgets() used, it doesn't enter it.
EDIT:
From this description I can't see the fclose()
of the file opened by freopen()
, however it looks like the stream has been closed. What is the cause of that?
Upvotes: 1
Views: 840
Reputation: 117298
You're accessing test_results
out of bounds so your program has undefined behavior.
void printer() {
for (int i = 0; i < 5; i++) {
printf("%d0 ", i);
for (int j = 0; j < 6; j++) {
printf("0%d ", j);
}
printf("\n");
}
printf("\n"); // this line makes it print 6 lines to the file
}
And in your while
loop counter
will reach 5
and test_results[5]
is out of bounds.
Always test the return value from functions that may fail, like freopen
, and also make sure that you're not running out of bounds when depending on external data (like your data file, that may get corrupted for other reasons).
Example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SEQ 120
void printer() {
for (int i = 0; i < 5; i++) {
printf("%d0 ", i);
for (int j = 0; j < 6; j++) {
printf("0%d ", j);
}
printf("\n");
}
printf("\n"); // this extra line doesn't matter if you check bounds later
}
void check_string() {
if (freopen("./check_str_out", "w", stdout)==NULL) {
perror("./check_str_out");
return;
}
char* storage = malloc(MAX_SEQ);
if (storage == NULL) {
perror("malloc");
return;
}
char* test_results[] = {"00 00 01 02 03 04 05 \n",
"10 00 01 02 03 04 05 \n",
"20 00 01 02 03 04 05 \n",
"30 00 01 02 03 04 05 \n",
"40 00 01 02 03 04 05 \n"};
int counter = 0;
printer();
if (freopen("/dev/tty", "w", stdout) == NULL) {
perror("/dev/tty");
return;
}
FILE* output = fopen("./check_str_out", "r");
if(output == NULL) {
perror("./check_str_out");
return;
}
while (counter < sizeof test_results / sizeof *test_results &&
fgets(storage, MAX_SEQ, output))
{
printf("count: %d, stor: %s, test: %s, comp: %d\n", counter,
storage, test_results[counter],
strcmp(storage, test_results[counter]));
counter++;
}
free(storage);
fclose(output);
}
int main(void) {
check_string();
return 0;
}
Regarding pointer
:
pointer == stdout
throughout the whole program after FILE* pointer = freopen("./check_str_out", "w", stdout);
. You can't read from stdout
. It's write-only.
"I can't seen the fclose()
of the file opened by freopen()
, however it looks like the stream has been closed. What is the cause of that?" - stdout
is closed automatically when the program terminates.
Upvotes: 2