Reading a file using argc and argv - c

I'm trying to (as the title says) read from a file into main, using argc and argv, taking the filename from the command line and passing it through main into a void function which opens, reads and writes it. However im getting Cannot open file... Segmentation fault.
void file_pass (char * argv[])
{
FILE *file_name;
if ((file_name = fopen(argv[1], "r")) == NULL)
{
printf("Cannot open file ...\n");
}
fclose(file_name);
}
Which leads me to think it isn't opening the file correctly but I'm not sure why.

In your function void file_pass (char * argv[]) -
if ((file_name = fopen(argv[1], "r")) == NULL)
Instead of this , you should try this -
if ((file_name = fopen(argv[0], "r")) == NULL) // file's name is in argv[0] in funciton
Because array indexing start with 0 and in function argv[1] may contain nothing .

Related

How to fix code to open files passed in the command prompt in codeblocks

I'm trying to pass the names of the arguments to be readen in codeblocks through set program arguments. When I open them directly, I use
FILE * file_1 = fopen("file31.ll", "r");
FILE * file_2 = fopen("file32.ll", "r");
And it works, cause file31 and file32 are in the same paste as the file. However, when I create a project (and put the files inside its paste), I try to write file31.ll and file32.ll in the arguments and it doesn't work. When compilling, the program warns that the files couldn't be open because the directory wasn't found ("error opening the file : no such a file or directory"). I've also tried writing "file31" and "file32", and also copied the address in Windows like:
C:\Users...\opening_files\file31
where opening_files is the name of the project
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "LCS.h"
int main(int argc, char * argv[])
{
if (argc < 3) {
printf("Incorret number of arguments!\n");
exit(1);
}
//I print argc and argv to test if the arguments are being passed correctly
printf("argc = %d\n", argc);
for (int i=1; i<argc; i++) {
fputs(argv[i], stdout);
printf("\n");
}
//They are printed correctly
//However, when trying to open the files, the program warns that the
//directories weren't found
//Opening the files
FILE * file_1 = fopen(argv[2], "r");
FILE * file_2 = fopen(argv[3], "r");
if (file_1 == NULL || file_2 == NULL)
{
perror("Error opening file\n");
}
I tried to read some other posts about this online but I haven't understand them very well, cause I'm pretty new to programming.
The indexing of the argv[] is incorrect. The argv[1] store the file_1 path and the argv[2] store the file_2 path.
FILE * file_1 = fopen(argv[1], "r");
FILE * file_2 = fopen(argv[2], "r");

Open files with argv gives me file NULL

I have a program that should take the file's name from command line using argc and argv. Printing argv[1] and argv[2] show me the exactly names I passed, but passing argv[1] and argv[2] as parameters to open the files in another function just show the error line I put if can't open the file.
My main:
int main(int argc, char* argv[])
{
if (argc != 4)
{
puts("Incorrect number of parameters.");
return 1;
}
else
{
Image *a, *b;
a = OpenFile(argv[1]);
b = OenFile(argv[2]);
} /* else */
return 0;
} /* main */
The function OpenFile will return a struct filled with information from the file. Here's the first part of the function:
Image *OpenFile(char* name)
{
FILE* f = fopen(name, "r");
Image* imagem;
int temp, i, cont, data[MAX];
char aux[2];
if(f == NULL)
{
puts("Error opening file.");
return NULL;
} /* if */
...
}
I'm passing the correct names but I receive the "Error opening file." line for each file I try to open.
Edit: It's giving me "No such file or directory", but I copied the files to the directory where the .exe is placed. It's not the first time I use the file's name from command line, but it's the first time I pass as parameters to another function.
From fopen man page:
RETURN VALUE
Upon successful completion fopen(), fdopen() and freopen() return a FILE pointer. Otherwise, NULL is returned and
errno is set to indicate the error.
So You could change:
if(f == NULL)
{
puts("Error opening file.");
return NULL;
} /* if */
With:
if(f == NULL)
{
perror("fopen");
return NULL;
} /* if */
And you ll get a pretty descriptive message on the reason fopen failed.
You should include errno.h in order to use perror

Weird bug using fopen() inside a function

I've been looking around for like 4hours and cannot find where the problem is.
I got this function over here which is supposed to open a file.
In the function I successfully get into the != NULL condition thus returning 1, then in the main the value of my pointer test_file_1 is null (and then segfault when fclose)
I do not understand why because I am assigning the return value of fopen to my pointer !!
Here is the prototype :
/*
* Open a file and save its file pointer into file_to_load
* If it worked, returns 1
* Else, 0
*
* Prints its own error message, so you only have to use the return
* value to set the program behavior as wished
*
* filename : name of the file (+ path if needed)
* file_to_load : the file to be loaded
*
*/
int load_file(char* filename, FILE* file_to_load);
And here is the function by itself :
int load_file(char* filename, FILE* file_to_load)
{
//r is for read-only mode, we do not want to let the program edit the file
//We will only save when told (using save_file)
if( (file_to_load = fopen(filename, "r")) != NULL )
{
return 1;
}
else
{
fprintf(stderr, THE_FILE);
fprintf(stderr, filename);
fprintf(stderr, CANT_BE_OPENED);
// Should include the error number for convenience
return 0;
}
}
And .. here is the use in the main :
FILE* test_file_1 = NULL;
//Closed only if exists or else .. segfault
if ( (load_file("../bin/test", test_file_1)) == 1)
{
fclose(test_file_1);
}
C is pass-by-value, not pass-by-reference.
That means a function always gets a copy of its arguments, and changing its copy has no effect on the expression used on calling.
Use additional indirection, here the modified lines (each has exactly one * or & more):
int load_file(char* filename, FILE** file_to_load);
int load_file(char* filename, FILE** file_to_load)
if( (*file_to_load = fopen(filename, "r")) != NULL )
if ( (load_file("../bin/test", &test_file_1)) == 1)
BTW: It would be better to return the file as the return-value, unless you need the return-value for something else or there are other reasons not shown in the example.
Here is a simple program which pretty much does what you want.
int load_file(char *filename, FILE *file_to_load){
file_to_load = fopen(filename, "r");
if(file_to_load !=0)
return 1;
else
return 0;
}
int main(int argc, char *argv[]){
FILE file_to_load;
if(load_file(argv[1],&file_to_load) == 1)
printf("File exists\n");
else
printf("Error loading the given file\n");
}
I have taken the file as a command line argument and changed the error messages but you can alter it according to your requirements.

Reseting the Argv Pointer after Incrementing

I have a program that opens files based on the char **argv command line arguments. Here's the logic:
char * openErrorString = "Error opening file: ";
FILE *fp1 = fopen(*++argv, "r");
if (fp1 == NULL) {
perror(openErrorString);
return 1;
}
FILE *fp2 = fopen(*++argv, "r");
if (fp2 == NULL) {
perror(openErrorString);
return 1;
}
The problem is, I later want to compare the two files and give meaningful output when lines in the files do not match. Here's the code I wrote for that:
while (fgets(fp1Line, max, fp1) != NULL &&
fgets(fp2Line, max, fp2) != NULL) {
if (strcmp(fp1Line, fp2Line)) {
printf("%s\n","Line discrepancy found:");
printf("%s: %s\n", argv[1], fp1Line);
printf("%s: %s\n", argv[2], fp2Line);
fclose(fp1);
fclose(fp2);
return 0;
}
}
However, when I call argv[1] in my printf statement, I get (null), i.e., the final entry in argv. When I call argv[2], I get TERM_PROGRAM=Apple_Terminal. I have no idea what that is. What appears to be happening is that because I incremented the argv pointer twice when accessing it to open the files, argv now starts at the second command line argument. Is there a good way to reset this behavior other than doing two lines of *argv-- after I open the files?
My advice would be to not modify argv. Make a copy of the pointer into another variable, and increment that. This way you can use argv again and again and not worry about where it's pointing right now.
Just don't increment argv, on example:
FILE *fp1 = fopen(argv[0], "r");
// ...
FILE *fp2 = fopen(argv[1], "r");
There is no reason to change the argv pointer if you need it again. Instead, replace
FILE *fp1 = fopen(*++argv, "r");
by
FILE *fp1 = fopen(argv[1], "r");
and
FILE *fp2 = fopen(*++argv, "r");
by
FILE *fp2 = fopen(argv[2], "r");

Where to place files to be used as command line arguments in Visual Studio

I am creating a project in C using Visual Studio and I need it to read a file and do an analysis on the text in that file. I have to pass the file to the command line, but I do not know where to place this file in order for it to be read. Here's the main method to help explain how this will be working:
int main(int argc, char *argv[]){
FILE * cmdFile;
char * nxtCmd = (char *) malloc(sizeof(char) * STR_LEN);
//Ensure memory allocation for nxtCmd succeeds
if (nxtCmd == NULL){
puts("Memory failed to allocate for nxtCmd.");
exit(1);
}
// check if argc is 2
if(argc == MAX_ARGS){}
else{
puts("Innapropriate number of arguments passed to the program.");
exit(1);
}
// check that argv[1] can be opened
if ((cmdFile = fopen(argv[1], "r")) == NULL){
puts("Can't open the command file.");
exit(1);
}
else{
puts("Command file has opened successfully.");
}
// if both above are true:
// start reading from the cmdfile
while ((nxtCmd = nextLine(cmdFile)) != NULL){
nxtCmd = nextLine(cmdFile);
printf("next line: %s", nxtCmd);
}
}
Any help or comments would be greatly appreciated.
Anywhere will do, just pass it to the program on the command line:
myprog.exe \path\to\file.txt

Resources