fprintf() on a new line of a file - c

How i can make a new line at the end of a file to fprintf() user inputed text?
My code right now is this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int lines;
int number;
FILE *fp;
printf("Insert random number: ");
scanf("%d", &number);
fp = fopen("textfile.txt", "r");
char ch;
while((ch=fgetc(fp))!=EOF)
{
if (ch=='\n') {
lines++;
}
}
fclose(fp);
fopen("textfile.txt", "ab");
fseek(fp, lines, SEEK_SET);
fprintf(fp,"%d", number);
fclose(fp);
}

You just need to add a '\n' to the fprintf() like this
fprintf(fp,"\n%d", number)
/* ^ */
but you also need a lot of error checking, for instance fopen() returns NULL when it fails to open the file.
Your code is actually very broken, you count the lines in the file opened with "r", i.e. for reading, then you call fopen() with "ab" but discard the return value, you then fseek() the number of lines, and fseek() is for the number of characters not lines, then you write to the closed fp pointer, because
fopen("textfile.txt", "ab"); /* you don't assign the return value anywhere */
fseek(fp, lines, SEEK_SET); /* this is the same pointer you `fclosed()' */
/* ^ this will not seek to the end of the file */
fprintf(fp,"%d", number); /* here `fp' is still invalid */
Test this
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *file;
const char *filename = "textfile.txt";
printf("Insert a number: ");
if (scanf("%d", &number) != 1)
{
fpritnf(stderr, "invalid input, expected a number\n");
return -1;
}
file = fopen(filename, "a");
if (file == NULL)
{
fprintf(stderr, "cannot open %s for appending\n", filename);
return -1;
}
fprintf(file, "\n%d", number);
fclose(file);
return 0;
}
You don't need to fseek() if you open with "a" because new content is appended to the end of the file, you need a '\n' before the user input if there was no '\n' in the file or if you want to force the new value in a new line.
You don't need the "b" in the mode string, because you are writing text to the file, and on some platforms the file will have issues when you open it in a text editor.

Related

Ho to copy text from one file to another in C?

I am writing a basic program to copy text to another text file. But in the console window after entering the filename from where text should be taken, the program ends and does not go further. How can I solve this problem?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1, filename2;
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s", filename1);
infile = fopen("filename1", "r");
printf("Enter a input file name:");
scanf("%s", filename2);
outfile = fopen("filename2", "w");
if (infile == NULL || outfile == NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
char characters;
do {
characters = getc(infile);
fprintf(outfile,"%s", characters);
printf("%s", characters);
} while (!feof(infile));
fclose(infile);
fclose(outfile);
return 0;
}
There are a few problems with your program:
You are using char variables to hold names of files. These variables should be char arrays or pointers to the first char of some allocated memory.
fopen("filename2", "w") seems wrong. Although, the first argument should be a char *, you are not reading / writing the files you just asked the user to enter.
fprintf(outfile,"%s",characters) - You are using %s to print characters. This will invoke UB.
char characters - The last character of a file, the EOF character is guaranteed to fit in an int. The characters variable should be declared as an int so that it can hold the EOF character.
Here is the program that works:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1[10], filename2[10];
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s",filename1);
infile = fopen(filename1, "r");
printf("Enter a input file name:");
scanf("%s",filename2);
outfile = fopen(filename2, "w");
if (infile==NULL || outfile==NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
int characters;
/*do {
characters=getc(infile);
fprintf(outfile,"%s",characters);
printf("%s",characters);
} while(!feof(infile));
*/
while ((characters = getc(infile)) != EOF) {
fprintf(outfile, "%c", characters);
printf("%c", characters);
}
fclose(infile);
fclose(outfile);
return 0;
}
There are a number of issues.
char filename1, filename2;
This only allows filename1 and filename2 to hold a single char - not a C string. You need to reserve memory as a char array. Like:
char filename1[64], filename2[64]; // Allow 63 chars for file name
Then
scanf("%s",filename1);
is really bad as it allows the user to overflow your input buffers. Consider using fgets or at least do:
scanf("%63s",filename1); // Limit user input to 63 chars as the buffer is 64
// The "last" char is for the string termination
Then the loop:
First, characters shall be int so that you can check for EOF. Further, check directly on getc instead of using feof. And don't use %s for printing a single char to the output file - use %c. Like
int characters;
while(1) {
characters=getc(infile);
if (characters == EOF) break; // Break (aka jump out of the loop) on
// end-of-file or errors
fprintf(outfile,"%c",characters); // %c instead of %s
// or use: putc(characters, outfile)
// instead of fprintf
printf("%s",characters);
}

Why are contents of a binary file not being printed in c?

Hello I am writing a program that reads the contents of a binary file and prints them to the screen.
#include <stdio.h>
#include <stdlib.h> // For exit()
int main()
{
FILE *fptr;
char filename[100];
printf("Enter the filename to open \n");
scanf("%s", filename);
// Open file
fptr = fopen(filename, "rb");
if (fptr == NULL)
{
printf("Cannot open file \n");
exit(0);
}
// Read contents from file
fseek(fptr,0L,SEEK_END);
int fsize = ftell(fptr);
fseek(fptr,0L,SEEK_SET);
unsigned char *c = malloc(fsize);
fread(c,fsize,1,fptr);
fclose(fptr);
printf("%s",c);
return 0;
}
but it does not print anything.Can someone explain me why and how should I fix this problem.
What you have attempted is not at all what you wanted to achieve.
Remember printf() formats the data it prints. To be printed properly with the %s formatting, the binary data values must be ASCII values but , of course, they are not.
You should probably attempt to printf() with %d.

How to detect if there exists a data in a file C File Handling

I am very new to File Handling in C. I would like to ask if there is any way that I could detect if there is an existing data on a file. Because if there's none, I will use "wb", but if there is a data already, I will just use append "ab".
I tried using "wb" instead of "ab" when I write data, but the first data I wrote won't read.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct clientInfo{
char Name[30];
};
void inputAccounts();
void viewAllRecords();
int main()
{
showOptions();
}
void inputData()
{
FILE *fp;
fp = fopen("hello", "ab");
struct clientInfo PERSONAL;
if(fp == NULL)
{
printf("Error!!!");
getch();
}
else
{
fflush(stdin);
printf("Enter Name: ");
gets(PERSONAL.Name);
fwrite((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp);
printf("File Created!!!");
getch();
fclose(fp);
}
}
void showOptions()
{
char choice;
system("cls");
printf("\n[1] Add Accounts");
printf("\n[2] View Records");
choice = getch();
if (choice == '1')
{
inputData();
}
else if (choice == '2')
{
viewAllRecords();
}
showOptions();
}
void viewAllRecords()
{
FILE *fp;
fp = fopen("hello", "rb");
struct clientInfo PERSONAL;
fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp);
system("cls");
if(fp == NULL){
printf("Error!!!");
getch();
}
else
{
while((fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp))==1)
{
printf("Name: %s\n", PERSONAL.Name);
}
}
getchar();
}
You can use fseek() to make your purpose done. fseek() is used to move file pointer associated with a given file to a specific position.
FILE *fp;
fp = fopen("test.txt", "r");
// Moving pointer to end
fseek(fp, 0, SEEK_END);
if(ftell(fp)>0){
printf("data exists on the file.\n");
}else{
printf("no data.\n");
}
for more details you can read this article.
Simply use ab both all cases.
If the file exists already, it will open the file and writing starts from the end of the file.
If the doesn't exists, it will be created and writing starts from the end of the file which is the same as the beginning.
From http://man7.org/linux/man-pages/man3/fopen.3.html:
a Open for appending (writing at end of file). The file is
created if it does not exist. The stream is positioned at the
end of the file.
EDIT
Since OP has posted more code it can be seen that the first entry will never be printed:
struct clientInfo PERSONAL;
fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp);
^^^^^^^
Read but there is no print
system("cls");
if(fp == NULL){
printf("Error!!!");
getch();
}
else
{
while((fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp))==1)
{
printf("Name: %s\n", PERSONAL.Name);
}
}
the solution is simple - just remove that fread so that fread is only done in the whileloop.
Other tips:
For gets see Why is the gets function so dangerous that it should not be used?
For fflush(stdin); see Using fflush(stdin)
The standard library also provides the stat and fstat functions that allow you to fill a struct stat to determine the file size directly. stat takes a file-path and a pointer to a stuct stat (declared with automatic storage is fine), while fstat takes an integer file-descriptor as its argument.
Using stat to determine whether the file size is greater than zero, is a simple matter of calling stat and then checking the .st_size struct member.
With appropriate validation, you could do:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define MAXC 1024
int main (void) {
char fn[MAXC]; /* filename */
struct stat sbuf; /* stat buffer */
FILE *fp;
/* prompt, read filename, trim line-end */
fputs ("enter filename: ", stdout);
if (!fgets (fn, MAXC, stdin)) {
fputs ("(user canceled input)\n", stderr);
return 1;
}
fn[strcspn (fn, "\r\n")] = 0;
/* call stat, fill stat buffer, validate success */
if (stat (fn, &sbuf) == -1) {
perror ("error-stat");
return 1;
}
/* test sbuf.st_size to check if file size > 0 */
if (sbuf.st_size > 0) {
puts ("opened ab");
fp = fopen (fn, "ab");
}
else {
puts ("opened wb");
fp = fopen (fn, "wb");
}
/* rest of code... */
}
Either way, using seek or stat, you can determine what you need.

Can't I use fscanf() for infinite time?

#include <stdio.h>
main() {
int n;
FILE *file;
printf("We are here to create a file!\n");
file = fopen("demo.txt", "w+");
if (file != NULL)
printf("Succesfully opened!");
printf("Enter number\n");
while (scanf("%d", &n)) {
fprintf(file, "%d", n);
}
fclose(file);
}
why fscanf() is not working here? Here scanf is working properly but fscanf() is not responding or working here. Can anyone explain what the problem is?
Your code has some problems:
the prototype for main without arguments is int main(void)
you do not exit the program if the file cannot be opened. You will have undefined behavior if fopen returns NULL because you later pass this null pointer to fprintf.
the loop iterates until scanf() returns 0. You should instead iterate while scanf() returns 1. scanf() will return EOF if it fails at end of file, causing an infinite loop.
you should probably output a separator after the number in fprintf() otherwise all numbers are going to be clumped together forming a long sequence of digits.
main() should return 0 or an error status
Here is a corrected version:
#include <stdio.h>
int main(void) {
int n;
FILE *file;
printf("We are here to create a file\n");
file = fopen("demo.txt", "w");
if (file != NULL) {
printf("Successfully opened\n");
} else {
printf("Cannot open demo.txt\n");
return 1;
}
printf("Enter numbers\n");
while (scanf("%d", &n) == 1) {
fprintf(file, "%d\n", n);
}
fclose(file);
return 0;
}
Regarding your question: why can't I use fscanf() instead of scanf()?
you can use fscanf() as long as you give it a stream pointer opened for reading: if you write while (fscanf(stdin, "%d", &n) == 1) the program will behave the same way.
if you want fscanf() to read from file, you need to perform a file positioning command between read and write operations, such as rewind() of fseek(). Yet fscanf() will fail if there is no number to read at the current position in the file and since you open file with "w+" mode, fopen() will be truncated it.
You could cause an infinite loop by writing a number to the file, rewinding it to the beginning and re-reading the same number, etc.
Here is some code for illustration:
#include <stdio.h>
int main(void) {
int n;
FILE *file;
printf("We are here to create a file\n");
file = fopen("demo.txt", "w+");
if (file != NULL) {
printf("Successfully opened\n");
} else {
printf("Cannot open demo.txt\n");
return 1;
}
printf("Enter a number: ");
if (scanf("%d", &n) == 1) {
fprintf(file, "%d\n", n);
rewind(file);
while (fscanf(file, "%d", &n) == 1) {
printf("read %d from the file\n", n);
if (n == 0)
break;
rewind(file);
fprintf(file, "%d\n", n >> 1);
rewind(file);
}
}
fclose(file);
return 0;
}
Interaction:
We are here to create a file
Successfully opened
Enter a number: 10
read 10 from the file
read 5 from the file
read 2 from the file
read 1 from the file
read 0 from the file

I want to copy my in file on to my out file.

In this code I opened my files in my open_file function. Then the process_file function needs to copy the text from my in file and Copy it to an out file. Right now it produces a new file but it is blank. It does not give me any error messages. I do not know what is wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LEN 100
FILE* open_file(char prompt[], char mode[]);
FILE* process_file(FILE* in, FILE* out);
int main(int argc, const char * argv[]) {
FILE* in = NULL;
FILE* out = NULL;
printf("MAD-LIBS Text Processor\n");
printf("The Program will open a mad-libs file, ask you to fill various words, and produce a funny story.\n");
open_file("Enter mad-lib file name:\n", "r");
open_file("Enter file name for resulting story:\n", "w");
process_file(in, out);
fclose(in);
fclose(out);
return 0;
}
/* open_file = prompts user for file name & and attempts to open it, if it fails it prompts the user again. */
FILE* open_file(char prompt [], char mode[]) {
char filename[255];
FILE* in;
do {
printf("%s", prompt);
scanf("%s", filename);
in = fopen(filename, mode);
if (in == NULL) {
printf("Unable to open file: %s. Try Again!\n", filename);
}
} while(in == NULL);
return in;
}
/* process_file = processes entire input file and writes it to output file */
FILE* process_file(FILE* in, FILE* out) {
char content[MAX_LEN];
char NewContent[MAX_LEN];
//gets whats in file in
while(fgets(content, content[MAX_LEN], in) != NULL) {
fputs (content, stdout);
strcat(NewContent, content);
}
// copies it
while (fgets(content, content[MAX_LEN], in) != NULL) {
fprintf(out, "%s", content);
}
printf("Successfully copied file\n");
return in;
}
You never assign the FILE* from open_file function to your variable, so it never gets processed.
in = open_file("Enter mad-lib file name:\n", "r");
out = open_file("Enter file name for resulting story:\n", "w");
You are not storing the FILE pointers that open_file is returning, so in
and out remain uninitialized.
You have to do:
in = open_file("Enter mad-lib file name:\n", "r");
out = open_file("Enter file name for resulting story:\n", "w");
process_file(in, out);
Also your process_file is wrong. NewContent is not initialized, when you do
strcat(NewContent, content);
this yields undefined behaviour. Declare NewContent like this:
char NewContent[MAX_LEN] = { 0 };
so that it is properly \0-terminated.
Also depending on the size of the file you are copying, MAX_LEN might not be
long enough to hold the whole file. In that case you would overflow the buffer.
It would be better not to use NewContent in the first place and write to out
in the same reading loop:
FILE* process_file(FILE* in, FILE* out) {
char content[MAX_LEN];
//gets whats in file in
while(fgets(content, MAX_LEN, in) != NULL) { //<- your fgets was wrong
fputs (content, stdout);
fprintf(out, "%s", content); // or fputs(content, out);
}
printf("Successfully copied file\n");
return in;
}
And you were calling fgets incorrectly (look at my corrected code)
Also bear in mind, that you did have 2 loop doing while(fgets(...) != NULL.
Well, the first loop ends, that's because fgets returns NULL, most likely
because the whole file was read or there was an I/O error. In either case
subsequent calls of fgets will return NULL as well, so your second loop
would not even be executed at all.

Resources