Fopen Fails to read from Command line - c

Fopen return NULL based on
'fopen' return a NULL
now I have one file to read and I want to output on console but it throws an error as fp return NULL here a snippet
#include<stdio.h>
int main(char argc,char **argv)
{
if(argc < 2)
{
printf("Usage:\t");
printf("Hash File path");
}
printf("Hash File : %s\n", argv[1]);
FILE *fp = fopen("argv[1]","r");
if(fp == NULL)
{
fprintf(stderr,"Can't open %s\n", argv[1]);
}
else
{
char buff[100];
while(!feof(fp))
{
if(fgets(buff,100,fp) == NULL) break;
fputs(buff,stdout);
}
fclose(fp);
}
return 0;
}
whenever I pass file Path E:\design\test.txt from the command line it always shows error report "Can't open...." like this
so the confusion is
why Fopen Failed to read from Command line?

There are few issues in code. Firstly, this
FILE *fp = fopen("argv[1]","r");
is wrong. First parameter of fopen() should be just argv[1] instead of "argv[1]". For e.g
FILE *fp = fopen(argv[1],"r");
if(fp == NULL) {
fprintf(stderr,"Can't open %s\n", argv[1]);
return 0; /* this you forgot, if fopen fails,then no need to proceed further */
}
Also if argc<2 is true then just wrinting printf() is not enough, you have to ask user to give correct command line input & don't let user proceed further. It should be
if(argc < 2) {
printf("Usage:\t");
printf("Hash File path");
return 0; /* return from here or use exit(0) */
}
Secondly, Read here why feof() is wrong. You can use it like
while(fgets(buff,100,fp) != NULL) { /* no need to use break */
fputs(buff,stdout);
}
instead of
while(!feof(fp))
{
if(fgets(buff,100,fp) == NULL) break;
fputs(buff,stdout);
}

Related

Running is fine but rename() does not work

Simple function code to delete a line from a text file by making a temporary text file that will store the new content once the line has been deleted and replacing the old Storage.txt file with the temporary file.
The delete() function works but my only problem seems to be the rename() function that seemingly won't do as intended.
THE CODE
void delete() {
struct task task;
FILE *fp;
char str[100];
char ch;
int delete_line = 0;
fp = fopen("Storage.txt", "r");
if (fp == NULL) {
printf("Error opening file");
fopen("Storage.txt", "w");
exit (1);
}
printf("\n\n\nAll Tasks\n");
printf("----------\n\n");
do {
ch = fgetc(fp);
printf("%c", ch);
} while (ch != EOF);
fclose(fp);
int line_no,ret;
char filename[] = "Storage.txt";
char newname[] = "temp.txt";
FILE *file, *temp;
file = fopen("Storage.txt", "r");
temp = fopen("temp.txt", "w");
printf("Select Line to delete: ");
scanf("d", &delete_line);
getchar();
temp = fopen("temp.txt", "w");
while (fgets(str, 99, fp) != NULL) {
line_no++;
if (line_no != delete_line) {
fputs(str, temp);
}
}
fclose(file);
fclose(temp);
remove(filename);
ret = rename(newname, filename);
if (ret == 0) {
printf("File renamed successfully");
} else {
printf("Error: unable to rename the file");
}
}
There are some problems in the code:
ch must be defined with type int to detect EOF reliably.
the do/while loop to read the file contents outputs the EOF indicator before testing it. You should use while ((ch = fgetc(fp)) != EOF) putchar(ch);
the identifier delete should be avoided to avoid confusing C++ programmers, use delete_line instead.
you should test for failure of fopen and remove and display the cause of the error.
if opening the file for reading fails, why do you create the file with fopen("Storage.txt", "w") ?
file temp.txt is open twice, which may prevent the rename operation on legacy systems.
line_no is not initialized. It should be initialized to 1 if lines are numbered starting at 1.
reading lines into an array is not reliable for this task as lines longer than 99 bytes will be counted more than once.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void delete_line() {
const char *filename = "Storage.txt";
const char *tempname = "temp.txt";
int ch;
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
exit(1);
}
printf("\n\n\nAll Tasks\n");
printf("----------\n\n");
while ((ch = getc(fp)) != EOF) {
putchar(ch);
}
fclose(fp);
int delete_line = 0;
printf("Select Line to delete: ");
if (scanf("d", &delete_line) != 1) {
fprintf(stderr, "invalid or missing input\n");
exit(1);
}
// read and discard the rest of the user input line
while ((ch = getchar()) != EOF && c != '\n')
continue;
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
exit(1);
}
FILE *temp = fopen(tempname, "w");
if (temp == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", tempname, strerror(errno));
fclose(file);
exit(1);
}
int line_no = 1;
while ((ch = getc(file)) != EOF) {
if (line_no != delete_line)
putc(ch, temp);
if (ch == '\n')
line_no++;
}
fclose(file);
fclose(temp);
if (remove(filename)) {
fprintf(stderr, "Cannot remove %s: %s\n", filename, strerror(errno));
} else {
if (rename(tempname, filename)) {
fprintf(stderr, "Cannot rename %s as %s: %s\n",
tempname, filename, strerror(errno));
}
}
}
Your code opens the "temp.txt" file twice:
temp = fopen("temp.txt", "w");
...
temp = fopen("temp.txt", "w");
And closes it once. That will leave one open file descriptor to the file, untill the program exits.
remove() uses unlink() for deleting files. The man page of unlink() says:
If the name was the last link to a file but any processes still have
the file open the file will remain in existence until the last file
descriptor referring to it is closed.
Ensure that all file descriptors are closed when not needed anymore.
The rename may fail, if file of oldpath or newpath is still open.
temp = fopen("temp.txt", "w"); Call it twice
The two main bugs here are:
1.
scanf("d", ...) instead of
scanf("%d", ...)
scanf() needs a format string to know how to parse the input, just like printf() (the f is for format) needs it to know how to construct the output; and their format string syntax is almost the same.
2.
Unintialized line_no, meaning that it's not guaranteed to start at 0/1, thus it might not ever be equal to delete_line, and will not delete the line.

Passing filename as argument causing segmentaion fault when the file is not found

I want to open a file by taking the filename as a command-line argument and then passing it to a function.
The code works perfectly fine when the file is opened, but it throws a segmentation fault error message when the file is not found. It also works when I shift the file opening logic from the runFile function to main function but it is causing segmentation fault when the filename is passed as an argument to the function.
#include <stdio.h>
#include <stdlib.h>
void runFile(char* fileName);
int main(int argc, char** argv)
{
if (argc != 2)
{
printf("Usage: ./lexer [source]\n");
exit(64);
}
else
{
runFile(argv[1]);
}
return 0;
}
void runFile(char* file)
{
FILE *fp;
if (!filename)
{
printf("Error");
}
fp = fopen(file, "r");
if ((fp = fopen(file, "r")) == NULL)
{
printf("File not opened!");
}
else
{
printf("File opened Successfully!\n");
}
fclose(fp);
}
Write your runFile() function like this:
void runFile(char* file) {
FILE* fp = fopen(file, "r");
if (fp == NULL) {
printf("File not opened!\n");
return;
}
// do something with the file
printf("File opened!\n");
fclose(fp);
}
The problem with your code was that you still called fclose(fp) even when fp was NULL (because it could not open the file); fclose(fp) should be called only once and only when fp != NULL.

C passing File stream as a function parameter

This function gives infinite loop. Any Help? And is it even possible to pass file stream to a function as argument.
#include<stdio.h>
#include<stdlib.h>
void fcopy(FILE *inFILE1){
FILE *inFILEcopy;
char a;
inFILEcopy=fopen("C:/Users/labuser.pcroot-PC.003/Desktop/empoleecopy.bak","w");
do{
a=fgetc(inFILE1);
fputc(a,inFILEcopy);
if(feof(inFILE1))break;
}while(1);
}
int main(){
FILE *inFILE;
inFILE=fopen("C:/Users/labuser.pcroot-PC.003/Desktop/empolee.dat","w");
fputs("My name is Anthony",inFILE);
fcopy(inFILE);
}
To summarize mine and Phil Brubaker comments, modify your code in this way:
#include<stdio.h>
#include<stdlib.h>
void fcopy(FILE *inFILE1) {
FILE *inFILEcopy;
char a;
inFILEcopy = fopen("C:/Users/scifani/Desktop/empoleecopy.bak", "w");
do{
a = fgetc(inFILE1);
fputc(a, inFILEcopy);
if (feof(inFILE1))break;
} while (1);
fclose(inFILEcopy);
}
int main(){
FILE *inFILE;
inFILE = fopen("C:/Users/scifani/Desktop/empolee.dat", "w");
fputs("My name is Anthony", inFILE);
fclose(inFILE);
inFILE = fopen("C:/Users/scifani/Desktop/empolee.dat", "r");
fcopy(inFILE);
}
FILE* fcopy(char* yourFile) { // Or parse a FILE like you did but with a pointer
FILE *inFILEcopy;
inFILEcopy = fopen("C:/Users/labuser.pcroot PC.003/Desktop/empoleecopy.bak", "w");
if (inFILEcopy == NULL)
return NULL; // You'll have to check null to see if fcopy() failed
FILE* inFILE1 = fopen(yourFile, "r");
if (inFILE1 == NULL) {
puts("File to be copied does not exist.\n");
return NULL;
}
for (char a = fgetc(inFILE1); feof(inFILE1);)
{
fputc(a, inFILEcopy);
if (ferror(inFILE1) || ferror(inFILEcopy)) { // If error in one of the two files
if (fclose(inFILE1))
puts("Couldn't close inFILE1\n");
if (fclose(inFILEcopy));
puts("Couldn't close inFILEcopy\n");
puts("Error during copy.\n");
return NULL;
}
}
return inFILEcopy;
}
int main() {
FILE *inFILE;
inFILE= fopen("C:/Users/labuser.pcroot-PC.003/Desktop/empolee.dat","w");
if (inFILE != NULL)
{
fputs("My name is Anthony", inFILE);
if (!ferror(inFILE) || fclose(inFILE)) // If no error when writing and closing works, we can copy
{
inFILE = fcopy("C:/Users/labuser.pcroot-PC.003/Desktop/empolee.dat");
if (inFILE != NULL)
puts("Copy success\n");
}
}
}
I think this is the best way to do this. I am open to any improvement though. Check this link if you have any question regarding the error checkings, someone explains the best way to do so. This should work perfectly.

Adding a file close statement causes a seg fault

When trying to close the file after reading it, I get a seg fault on running the program.
int inputDirectory()
{
char fileName[64];char directoryBuffer[256];FILE *fp;
printf("\n> Please type the filename containing the list of directories. >");
inputFix(fileName, sizeof(fileName));
fp = fopen(fileName,"r");
if(access(fileName, F_OK) == 0)
{
if (fp == 0)
{
printf("> Error opening file.");
return 1;
}
else
{
if (access(fileName, R_OK) == 0)
{
while (fgets(directoryBuffer, sizeof(directoryBuffer), (FILE*)fp))
{
readCheck(directoryBuffer);
printf("%s \n", directoryBuffer);
getInode(directoryBuffer);
}
}
else
{
printf("\n> File can't be read.");
}
}
}
else
{
printf("\n> File %s does not exist ", fileName);
}
fclose(fp);
return 0;
}
void inputFix(char string[],int length)
{
int ch, len = 0;
fgets(string, length, stdin);
string[strcspn(string, "\r\n")] = '\0';
len = strlen(string);
if (len == length - 1)
{
while((ch = getchar()) != '\n' && ch != EOF);
}
}
void readCheck(char string[])
{
string[strcspn(string, "\r\n")] = '\0';
}
Ive been reading into race conditions, but from my understanding there isn't one? Is there a need to check to see if the file exists before trying to open it? Is there a need to include some of the checks that I'm using?
Looking at these lines.
if (fp == 0)
{
printf("> Error opening file.");
fclose(fp); // NOT NEEDED. REMOVE THE LINE
}
It seems you don't need to call fclose when you were not able to open the file.
Remove the line.
If fp is null (equal to 0), you do not need to close it, the file was never opened to begin with. You should close fp after you are done successfully reading from it.
You are closing the file at the end regardless of whether the file ever opened or not. Calling fclose on an unopened file can cause a crash. Try this instead. I have moved the fclose statement to be called only when fp is not NULL.
int inputDirectory()
{
char fileName[64];char directoryBuffer[256];FILE *fp;
printf("\n> Please type the filename containing the list of directories. >");
inputFix(fileName, sizeof(fileName));
if(access(fileName, F_OK) == 0)
{
fp = fopen(fileName,"r");
if (fp == NULL)
{
printf("> Error opening file.");
return 1;
}
else
{
if (access(fileName, R_OK) == 0)
{
while (fgets(directoryBuffer, sizeof(directoryBuffer), (FILE*)fp))
{
readCheck(directoryBuffer);
printf("%s \n", directoryBuffer);
getInode(directoryBuffer);
}
}
else
{
printf("\n> File can't be read.");
}
fclose(fp);
}
}
else
{
printf("\n> File %s does not exist ", fileName);
}
return 0;
}
Only call fclose() on a FILE* which had been returned by a successful call to fopen().
To test wether fopen() had been successful compare its result against NULL. If this test succeeds the call had not been successful:
#include <stdio.h>
int main(void)
{
char filename[] = "myfile";
FILE * fp = fopen(filename, "r");
if (NULL == fp)
{
fprintf(stderr, "fopen(\"%s\", ...) failed.\n", filename);
}
else
{
fprintf(stderr, "fopen(\"%s\", ...) succeeded.\n", filename);
/* Perform operation on fp here. */
fclose(fp);
}
return 0;
}

How to provide the output of the first input file as the second input file in one pass in C?

Assume that I have a file called 1.lex. An input file 1.c is provided. The output of this is the next input. I want this to happen in a single pass because when the first output is produced, the memory buffer contains some information that is required for the second input file.
Below is the code for file handling for the situation explained above.
char * basename(char *name)
{
char *temp;
int i=0, j=0, len;
temp = (char *)malloc(strlen(name));
len = strlen(name);
len--;
while(1)
{
if(name[len] != '.')
len--;
else
{
for( i = 0; i < len; i++)
temp[j++] = name[i];
break;
}
}
temp[j] = '\0';
return temp;
}
int main(int argc, char** argv)
{
if(argc != 2)
{
fprintf(stderr,"Usage: filename\n");
exit(1);
}
yyin = fopen(argv[1],"r");
if(yyin == NULL)
{
fprintf(stderr,"cannot open file: %s",argv[1]);
exit(0);
}
file = basename(argv[1]);
realloc(file, strlen(file)+10);
strcat(file,".met");
yyout = fopen(file,"w");
yyparse();
return 0;
}
int yywrap()
{
fclose(yyin);
yyin = fopen(file,"r");
if(yyin == NULL)
{
fprintf(stderr,"cannot open file: %s",file);
exit(0);
}
file = basename(file);
realloc(file, strlen(file)+10);
strcat(file,".meta");
yyout = fopen(file,"w");
yyparse();
return 1;
}
If I comment yyparse() in yywrap() function, there is no segmentation fault but nothing gets written in ".meta" file but first o/p file ".met" gets written. If I uncomment, there is segmentation fault and nothing gets written in ".met" file.
Function "basename" is to get the basename of the input.
Function main() which opens the first file and calls yyparse().
When yyparse() is finished with the first file, it calls yywrap(), which opens the next file.
Please see the comment above in the yyparse() line.
If there is another way to solve my problem, please let me know.
Thanks.
Create a pipe and open it for writing and assign it to yyout and open the pipe for reading and assign it to yyin
See http://www.gnu.org/software/libc/manual/html_node/Creating-a-Pipe.html
Similar to the code posted initially. I have explained the changes after the code.
int main(int argc, char** argv)
{
file_num++;
argc = file_num_max;
if(argc != 2)
{
fprintf(stderr,"Usage: filename\n");
exit(1);
}
yyin = fopen(argv[1],"r");
if(yyin == NULL)
{
fprintf(stderr,"cannot open file: %s",argv[1]);
exit(0);
}
file = basename(argv[1]);
realloc(file, strlen(file)+10);
strcat(file,".met");
yyout = fopen(file,"w");
while(yylex())
;
return 0;
}
int yywrap()
{
fclose(yyin);
fclose(yyout);
yyin = fopen(file,"r");
if(++file_num <= file_num_max)
{
if(yyin == NULL)
{
fprintf(stderr,"cannot open file: %s",file);
exit(0);
}
file = basename(file);
realloc(file, strlen(file)+10);
strcat(file,".meta");
yyout = fopen(file,"w");
return 0;
} else {
return 1;
}
}
As said before, function main() which opens the first file and calls yylex().
When yylex() is finished with the first file, it calls yywrap(), which opens the next file, and yylex() continues.
When yywrap() has exhausted all the command line arguments, it returns 1, and yylex().
I just did some small changes and it worked but took some time though!
Cheers.

Resources