I am writing a program that reads from a file passed as an arguement, or reads from stdin if no arguements are given.
The code runs fine with a file passed, but I get a seg fault when no file is passed.
I basically call fopen on argv[1] if a file was given, but if no file was given I call:
f = fopen("stdin", "r");
Is this the correct syntax for opening stdin as a file?
When you start a program, the main() function is not the first thing that
get's called, quite a few things happen before the main() function is
called. One of those things is to open stdin, stdout and stderr. In
general you don't need to worry about the details how the OS does that, you
just can relay that when main() is executed, these streams are open and you
can use them.
So in your case, you can do this:
#include <stdio.h>
int main(int args, char **argv) {
FILE *fp;
if(args == 1) {
fp = stdin;
} else {
fp = fopen(argv[1], "r");
if(fp == NULL) {
fprintf(stderr, "Unable to open %s for writing\n", argv[1]);
return 1;
}
}
// do your read operations on fp
if(fp != stdin) {
fclose(fp);
}
return 0;
}
So when you call the program without arguments, stdin is used, otherwise a
file is used.
The reason why your code crashes is because
f = fopen("stdin", "r");
tries to open a file literally called stdin, which you most probably don't
have. fopen will return NULL and you probably don't check for that. If you
try to use a function that expects a FILE* pointer but pass NULL, then
you'll most likely will get a segfault.
USE f = stdin;
NOT f = fopen("stdin", "r");
Related
I'm trying to read a binary file of 32 bytes in C, however I'm keep getting "segmentation fault (code dumped)" when I run my program,
it would be great if somebody can help me out by pointing where did I go wrong?.
my code is here below:
int main()
{
char *binary = "/path/to/myfiles/program1.ijvm";
FILE *fp;
char buffer[32];
// Open read-only
fp = fopen(binary, "rb");
// Read 128 bytes into buffer
fread (buffer, sizeof(char), 32, fp);
return 0;
}
It's because of the path. Make sure that "/path/to/myfiles/program1.ijvm" points to an existing file.
You should always check the return value of fopen.
\\Open read-only
fp = fopen(binary, "rb");
if(fp==NULL){
perror("problem opening the file");
exit(EXIT_FAILURE);
}
Notice also that you are reading 32 bytes in your buffer and not 128 as your comment says.
You must check the return result from fopen().
I'm assuming you are getting the segfault in the fread() call because your data file doesn't exist, or couldn't be opened, and you are trying to work on a NULL FILE structure.
See the following safe code:
#include <stdio.h>
#include <stdint.h>
#define SIZE_BUFFER 32
int main()
{
char *binary = "data.txt";
FILE *fp = NULL;
char buffer[SIZE_BUFFER];
// Open read-only
fp = fopen(binary, "rb");
// Read SIZE_BUFFER bytes into buffer
if( fp )
{
printf("Elements read %ld\n", fread (buffer, sizeof(char), SIZE_BUFFER, fp));
fclose(fp);
}
else
{
// Use perror() here to show a text description of what failed and why
perror("Unable to open file: ");
}
return 0;
}
When I execute this code it doesn't crash and will print the number of elements read if the file is opened or it will print "Unable to open file" if the file could not be opened.
As mentioned in the comments you should also close the file being exiting. Another thing you can do is the following:
FILE *fp = fopen(.....);
Instead of declaring and assigning in two separate steps.
There are two possible reasons
The fopen(3) function failed due to some reason, which means fp is NULL, and then you are trying to use the null-pointer in fread(3). This can crash. #OznOg has already given a subtle hint to look into this direction.
If the fopen call is a success (i.e. fp is non-NULL after calling fopen), the code can still crash because you are reading 32 chars into the variable binary, while binary has been initialized with only 30 chars.
I am trying to check if a file exists by opening it with fopen() and then checking if the function returns NULL. But when I run the code, it says a read access violation error accured, but I don't get why, since I checked and the file I am trying to read is txt and has text already written in it. Can someone explain why and how I can fix it?
int main(int argc, char** argv)
{
int quit = FALSE;
if (fopen(*(argv+2), 'r') == NULL)
{
printf("Invalid input! File does not exit.");
quit = TRUE;
}
}
First, from the fopen manual, we can see that the function signature is:
FILE *fopen(const char *pathname, const char *mode);
What this means is that it will return a pointer of type FILE, and expects two arguments, both pointers to char. The second argument you pass to fopen in your code is a char, not a char*, so we need to fix that. Also, store the returned fopen pointer, as you should use it to close the file after you're done with it.
So, your code would be something like:
FILE *fp;
if ((fp = fopen(argv[2], "r")) == NULL) {
printf("File does not exist!\n");
exit(0);
} else {
/* file exists... do stuff */
fclose(fp);
}
I'm writing an application which should read some data at some level from a file. When I run the code (including fopen() and fclose())for more than a few hundred times, I got the error message (which I know it means that it cannot open the file):
Debug Assertaion Failed!
Program:
D:\blahblah
file: f:\dd\vctools\crt\crtwin32\stdio\fgets.c
Line: 57
Expression: (string!=NULL)
Can you please help me to understand why it should break after more than three hundered time?
Func_Main(char * filePath, ...){
for(int i=0;i<1000;i++){
Func_1(filePath);
....
}
....
}
Func_1(char* filepath){
char buffer[1024];
FILE * file= NULL;
file = fopen(filepath, "r");
while(fgets(buffer, sizeof(buffer), file)){
\\ do something
}
fclose(file);
}
You should check the return value of fopen. It will return a null pointer if opening the file failed.
And it will fail because \ is an escape character , use \\ in the filename string.
Problems I see:
You never use the argument passed to Func_1. You use a hard coded path instead.
The hard coded path has an error. You are not escaping the backslash in the hard coded path . It should be:
file = fopen("c:\\blahblah.txt", "r");
^^
You are not checking whether fopen was successful. You are assuming it was successful. Use:
file = fopen("c:\\blahblah.txt", "r");
if ( file == NULL )
{
// Deal with the error.
perror("Unable to open the file");
}
Update, after the OP edited the question
The first two points can be ignored. The last point still needs to be considered.
file = fopen(filepath, "r");
if ( file == NULL )
{
// Deal with the error.
perror("Unable to open the file");
}
im currently doing a project which works with input files.
The code is doing everything that i want, and its fully correct, the problem is the way im reading the file.
FILE *fp;
fp = fopen (argv[1], "r");
in the terminal im using ./filec input.in, and everything gets printed correctly in the terminal, but i have to open the file in this way:
./filec < input.in > < output.myout > and im not sure what does that entail.
Thank you, and sorry for the poor english
Your argv[1] would have the input file, and yourargv[2] would have the output file.
A basic beginning layout for you to work on would be:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
if (argc != 3)
{
exit(EXIT_FAILURE); //If there are not three arg, terminate the program.
}
FILE *fp_read, *fp_write;
fp_read = fopen(argv[1],"r");
fp_write = fopen(argv[2],"w");
//Do whatever you want with it.
fclose(fp_read);
fclose(fp_write);
return 0;
}
I assume you have a typo and you actually mean:
./filec < input.in > output.myout
Basically, this means you are letting the shell do all the work for you, and your code can simply read from stdin and write to stdout. You might try:
fp = argc > 1 ? fopen(argv[1], "r") : stdin;
It could be you misunderstood the --help option, the first notation you describe is, for commandline arguments, the correct one. "" is just a notation that is used, meaning that you can change the name of the parts between <>.
Anyway, if you really need to use that notation to call your program, you could make a new array containing the argv[1] without <>.
pseudo code:
char newFilename[20];
//skip first and last character (if needed, changes values to skip first two and last two chars
for(i = 1; i < argv[1].length - 2; i++){
newFilename[i - 1] = argv[1][i];
}
fp = fopen (newFilename, "r");
Note that the < and > characters are interpreted as file redirection operations, so you should do (in this case) ./youprogram "< file.in >" "< file.out >"
First, read about fopen(3) and stdio(3)
You want to read from stdin
When calling fopen you always should check for failure, e.g. (after having tested that argc>1, assuming you defined int main(int argc, char**argv) as is conventional!)
FILE *fp = fopen (argv[1], "r");
if (!fp) {perror(argv[1]); exit(EXIT_FAILURE); };
so you probably want:
FILE *fp = NULL; // I prefer always initializing variables
if (argc>1) {
fp = fopen (argv[1], "r");
if (!fp) {perror(argv[1]); exit(EXIT_FAILURE); };
}
else fp = stdin;
If you invoke your program as ./myprog < someinput.txt > someoutput.txt then everything you printf, putchar or send to stdout goes into someoutput.txt, and stdin is the someinput.txt. Generally the redirection is done externally (by the shell on POSIX systems)
scanf(" %[^\n]", in);
then for example , i input Knock Knock and hit enter
but my code block inside
if (strcmp ("Knock Knock",out)==0)
does not work
please instruct me ,thanks a lot!
char in[80],out[80];
void input(){
printf("Client: ");
scanf("%[^\n]",in);
fp=fopen("test","w");
if (!fp) return ;
fputs(in,fp);
fclose(fp);
}
fp=fopen("test","r");
fgets(out,81,fp);
fclose(fp);
fp=fopen("test","w");
if (strcmp ("Knock Knock",out)==0)
fputs("Server: Who is there?\n",fp);
First off, the layout of the code is very confusing, and as it stands, it would never compile. You have a function input() that you never seem to call, and you leave code outside the function that should be inside another function, or better yet, all of it should be contained inside a main() function so that it can be executed. Here is a cleaned up example for what you're wanting to-do:
#include <stdio.h>
char in[80],out[80];
int main()
{
printf("Client: ");
scanf("%[^\n]",in); //you really should use fgets() here
FILE* fp = fopen("test.txt","w");
if (!fp)
{
perror("Failed to open file");
return 1;
}
fputs(in,fp);
fputs("\n",fp);
fclose(fp);
fp = fopen("test.txt","r");
if (!fp)
{
perror("Failed to open file");
return 1;
}
fgets(out,80,fp);
fclose(fp);
fp = fopen("test.txt","a+");
if (!fp)
{
perror("Failed to open file");
return 1;
}
if (strcmp ("Knock Knock\n",out)==0)
fputs("Server: Who is there?\n",fp);
return 0;
}
Some important notes:
1) fp has a file-type FILE*, since that is the return of fopen(), but you never declare it as such. So this would never compile with that error.
2) Every time you open a file with the w flag, it erases the entire contents of the file. So if you were intending on appending to the file to have a history of what your output from your program was, you need to use the a+ flag when calling fopen()
3) It would be nice to have some type of error print-out if you failed to open the file rather than scratching your head at why "test.txt" is empty after the program takes the input from stdin. Also if you're going to keep re-opening the file, check for a NULL each time since you're going to get unpredictable results from trying to work with a NULL file pointer (most likely a crash).
4) scanf() can result in nasty buffer over-runs from user-input (or malicious user input) ... use fgets() with stdin to a known-length buffer instead.
You should be able to compile this code now and run it. Works for me with gcc 4.4.3 on Ubuntu. After running, your "test.txt" file should look like:
Knock Knock
Server: Who is there?