Adding Multiple Lines to a Text File Output? - c

I am using a basic C code to print to a text file:
FILE *file;
file = fopen("zach.txt", "a+"); //add text to file if exists, create file if file does not exist
fprintf(file, "%s", "This is just an example :)\n"); //writes to file
fclose(file); //close file after writing
printf("File has been written. Please review. \n");
My question is regarding the above code: I have multiple lines I have printed that I would like to be saved to the text document. How can I easily include multiple lines of code to be printed in my file using the above code?

Move file writing into a procedure:
void write_lines (FILE *fp) {
fprintf (file, "%s\n", "Line 1");
fprintf (file, "%s %d\n", "Line", 2);
fprintf (file, "Multiple\nlines\n%s", "in one call\n");
}
int main () {
FILE *file = fopen ("zach.txt", "a+");
assert (file != NULL); // Basic error checking
write_lines (file);
fclose (file);
printf ("File has been written. Please review. \n");
return 0;
}

There are lots of ways to do this, here's one:
#include<stdio.h>
#include<string.h>
int appendToFile(char *text, char *fileName) {
FILE *file;
//no need to continue if the file can't be opened.
if( ! (file = fopen(fileName, "a+"))) return 0;
fprintf(file, "%s", text);
fclose(file);
//returning 1 rather than 0 makes the if statement in
//main make more sense.
return 1;
}
int main() {
char someText[256];
//could use snprintf for formatted output, but we don't
//really need that here. Note that strncpy is used first
//and strncat used for the rest of the lines. This part
//could just be one big string constant or it could be
//abstracted to yet another function if you wanted.
strncpy(someText, "Here is some text!\n", 256);
strncat(someText, "It is on multiple lines.\n", 256);
strncat(someText, "Hooray!\n", 256);
if(appendToFile(someText, "zach.txt")) {
printf("Text file ./zach.txt has been written to.");
} else {
printf("Could not write to ./zach.txt.");
}
return 0;
}
notice the strncpy and strncat functions since you aren't really utilizing the formatted input that comes with the xprintf functions.

Related

File Pointer Not Being Assigned a Value When Using fopen()

I am trying to write a simple C program which will read data from a csv file and perform some calculations on this data.
Unfortunately I have a problem where a file pointer of mine, fptr , is not being assigned a value after calling fopen(). I know this is the case after stepping through VS 2017's debugger. Yet I do not know why this is the case. This is a huge problem and means my program will throw some very nasty exceptions any time I try to read data from the file or close the file.
My code is below:
main.c
#include<stdio.h>
#include <stdlib.h> // For exit() function
#include"constants.h" //For access to all project constants
/***************************************************************************************************************
To keep the terminal from automatically closing
Only useful for debugging/testing purposes
***************************************************************************************************************/
void preventTerminalClosure() {
//flushes the standard input
//(clears the input buffer)
while ((getchar()) != '\n');
printf("\n\nPress the ENTER key to close the terminal...\n");
getchar();
}
/***************************************************************************************************************
Read the given input file
***************************************************************************************************************/
void readInputFile(char fileName[]) {
FILE *fptr;
char output[255];
//open the file
if (fptr = fopen(fileName, "r") != NULL) { //read file if file exists
//fscanf(fptr, "%[^\n]", output);
//printf("Data from the file:\n%s", output);
printf("<--Here-->");
}else {
printf("\nERROR 1: File %s not found\n", fileName);
preventTerminalClosure();
exit(1);
}
fclose(fptr); //close the file
}
/***************************************************************************************************************
* * * Main * * *
***************************************************************************************************************/
void main() {
char testName[MAX_NAME_SIZE];
printf("Hello World!\n");
printf("Please enter your name: ");
scanf("%s", testName);
printf("It's nice to meet you %s!", testName);
readInputFile("dummy.txt");
preventTerminalClosure(); //Debug only
}
I have made sure that my fake file does indeed exist and is located in the correct location. Otherwise my code would hit the else block inside of readInputFile(). That is something I have thoroughly tested.
There is clearly something basic that I am missing which explains this pointer behavior; but what that is, I am not sure. Any help would be appreciated! :)
Use parenthesis to enforce order, so that fptr is compared against NULL after it has been assigned value returned by fopen:
FILE *fptr;
char output[255];
//open the file
if ( (fptr = fopen(fileName, "r")) != NULL)

fprint doesn't work in loop

I am trying to repeatedly read a string from the command line and print it to a file. This is my code:
int main ()
{
FILE* fp=fopen("test.txt","w");
char* tofile[10];
while(1){
printf("cat: ");
scanf("%s",tofile);
fprintf(fp,"%s\n",tofile);
}
return 0;
}
It works just fine outside the loop. But inside, it just doesn't print.
The fprintf function returns the correct amount of characters it has to print.
Note: I know there's a similar question out there, but it hasn't been answered yet, and I hope my code can help in this matter since it's simpler.
Well first it doesn't seem that what you want is reading on the command line.
The command line what you write right when you execute your program such as:
./main things that are on the command line
What it seems you want to do is to read on the standard input.
What you should consider is to use the fgets function, as it has a limit of characters to be read, so that you can store them "safely" into a buffer, like your tofile.
As you want to read on the standard input you can use the stdin stream (which is a FILE* that is automatically created for every program)
The line goes
fgets(tofile, 10, stdin);
Your loop becoming :
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
meaning: as long as we can read on the standard input, print "cat :" and store what we just read in the file controlled by the stream pointer fp.
Some important stuff
When you try to open a stream it may fail and you should test it:
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
Right before exiting your main, you should also close the file and check if it has succeeded, like that for example:
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
The whole thing becomes:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
char tofile[10];
printf("cat: ");
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Improvements
I don't know if it is just a little program or it aspires to become a greater program.
In the last case you should consider using defines and not a magical number such as
#define BUFFER_MAX_SIZE 10
char tofile[BUFFER_MAX_SIZE];
while (fgets(tofile, BUFFER_MAX_SIZE, stdin) != NULL) { ... }
This helps for readability and makes the program less apt to debug when modifying such a size. Because with the define all the part of the code needing the size will still be fully functional without modifying them.
Please also keep in mind that your tofile acts as a buffer, and it's really a small buffer that can easily be overflowed.
This will work. fgets() returns the string it reads from the specified file pointer. If this string returns only a newline ("\n"), that means nothing was entered at stdin.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp = fopen("test.txt","w");
// always check if fopen() == null
if (!fp) {
fprintf(stderr, "Could not write to file\n");
return 1;
}
char tofile[30];
printf("cat: ");
while (fgets(tofile, 30, stdin)) {
if (strcmp(tofile, "\n") == 0)
break;
fprintf(fp, "%s", tofile);
printf("cat: ");
}
// always fclose()
fclose(fp);
return 0;
}
Edited code.

C - How to extract specific comment lines from a code file

I want to write a code to extract todo task list from a code file.It's basically scanning a code file and detecting lines that include "TODO" string and then writing those lines into a text file.
So far my my code is like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE* f;
char line[200];
f = fopen("someFile.c", "r");
char c;
char str;
while(!feof(f)){
fgets(line,sizeof(line),f);
if(strstr(line, "TODO") != NULL)//Extracts every line with TODO
{
c=fgetc(f);//c = lines with TODO
}
}
fclose(f);
f= fopen("todoListFile.txt","w");
while(!feof(f))
{
fputs(c,f);//Writing the content of the c in to the text file.
}
fclose(f);
return 0;
}
When I run this code it crashes after 1-2 seconds.
My mistake is probably at the second part which is getting those "TODO" lines and writing down those to the text lines. But I'm pretty stuck at that part and don't know what to do.
Note: Content of someFile.c is basically some comment lines with "// TODO :"
The specification pretty much indicates that you have to open two files, one for reading, one for writing. As you read a line from the input file, if that line contains TODO, you need to write that line to the output file. That leads to the straight-forward code:
#include <stdio.h>
#include <string.h>
int main(void)
{
char file1[] = "someFile.c";
char file2[] = "todoListFile.txt";
FILE *fp1 = fopen(file1, "r");
if (fp1 == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", file1);
return 1;
}
FILE *fp2 = fopen(file2, "w");
if (fp2 == NULL)
{
fprintf(stderr, "Failed to open file %s for writing\n", file2);
return 1;
}
char line[200];
while (fgets(line, sizeof(line), fp1) != 0)
{
if (strstr(line, "TODO") != NULL)
fputs(line, fp2);
}
fclose(fp1);
fclose(fp2);
return 0;
}
Note that it checks that the files were opened successfully, and reports the file name if it failed, and exits with a non-zero status (you could add <stdlib.h> and use EXIT_FAILURE if you prefer).
When run on (a copy of) its own source, it leaves the todoListFile.txt containing one line:
if (strstr(line, "TODO") != NULL)
Simple modifications of the program would:
Write to standard output instead a fixed name file.
Take command line arguments and process all the input files named.
Read standard input if no input files are named.
Increase the line length. 200 is better than 80, but lines can be longer than that. I tend to use 4096 as a line length unless there's a reason to allow longer lines.

Read all Lines of a cpp File with Fgets

in my simple impl. i want to read all lines of a cpp file
FILE * pFile;
fopen_s(&pFile,"test.cpp","r+");
if (pFile!=NULL)
{
fputs ("fopen example", pFile);
char str [200];
while (1) {
if (fgets(str, 200, pFile) == NULL) break;
puts(str);
}
fclose (pFile);
}
my text.cpp contains this:
Testline1
Testline2
Testline3
Testline4
as an output i get unreadable chars:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
what is wrong with my code?
my idea is to search for a special line of code, and edit it later on
When the file is open for updating, and you want to read2 after writing you need to call fflush1. So call it after you write into the file here:
fputs ("fopen example", pFile);
1 (Quoted from ISO/IEC 9899:201x 7.21.5.3 The fopen function 7)
However, output shall not be directly followed by input without an
intervening call to the fflush function or to a file positioning function (fseek,
fsetpos, or rewind)
2 Output is writing into the file, and input is reading the file.
This code should achieve what you are trying to do:
#include <stdio.h>
#define MAX_LINE 1024
int main(int argc, char *argv[])
{
FILE *pFile;
char buf[MAX_LINE];
fopen_s(&pFile, "test.cpp", "r");
if (pFile == NULL)
{
printf("Could not open file for reading.\n");
return 1;
}
while (fgets(buf, MAX_LINE, pFile))
{
printf("%s", buf);
}
fclose(pFile);
}

How can I determine if a file is empty?

How do I determine if a file is empty? The file is opened by a C program running on the Windows platform. I want to open a file in append mode, and, if empty, first print a header to it.
// Open CSV & write header
report_csv = fopen("SNR.csv", "a+");
if (!report_csv) {
fprintf(stderr, "Unable to open CSV output file...");
return -1;
}
if (!ftell(report_csv)) {
fprintf(report_csv, "Column A;Column B;Column C\n");
}
// ... print data to file
fclose(report_csv);
I was expecting ftell to return the current file size if the file was not empty, which happens because the code above is looped.
However, ftell always returns 0 and the header is printed multiple times.
I know I could fopen it with r and use fseek/ftell/fclose and then fopen it again with a+, but I think it's possible to do this without opening and closing the file multiple times.
Actually, when fopening a file in append mode, the file pointer is initially at the begining of the file. It moves to the end of it as soon as you write something or use fseek.
I just needed to add fseek(report_csv, 0, SEEK_END); before my if (!ftell(report_csv)).
Let's check this.
Code:
#include <stdio.h>
int main(int argc, char **argv) {
FILE *test;
size_t size;
char buf[100];
/* Truncate file */
test = fopen("test", "w");
if (!test) {
fprintf(stderr, "Cannot open file `test`!\n");
return 1;
}
/* Write something */
fprintf(test, "Something. ");
fclose(test);
/* Open in append */
test = fopen("test", "a+");
if (!test) {
fprintf(stderr, "Cannot open `test` in append mode!\n");
return 1;
}
/* Try to get the file size */
size = ftell(test);
printf("File pointer is: %d\n", size);
fseek(test, 0, SEEK_END);
size = ftell(test);
printf("After `fseek(test, 0, SEEK_END)`, the file pointer is: %d\n", size);
/* Append */
fprintf(test, "And that. ");
fclose(test);
/* Same without fseek */
test = fopen("test", "a+");
if (!test) {
fprintf(stderr, "Cannot open `test` in append mode!\n");
return 1;
}
fprintf(test, "Hello! ");
size = ftell(test);
printf("File size is now: %d\n", size);
fclose(test);
/* Try to read */
test = fopen("test", "r");
if (!test) {
fprintf(stderr, "Unable to open `test` for reading!\n");
return 1;
}
printf("File contents:\n\t");
while (test && !feof(test)) {
fgets(buf, sizeof(buf), test);
printf("%s", buf);
}
/* Cleanup & exit */
fclose(test);
printf("\n\nExiting.\n");
return 0;
}
Output:
File pointer is: 0
After `fseek(test, 0, SEEK_END)`, the file pointer is: 11
File size is now: 28
File contents:
Something. And that. Hello!
Exiting.
When opening a file with fopen with the a+ mode, all writing operations will be performed at the end of the file. You can reposition the internal pointer to anywhere in the file for reading, but writing operations will move it back to the end of file. The initial pointer position for reading is at the beginning of the file.
So you need to call an fseek(pFile, 0, SEEK_END) on your FILE pointer.
You can call _stat() and get the value st_size into struct _stat (you dont need open the file).Declared in sys/types.h followed by sys/stat.h
I don´t know Windows programming, but it can help you: http://msdn.microsoft.com/en-us/library/14h5k7ff.aspx

Resources