On this page you will find some hints and tricks how to simplify printing the same thing to both the terminal window and a file. By adding to the code samples provided, you can create something that will work for you the best. Some of the ideas described in the following code files:
- In Linux, everything is considered a file (folders, pipes, physical devices – e.g. optical drive etc.). Even writing text to the terminal window is considered writing to a file [ Wikipedia: everything is a file ]. The three standard streams are stdin (input stream from keyboard), stdout (output stream to the terminal) and stderr (error stream, also written to the terminal by default).
Additional reading: file descriptors [ Wikipedia: file descriptor ] - By using the properties of the files / streams, we can investigating printing and scanning:
1 2 3 4 5 6 |
printf("This line will be written to the terminal window\n"); fprintf(stdout, "This line will also be written to the terminal window\n"); // Both of the following lines will read from the keyboard scanf("%d", &num); fscanf(stdin, "%d", &num); |
- In addition to this, if we check for the value of the file pointer (not being NULL), we can make it so that log files are only written when opening of the file succeeded or make it switchable by user depending on their wishes – e.g. we can have a debug mode where it logs everything, but in normal mode it only prints on the screen.
- When going even deeper, we can add timestamps to our logfiles. More information and examples on this can be found from here: http://www.cplusplus.com/reference/ctime/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
/** * Fail: log_sample.c * Author: Risto Heinsar * Created: 12.02.2018 * Modified: 16.02.2018 * * Description: Sample code which demonstrates the use of printing formatted text * into string buffers, so that they can be more easily printed out * to multiple files. Within this code, I also use a fixed width integer * type uint64_t and it's corresponding format for printing. * Second idea that is demonstrated within this code is the possibility to * use file printing commands to print to terminal, using the idea that * stdout is also a file which can be printed to. */ #include <stdio.h> #include <stdlib.h> #include <inttypes.h> #define BUF_LEN 1024 void PrintCombined(FILE *fo, char *text); void PrintWithDestination(FILE *stream, char *text); int main(void) { char buf[BUF_LEN]; FILE *fo; float wage = 9.25; char *position = "Specialist"; // fixed width 64-bit unsigned integer variable. Look up stdint and inttypes libraries. uint64_t identNum = 36804210333l; // The following condition will both try to open a file and check if it was // successful. The contents of this condition will only run if it was. if ((fo = fopen("out.txt", "w")) != NULL) { // printing into a string buffer so we can later use it in multiple places // This uses format types from stdinth and inttypes.h headers. sprintf(buf, "Employee with the eID %"PRIu64" has a job title of \"%s\" and" "makes %.2f euros an hour\n", identNum, wage, position); // print with selective destination (first option) PrintWithDestination(stdout, buf); PrintWithDestination(fo, buf); // use a single function to print precomposed text (second option) PrintCombined(fo, buf); fclose(fo); } return EXIT_SUCCESS; } /** * Description: Prints the precomposed text into the given stream. The stream can * either be just a normal FILE or it can also be stdin or stderr * streams. * Parameters: stream - FILE pointer where the text should be printed to. * text - char pointer, text that should be precomposed and will * be directly put on the stream * Return: none */ void PrintWithDestination(FILE *stream, char *text) { fprintf(stream, text); } /** * Description: Prints the precomposed text into the given stream. Slightly more compact * than the previous function, but the end result will be identical. * Parameters: fo - FILE pointer, the output file to store the text * text - char pointer, text that should be precomposed and will * be directly put on the stream * Return: none */ void PrintCombined(FILE *fo, char *text) { PrintWithDestination(stdout, text); PrintWithDestination(fo, text); // We could also use simpler functions here instead of reusing PrintWithDestination // puts(text); // fputs(text, fo); } |