Struggling to understand file pointers? - c

Main description of the problem below, where it happens. But simply, I cannot figure out why I get error messages after asking
if (outf!=NULL){
printf("Output file already exists, overwrite (y/n):");
scanf("%c",yn);
}
Where outf is a file pointer to an existing file. Please read description halfway through code.
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main() {
/* Declare file pointer */
FILE *inf;
FILE *outf;
int linenumber,linecounter=0,linepresent;
char filename[21];
char detail[21];
char linedetail[21];
char outfilename[21];
char letter,yn='y';
int position;
/*INPUT DETAILS Ask user for file name and line number*/
printf("Please enter an input filename and a linenumber: ");
//scan filename to char string and line number to int variable
scanf("%s %i",&filename,&linenumber);
/*OUTPUT DETAILS Ask user for file name, letter & position, etc*/
printf("Please enter an output filename, a letter and a position:");
scanf("%s %c %i",&outfilename,&letter,&position);
/* Open file for reading */
inf=fopen (filename,"r");
outf=fopen(outfilename,"r");
/*check that file exists*/
if (inf!=NULL) {
Up until here everything works fine!
Then I try to find out if the outf file already exists. If outf points to an existing file, it DOES print "Output file already exists, overwrite (y/n):"
HOWEVER, as soon as it prints this I get error windows opening! This is probably an extremely rookie mistake - I'm still learning C. If there is no such file the program completes normally and bypasses the if statement okay.
if (outf!=NULL){
printf("Output file already exists, overwrite (y/n):");
scanf("%c",yn);
}
if (yn=='y'){
/*keep reading to end of file*/
while (feof(inf)==0) {
linecounter++;
/*read each line and store the line number in detail[WORDS GO HERE]*/
fscanf (inf,"%s", &detail);
/*If we reach the line selected by the user*/
if (linecounter==linenumber){
strcpy(linedetail,detail);
linepresent=1;
}
}
if (linepresent==0) {
printf("File only contains %i lines",linecounter);
}
} else {
exit(1);
}
} else {
printf("Input file not found");
}
printf("%s",linedetail);
/* close the file */
fclose(inf);
fclose(outf);
return (0);
}

First, already mentioned problems: You're opening the output file in reading mode. To open it for writing:
outf=fopen(outfilename,"w"); /* Note the "w". */
Also, scanf() accepts pointers to variables, not their values, so if you write scanf("%c", yn);, you will give scanf the character y as a pointer, which is nonsense. You need to do it like this: scanf("%c", &yn);.
Even if you fix these, however, your program won't do what you expect. If the file you're trying to open for writing doesn't exist, fopen() won't return NULL, it will create a new file. Your code will always overwrite the output file if it exists. NULL is returned only if fopen couldn't open/create the file (e.g. you didn't have the permissions to do it), and you should handle it like this:
outf=fopen(outfilename, "w");
if(outf == NULL) {
perror("Failed to open output file: ");
fclose(inf); /* Don't leave files opened. It's bad form. */
exit(1);
}
/* Open succeeded, do your stuff here. */
Note that no else block is needed after the if, because exit() ends the program immediately.
Also, there is no such thing as a "pointer to a file". FILE is just a structure that represents an open file.

http://www.cplusplus.com/reference/clibrary/cstdio/fopen/
You are open the output file with the read flag. Try changing it to "w".
outf=fopen(outfilename,"w");
Although it is worth noting writing to a file opened with "w" will whack the old file. use "a" to append to the file.

You should pass the address of yn to scanf function.
scanf("%c", &yn);

Related

data written to txt file appears in some bizzare language[C]

So I've written a program that will take in a information about a dvd (specifically it's postion, IDkey(just some random number) Title, Genre and Year of release), and using a struct it will write that info to a .txt file called "person.txt". I'm positive my code works for the most part but when I go to test it the output received in the .txt file is written in some weird symbol language and not English and quite frankly I have no idea as to why this is. Any explanation on why this is happening would be much appreciated, thanks :)
PROGRAM
#include <stdio.h>
#include <stdlib.h>
// a struct to read and write
struct dvd
{
int fposition;
int fIdKey;
char ftitle[50];
char fgenre[50];
int fyear;
};
int main ()
{
FILE *outfile;
struct dvd input;
// open file for writing
outfile = fopen ("person.txt", "w");
if (outfile == NULL)
{
fprintf(stderr, "\nError opend file\n");
exit (1);
}
printf("Postion: ");
scanf("%d", &input.fposition);
printf("ID Key: ");
scanf("%d", &input.fIdKey);
printf("Title: ");
scanf("%s",&input.ftitle);
printf("Genre: ");
scanf("%s", &input.fgenre);
printf("Year: ");
scanf("%d", &input.fyear);
// write struct to file
fwrite (&input, sizeof(struct dvd), 1, outfile);
if(fwrite != 0)
printf("contents to file written successfully !\n");
else
printf("error writing file !\n");
// close file
fclose (outfile);
return 0;
}
TEST RUN
TEST RUN OUTPUT IN THE .TXT FILE
You are writing these values to the file:
int fposition;
int fIdKey;
char ftitle[50];
char fgenre[50];
int fyear;
But you are displaying the whole file as characters. That kind of works for ftitle and fgenre because they really are characters...though since you don't populate all 50 characters there are some ugly uninitialized characters shown as well. That is easy to fix: just fill the unused characters (as well as the null terminator) with some known character (such as space) before writing to the file, or do not write the unused characters at all. You can use strlen() to find the length of each string and memset() to set the unused characters to a well-known character which is printable.
Next, saving an int and reading it as text is problematic. You need to decide on a single format. Either you write as integers like now, and you read as integers (which means you need a special program to read the file), or you commit to writing only text to the file.
Easiest might be to only write text to the file. You can use fprintf() for that, instead of fwrite(). You can use fprintf() for the character arrays as well, it will automatically write only the "used" part of each string up to the null terminator, skipping all the "garbage" characters.

C - Terminal Write and Output to a Text File

I am a student taking an introductory C course and have our first C midterm coming up. Our test environment would store our actions and printf output to a text file. However, our TA suggested we write to a file ourselves using fprintf just in-case.
Is there a very simple way I can copy my terminal/console output and input (what I enter in after scanf) to a text file like output.txt?
I tried
freopen("output.txt","w",stdout);
but that won't write my scanf input to the text file.
Can anyone help?
Don't use scanf();
Use fgets();
An example:
#include <stdio.h>
#include <stdlib.h>
#define Contents_Size 1000
int main()
{
char contents[Contents_Size];
//Opening the file
FILE * fp;
fp = fopen("\myfile.txt", "w"); //"w" = write
//If there is an error
if(fp == NULL)
{
//Exit
printf("Error!\n");
exit(EXIT_FAILURE);
}
//This part require your input
printf("Enter the contents of file: \n");
fgets(contents, Contents_Size, stdin);
//Write your input in file
fputs(contents, fp);
//Close the file
fclose(fp);
return 0;
}
fgest() will copy your input in contents[] and fputs() will paste every char of contents[] in your file.

Parsing file into an array [duplicate]

This question already has an answer here:
what's the preferred library for CSV parsing/writing in C++? [closed]
(1 answer)
Closed 7 years ago.
Good day. Don't know whether this question has been asked before. Any who, I have a text file with contents like below
AP0003;Football;13.50;90
AP0004;Skateboard;49.90;30
It is basically,
Item Code;Item Name;Price per unit;Quantity
I am trying to put the contents of the text file into an array but I've had no luck so far. And, I can't find anything similar on Stack Overflow (or maybe my search parameters is not accurate). Would appreciate any help I can get. Am new to C Programming.
Firstly open the file using fopen:
FILE* fp = fopen("NAME_OF_FILE.txt", "r"); // "r" stands for reading
Now, check if it opened
if(fp == NULL) //If fopen failed
{
printf("fopen failed to open the file\n");
exit(-1); //Exit program
}
Suppose that these are your arrays to store the line and each data are:
char line[2048]; //To store the each line
char itemCode[50];
char item[50];
double price;
int quantity; //Variables to store data
Read the file using fgets. It consumes line by line. Put it in a loop which terminates when fgets returns NULL to scan the whole file line by line. Then extract data from the scanned line using sscanf. It, in this case, will return 4 if successful:
while(fgets(line, sizeof(line), fp) != NULL) //while fgets does not fail to scan a line
{
if(sscanf(line, "%[^;];%[^;];%lf;%d", itemCode, item, price, quantity) != 4) //If sscanf failed to scan everything from the scanned line
//%[^;] scans everything until a ';'
//%lf scans a double
//%d scans an int
//Better to use `"%49[^;];%49[^;];%lf;%d"` to prevent buffer overflows
{
printf("Bad line detected\n");
exit(-1); //Exit the program
}
printf("ItemCode=%s\n", itemCode);
printf("Item=%s\n", item);
printf("price=%f\n", price);
printf("Quantity=%d\n\n", quantity); //Print scanned items
}
Finally, close the file using fclose:
fclose(fp);
You can try this code :
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str1[1000],ch;
int i=0;
FILE *fp;
fp = fopen ("file.txt", "r"); //name of the file is file.txt
while(1)
{
fscanf(fp,"%c",&ch);
if(ch==EOF) break; //end of file
else str[i++]=ch; //put it in an array
}
fclose(fp);
return(0);
}
This will put your entire file into an array str including '\n' and other special characters.If you dont want the special characters put neccessary conditions in the while loop.

Open file, print to stdout, append to file, and print to stdout again

In the following C-code I open a file called test.txt which contains a few lines. I then read in those lines in a while-loop and print them to stdout. Afterwards I make a few changes in the file by e.g. appending the number 42 to it. I then want to print the contents of the changed file to stdout but I seem to missing something there. Here is my code so far (unnecessarily commented):
#include <stdio.h>
#include <stdlib.h> /* for exit() */
main ()
{ /* Declare variables */
FILE *file_read;
char file_save[100];
int number = 42;
/* Open file */
file_read = fopen("/home/chb/files/Cground/test.txt", "a+");
/* Check if file exists. */
if (file_read == NULL) {
fprintf(stderr, "Cannot open file\n");
exit(1);
}
/* Print what is currently in the file */
printf("This is what is currently in the file:\n");
while(fgets(file_save, 100, file_read) != NULL) {
printf("%s", file_save);
}
/* Change the contents of the file */
fprintf(file_read, "%d\n", number);
/* Print what is in the file after the call to fscanf() */
printf("This is what is now in the file:\n");
/* Missing code */
fclose(file_read);
}
It seems that a simple while-loop placed where Missing code is, similar to the one already used before will not suffice. Can someone please explain what is going on. I don't mind technicalities!
In order to read the file from the start again you have to call fseek() first, like so
fseek(file_read, 0, SEEK_SET);
this sets the stream position indicator back to the start of the file.
See http://www.cplusplus.com/reference/cstdio/fseek/ for more info.
You do not set the file pointer back to start. As it's already at the end of the file, there's nothing more to read.
Before reading the file again, do:
rewind(file_read); //before the "missing code" comment
to set it back at the start of the file.

Creating a file and copying its content to other file in c language

I need a C program to copy contents of one file to another file along with the following conditions :
1.) The file from which we read data may or may not exist.
2.) The file to which the data is being copied may or may not exist.
If the file exists, then the data shall be directly copied and if the file doesn't exist, there should be an option to create the file ,enter data into it and the later copying the contents of the file into the other file.
I worked out the following code,
At present my modified code is :
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
void main()
{
FILE *f1,*f2;
char c;
char name1[20],name2[20];
clrscr();
setvbuf(stdout, 0, _IONBF, 0);
printf("\nEnter the source file name :");
scanf("%s",name1);
if((f1=fopen(name1,"r"))==NULL)
{
fclose(f1);
f1=fopen(name1,"w");
printf("\nThe specified file does not exist \nNew file will be created");
printf("\nEnter the data for the new file : ");
while((c=getchar())!=EOF)
{
putc(c,f1);
}
fclose(f1);
}
f1=fopen(name1,"r");
printf("\nEnter the destination file name :");
scanf("%s",name2);
f2=fopen(name2,"w+");
while((c=getc(f1))!=EOF)
{
putc(c,f2);
}
rewind(f1);
rewind(f2);
printf("The data in the source file is :\n");
while((c=getc(f1))!=EOF)
{
printf("%c",c);
}
printf("\nThe data in the destination file is :\n");
while((c=getc(f2))!=EOF)
{
printf("%c",c);
}
fclose(f1);
fclose(f2);
fflush(stdin);
getch();
}
But the program works fine only when the source file already exists . If i create a new file then no input is being taken for the destination file name and the data in the destination file file is blank. So what should i do now?
What should I modify to make it work ?
Suggest me any code of your choice also ... Thank you !
Well, I see several problems in your code but the most important one is that the expression:
(c=getc(f1))!=EOF
Will always evaluated true, so you'll run infinite loops. If you read getc documentation you'll realize that it returns an int not a char:
getc documentation
So basically what you're doing is truncating the EOF, which is an int generally defined as -1, to a char when:
c=getc(f1) // At this point C = 255(0xFF) if getc returned EOF
And then promoting c to an int when is compared to EOF, since an int is big
enough to hold 255 the comparison made is 255 != -1, which is always true.
To fix that just declare c as an int.
Some more tips:
You may also want to make sure that it was an end of file condition by using feof since getc returns EOF on other error conditions as well.
You may want to move the "\n" to the end of your senteces on printf calls to force a flush on stdout. Or alternatively you can add this at the start of your program:
setvbuf(stdout, 0, _IONBF, 0);
It seems you're storing the file names in name1 and name2, so you may want to remove the double quotes from fopen file names so that it actually use them.
When you open name2 you use write access only but at the end you try to read and display its content, you may want to use "w+" as the access mode.
When you're trying to print the resulting data the file handler in f2 has already been closed. And the file cursors are already at the end of the file so you may want to use rewind, e.g.
//fclose(f2);
rewind(f1);
rewind(f2);
printf("The data in the source file is :\n");
while((c=getc(f1))!=EOF)
{
printf("%c",c);
}
printf("The data in the destination file is :\n");
while((c=getc(f2))!=EOF)
{
printf("%c",c);
}
fclose(f1);
fclose(f2);
finally the successful code is :
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
void main()
{
FILE *f1,*f2;
char c;
char name1[20],name2[20];
clrscr();
printf("\nEnter the source file name :");
scanf("%s",name1);
if((f1=fopen(name1,"r"))==NULL)
{
fclose(f1);
f1=fopen(name1,"w");
printf("\nThe specified file does not exist \nNew file will be created");
printf("\nEnter the data for the new file : ");
while((c=getchar())!='^')
{
putc(c,f1);
}
fclose(f1);
}
f1=fopen(name1,"r");
printf("\nEnter the destination file name :");
scanf("%s",name2);
f2=fopen(name2,"w+");
while((c=getc(f1))!=EOF)
{
putc(c,f2);
}
rewind(f1);
rewind(f2);
printf("The data in the source file is :\n");
while((c=getc(f1))!=EOF)
{
printf("%c",c);
}
printf("\nThe data in the destination file is :\n");
while((c=getc(f2))!=EOF)
{
printf("%c",c);
}
fclose(f1);
fclose(f2);
fflush(stdin);
getch();
}

Resources