I made a following program.The program shows no compiler error. There exist a file alive.txt in the directory. I want to use gets to write string to the file alive.txt but its not working properly.
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
int main()
{
FILE *myfile;
char c,d;
char e[100];
myfile=fopen("alive.txt","r");
if(!myfile)
{
puts("Disk Error");
return(1);
}
while((c=fgetc(myfile))!=EOF)
{
putchar(c);
}
puts("\n");
puts("Do ya want to overwrite this file:{Y/N}");//
d=toupper(getchar());
if(d!='Y')
{
puts("Ok.. See ya Later");
return(1);
}
myfile=fopen("alive.txt","w");
puts("Type The Character to overwrite");
gets(e); // scanf works
fprintf(myfile,"%s",e);
fclose(myfile);
getch();
return(0);
}
The file is already open for reading from when you open it for writing to. Add
fclose(myfile);
before the second fopen.
The problem is that gets() reads the newline after the Y and realizes 'end of line', and returns an empty string (because it removes the newline), so there's nothing written to the file. If you use scanf("%s", e); instead of gets(), the %s format skips leading white space (such as the newline after the Y) and reads the next word.
Other problems include:
You're also leaking file descriptors (file streams) because you don't fclose() the myFile from the first fopen().
You're using gets() which is, as stated in a comment, a very bad idea. (Teachers who suggest using gets() should be forcibly restrained from teaching; students who use gets() should be given 0 marks automatically.) Don't use gets(); use fgets() or
getline() instead. Note that fgets() includes the newline in the data if there's space for it.
You're using char c; and then trying to detect EOF with it — which is unreliable.
You don't check that your fopen() calls succeed; you use the file pointer anyway, which will cause your program to crash if the file isn't there for any reason.
#include<stdio.h>
//#include<conio.h> Non-portable
#include<ctype.h>
int main()
{
FILE *myfile;
char c,d;
char e[100];
myfile=fopen("alive.txt","r");
if(!myfile)
{
puts("Disk Error");
return(1);
}
/* Show the current file content. */
while((c=fgetc(myfile))!=EOF)
{
putchar(c);
}
fclose(myFile); // Close the read-only file mode.
puts("\n");
puts("Do ya want to overwrite this file:{Y/N}");
d=toupper(getchar());
if(d!='Y')
{
puts("Ok.. See ya Later");
return(1);
}
/*Flush '\n' character from stdin */
getchar();
puts("Type The Characters used to overwrite");
gets(e); // scanf works
myfile=fopen("alive.txt","w"); Re-open in write mode, deleting old file content.
fprintf(myfile,"%s",e);
fclose(myfile);
// getch(); Non-portable
/* Be nice and close the file when finished with it. */
fclose(myfile);
return(0);
}
Related
I am trying to write user input to a txt file using a while loop.
But for some reason that I don't know, the while loop doesn't stop by clicking 'enter'.
when I click 'enter', I see "while loop executed" so I know the while loop iterated again even though I wanted to stop the while loop.
How to do it in a right way?
P.S: I use Microsoft Visual Studio recommended by my professor.
#include <stdio.h>
#include <string.h>
void main()
{
//writing to file
char write[100];
char fileName[100];
printf("give a name for file: ");
gets_s(fileName,99);
strcat(fileName,".txt");
FILE* pF = fopen(fileName, "w");
printf("what needs to be written?\n: ");
while(gets_s(write,99) != NULL)
{
printf("whileloop executed\n");
fprintf(pF,"%s\n", write);
}
fclose(pF);
}
Per Microsoft's gets_s() documentation, gets_s() returns NULL on end-of-file and error conditions:
Return Value
Returns buffer if successful. A NULL pointer indicates an error or
end-of-file condition. Use ferror or feof to determine which one
has occurred.
Hitting the enter key does not close the input stream and cause an end-of-file condition. It just places a zero-length line terminated with a newline in the input stream.
To do that on Windows from a terminal, one usually has to enter the CTRL-Z key combination.
You need to do some handling there as gets_s() will return and empty string when enter is hit. You can write an extra function to handle that:
size_t my_gets(char *buf,size_t len)
{
size_t ret=0;
if(gets_s(buf,len))
ret = strlen(buf);
return ret;
}
Then change your loop to:
while(my_gets(write,99))
{
...
P.S.- You should avoid calling variables with the same name of system functions (i.e. write).
When I executed below code, m2.txt created correctly as expected with the specified data.
#include <stdio.h>
int main()
{
FILE *fp1;
char ch;
fp1=fopen("m2.txt", "a+");
fputs("Hello, data is appended\0", fp1);
fseek(fp1,0,SEEK_SET);
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
fclose(fp1);
return 0;
}
Now I commented fseek and executed the below code. (I deleted this m2.txt file before executing)
#include <stdio.h>
int main()
{
FILE *fp1;
char ch;
fp1=fopen("m2.txt", "a+");
fputs("Hello, data is appended\0", fp1);
//fseek(fp1,0,SEEK_SET);
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
fclose(fp1);
return 0;
}
To my surprise, displayed data on the screen had just whitespaces. Even "Hello, data is appended"was missing. Also the m2.txt file had many white spaces.
Why this problem? If fseek is not done before read, it should affect only read operation I thought. Why extra spaces are getting written to the file?
In a+ mode, read pointer is pointing to the beginning if no write operation is done. But in case write operation is done, pointer will be at the end I suppose. In such case, read should not be displaying anything without fseek right? In anycase, issues could be there with read. But why write is having issues even though write is done before read.
I am using Codeblock 15.12 and default mingw came with codeblock.
Edited:
I further thought if it could be some compiler related issue. Grabbed old Visual Studio 6 and compiled. Several lines of unreadable characters are printed at the end. So it is not compiler issue. Somewhere some silly issue is there it looks.
After some search, I found that fflush() or fclose() or fseek() is needed before reading the file. Otherwise the entire write buffer may be filled/affected. Tried with fflush() and write operation did not write any junk at the end even if fseek() is not called. Here is the code (Of course fseek() will be there inplace of fflush() in actual code. I just commented fseek and added fflush() for testing purpose).
int main()
{
FILE *fp1;
char ch;
fp1=fopen("m2.txt", "a+");
fputs("Hello, data is appended", fp1);
fflush(fp1);
// fseek(fp1,0,SEEK_SET);
while((ch=getc(fp1))!=EOF)
{
putchar(ch);
}
fclose(fp1);
return (0);
}
This question already has answers here:
Removing trailing newline character from fgets() input
(14 answers)
Closed 8 years ago.
I'm prompting the user for the file name, but once the user presses enter, it takes that into the file name as well. so the file is never found.
int main (){
char file[100];
FILE *fp;
printf("Please enter a valid filename:\n");
fgets(file,100,stdin);
fp=fopen(file, "r");
if(!fp){
printf("File not found.\n"); \\This will always happen because a new line is added to the user's input.
return 1;}
If I use
scanf("%s", file);
The issue doesn't happen, but I heard scanf is not a good function to use and would introduce new issues. How can I solve the new line problem with fgets?
After fgets(file,100,stdin);, do this file[strlen(file)-1]='\0';, it will remove \n from the code. To use strlen() function you need to include string.h in your code.
Try this modified code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (){
char file[100];
FILE *fp;
printf("Please enter a valid filename:\n");
fgets(file,100,stdin);
file[strlen(file)-1]='\0'; //Removing \n from input
fp=fopen(file, "r");
if(fp==NULL)
{
printf("File not found.\n");
return 1;
}
else
{
printf("File found!\n");
fclose(fp);
return 0;
}
}
fgets() returns the \n new line code.... that's what it does. You must wipe out that character.
Given that overflowing, or at least totally filling, incoming buffers is a popular attack vector I prefer code that defends against such.
char *cp;
file[(sizeof file)-1)] = '\0'; /* assure \0 termination on buffer fill attack */
cp = strchr( file, '\n' ); /* find expected \n, but allow for none */
if ( cp ) *cp = '\0'; /* safely clear closing \n */
After succesfully reading a re-directed file to my program from the console, I ask a user to enter a word, then use scanf() to read in the word.
The problem i'm having is that scanf() is immediately reading in junk characters and then the program continues. It doesn't even pause to let the user enter anything in the console. It doesn't happen when I don't open a file. EVERYTHING else works perfectly. What could be the issue:
**I tried everything suggested, still can't get it to work. I've made a new project that is just for getting this part to work, here it is. Ignore that scanf is only looking for a single character, even though I ask for a word. I did this just to see if the program would actually pause and allow me to enter something, but it doesn't. Just enters some garbage and program ends.
main(){
int n,i;
char ch;
char line[80];
while(fgets(line, 80, stdin) != NULL){
for(i=0;i<80;i++){
ch=line[i];
if(ch=='\n'){
printf("%c",ch);
break;
}
else{
printf("%c",ch);
}
}
}
printf("Please enter a word: ");
scanf("%c",&ch);
}
You can't re-direct stdin from a file and then also use the keyboard for input (that I know of). If you want to do that, it's simpler to have the program take the input file as a command-line argument and then run it like so: prog myfile.txt. Also, leave yourself a pad with fgets() -- use one less than the allocated array for maxlen. It's always safest with C char arrays to use one less than the allocated length for anything requiring a maximum length in case the maximum length is not including the '\0' terminating character.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char *argv[])
{
FILE *f;
int i;
char line[80];
if (argc<2)
{
printf("Usage: %s <inputfile>\n",argv[0]);
exit(10);
}
/* Open file and echo to stdout */
f=fopen(argv[1],"r");
if (f==NULL)
{
printf("Cannot open file %s for input.\n",argv[1]);
exit(20);
}
while (fgets(line, 79, f) != NULL)
printf("%s",line);
fclose(f);
/* Get user input from stdin */
printf("Please enter a word: ");
if (fgets(line,79,stdin)==NULL)
{
printf("Nothing entered. Program aborted.\n");
exit(30);
}
/* Remove CR/LF from end of line */
for (i=strlen(line)-1;i>=0 && (line[i]=='\n' || line[i]=='\r');i--)
;
line[i+1]='\0';
printf("The word entered is: '%s'\n",line);
return(0);
}
sscanf is used to input from a stream or a buffer, and in unix stdin is considered as file so u are supposed to use fscanf which inputs from a file so use fscanf(stdin,"%s",testword);
While doing filing im stuck here.The condition of the while loop is not working.The compiler says cannot convert int to FILE*.
while(pFile!=EOF);
Should i typecase the pFile to int?I tried that but it did not worked.Thanks in advance.
The complete code is:
int main()
{
char ch;
char name[20];
FILE *pFile;
int score;
pFile=fopen("database.txt","r");
if(pFile!=NULL)
{
while(pFile!=EOF);
{
fscanf(pFile,"%c",ch);
}
}
else
printf("Cant open the file.......");
fclose(pFile);
return 0;
}
First, you do not want to use while (!feof(pFile)) -- ever! Doing so will almost inevitably lead to an error where the last data you read from the file appears to be read twice. It's possible to make it work correctly, but only by adding another check in the middle of the loop to exit when EOF is reached -- in which case, the loop condition itself will never be used (i.e., the other check is the one that will actually do the job of exiting the loop).
What you normally do want to do is check for EOF as you read the data. Different functions indicate EOF in different ways. fgets signals failure (including EOF) by returning NULL. Most others (getc, fgetc, etc.) do return EOF, so you typically end up with something like this:
int ch; // Note, this should be int, NOT char
while (EOF != (ch=getc(pFile)))
process(ch);
or:
char buffer[MAX_LINE_SIZE];
while (fgets(buffer, sizeof(buffer), pFile))
process(buffer);
With scanf, checking for success is a little more complex -- it returns the number of successful conversions, so you want to make sure that matches what you expected. For example:
while (1 == fscanf(fPfile, "%d", &input_number))
process(input_number);
In this case I've used 1 because I specified 1 conversion in the format string. It's also possible, however, for conversion to fail for reasons other than EOF, so if this failes, you'll frequently want to check feof(pFile). If it returns false, do something like reading the remainder of the line, showing it to the user in a warning message, and then continuing to read the rest of the file.
It depends what pFile and EOF are defined as, but I will asssume that pFile is a *FILE, and EOF is from stdio.h. Then I guess you should do something like:
#include <stdlib.h>
#include <stdio.h>
#define FILENAME "file.txt"
int main(void) {
FILE *pFile;
int ch;
pFile = fopen(FILENAME,"r");
if (pFile) {
while ((ch = getc(pFile)) != EOF) {
printf("Read one character: %c\n", ch);
}
close(pFile);
return EXIT_SUCCESS;
} else {
printf("Unable to open file: '%s'\n", FILENAME);
return EXIT_FAILURE;
}
}
which yields
$ echo "abc" > file.txt
$ /tmp/fileread
Read one character: a
Read one character: b
Read one character: c
Read one character:
# last character being a linefeed
Assuming pFile is your file handle, this doesn't change as you read from the file. EOF is returned by e.g. fgetc(). See e.g. http://www.drpaulcarter.com/cs/common-c-errors.php#4.2 for common ways to solve this.
here is correct way:
c = getc(pFile);
while (c != EOF) {
/* Echo the file to stdout */
putchar(c);
c = getc(pFile);
}
if (feof(pFile))
puts("End of file was reached.");
else if (ferror(pFile))
puts("There was an error reading from the stream.");
else
/*NOTREACHED*/
puts("getc() failed in a non-conforming way.");
fclose(pFile);
pFile is a pointer to a file. EOF is usually defined as -1, a signed integer.
What you should do is fopen, make sure pFile != NULL, then call some function on the file handle until that function returns EOF. A pointer will (or rather, should) never be EOF. But a function acting on that pointer may return EOF.
I'm guessing you want to keep looping while you haven't hit end-of-file. In that case, you are looking for this:
while (!feof(pFile))
{
...
}
That said, this is still not quite correct. feof will only return true once it tries to read beyond the end of the file. This means feof can return false and yet there is no more data to read. You should really try your operation and only check for end of file if it fails:
char buffer[SIZE];
while (fgets(buffer, sizeof(buffer), pFile))
{
...
}
if (!feof(pFile))
{
// fgets failed for some reason *other* then end-of-file
}