Unexpected error when reading from a text file in C - c

I'm trying to read text from a file (should be pretty easy right?). As far as I recall, the syntax should look something like
FILE *filename;
filename = fopen("filename.txt", "r"); /*when file is the same
folder of the .exe*/
Below is my code. When I run it, I simply get "Error", which is the prompt I wanted in case of an error. I included here a global struct declaration because it's literally the only other thing in the code, even though I'm positive it's not causing any problem with opening the file.
#include <stdio.h>
#include <stdlib.h>
struct list {
char subject[20];
char prof_name[20];
char prof_surname[20];
char period[20];
int credits;
int pass_rate;
};
int main()
{
struct list data[80];
FILE *prof;
prof = fopen("professor.txt", "r");
if (prof == NULL) {
fprintf(stderr, "Error");
exit(EXIT_FAILURE);
}
return 0;
}
The file has the correct name and extension, it's in the same folder as the .exe (I've also tried with the address, it still does the same). I feel like I'm going to get crazy if I look at the code even for just one more minute. There must be something I missed

Regarding the comment "when file is the same folder of the .exe", that is incorrect.
Instead relative paths (like your professor.txt) is relative from the process current working directory. Which might be very different from the location of the .exe file.
My guess is that you're running inside Visual Studio (or other IDE) which places the executable files in a sub-directory. The working directory when running, though, is usually the project root directory.
So either go into the project settings and change the working directory when running the program into the directory where the file is located, or move the file to the actual working directory.
You can use the _getcwd function to get the process working directory, to verify that it is what you believe it is.

Related

Use fopen independently on the current directory

Let's say I am in 2 differents directory:
On the one hand:
print_text_from_file.c
text_to_be_printed.txt
On the other hand:
src/
print_text_from_file.c
text_to_be_printed.txt
And the source code from the .c:
// can't use argv
int main(void){
FILE *fp = fopen ("text_to_be_printed.txt", "r");
if (fp != NULL) {
// working function which takes fp and prints it as expected
print_from_file(fp);
fclose (fp);
}
else {
printf("The file doesn't exist\n");
}
return 0;
}
And let's say, the file only contains Hello World !
If I compile it
After compiling it from being in the first directory with gcc print_text_from_file.c
and after executing it with ./a.out, the output is:
Hello world ! (exactly what I want)
However if I'm in the second case, I'll compile being on src : gcc print_text_from_file.c
and then execute it with being out of src: ./src/a.out, the output is:
The file doesn't exist.
So basically the challenge is that I can't use argv AND I can't know from where the user will execute the file (so I don't know if using absolute paths would be correct). From anywhere, the program will have to print Hello World !.
You really should read something like Advanced Linux Programming and something about operating systems.
And you might also look into syscalls(2) and credentials(7)
The important notions are working directory, process, glob, unix shell, and PATH
See also chdir(2), path_resolution(7), glob(7), getcwd(3), exec(3), proc(5)
There are several issues here:
gcc generates the a.out file at the working directory. It does not matter whether your build print_text_from_file.c or src/print_text_from_file.c, the a.out file is created at the same place, at the working directory (not at src directory). When you run src/a.out, I don't know what did you actually run, maybe an old artifact.
The file opened by the program calling fopen is relative to the working directory. If you want to open the file src/text_to_be_printed.txt you should give path which is relative to the working directory (i.e. src/text_to_be_printed.txt).
Alternative way is to give the full path of the file. e.g. something like /home/myuser/src/text_to_be_printed.txt; this way, the program will find the input file, not as relative to the working directory but as absolute path.
In order to enable the user to give you the path, you shall change the main function signature to get arguments from the user. It should be: int main(int ac, char **av). The user shall run the command like this ./a.out INPUT_FILE_PATH, where INPUT_FILE_PATH is either relative to the working directory or absolute path.
You can access INPUT_FILE_PATH within your code as av[1]. Code will look like this:
int main(int ac, char **av){
const char *input_path = av[1];
FILE *fp = fopen (input_path, "r");
...

How to make .txt files visible to Visual C

I'm writing a program to that needs to read 32-bit binary numbers in as strings from a text file (notepad). The file contents look like this:
11111111111111110111100011111110
11111111111111111111111111110101
00000000100001011010101011110101
00000000000000000000000010010001
Every time I try to run the code I get the error message saying that the debug assertion failed because the (stream != NULL) condition was not satisfied. I assume that this comes from an error with the fscanf part of the code. I have looked at similar questions with the solution usually being to move the text file to the current working directory, but I am not sure what this means. I am using visual studio Express 2013, and have the text file saved under resource files in my console application. I also have the console application and the text file saved in a single folder on my desktop. Neither of these seem to have had any effect in resolving the error. Here is my source code if it helps at all:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
void main()
{
char str[34];
FILE *binnz;
binnz = fopen("binns.txt", "r");
while (fscanf(binnz,"%s",str) != EOF)
{
printf("%s\n", str);
}
fclose(binnz);
}
If the problem is where the text file is stored, where -exactly- do I put it?
Thanks in advance.
I have looked at similar questions with the solution usually being to move the text file to the current working directory, but I am not sure what this means.
The working directory of a program basically allows it to open files by a relative path. Typically, the working directory of a program will be wherever the executable file resides (so it can easily reference files in the same directory); however, when debugging in Visual Studio, it'll use the project directory as the working directory by default. You can change this under the "Debugging" page of your project settings, or you can just put binns.txt in your project directory.
The resource directory is the wrong place. Add a system("dir") to your program, and it will show you where your program is running. Put your file in there, and you should be good to go.

program doesnt work if called from another folder

In Command Prompt, this works: whatever\folder> bezier.exe
but this doesn't: whatever> folder\bezier.exe
My bezier program loads some settings from a local file, so I believe the problem is that the program thinks its directory is whatever\ when it is actually whatever\folder\. I'm calling it from within a C program using CreateProcess(). If I am correct in guessing the problem, is there any way to ensure the program has the right directory for itself?
the main method of bezier.exe:
int main(int argc, char* argv[]) {
char buf[200];
FILE* f = fopen("out.txt","w");
GetCurrentDirectory(200,buf);
fprintf(f,buf);
fclose(f);
SDL_Surface* screen;
SDL_Event e;
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_FULLSCREEN|SDL_HWSURFACE);
if (screen == NULL)
exit(-1);
SDL_ShowCursor(SDL_DISABLE);
srand(time(NULL));
loadColors(COLOR_FILE);
fill(screen, backColor);
initialiseVars();
while (e.type != SDL_KEYDOWN)
{
//do stuff
}
SDL_Quit();
return 0;
}
Here's the crazy part. With "..> folder\bezier.exe" it doesn't write its path, but it does start a new window. That doesn't make any sense to me, because SDL_SetVideoMode is after writing the path.
You can use GetModuleHandle and GetModuleFileName to find out where your execuatble file is, then use that information to create a file specification for your local settings file.
GetModuleHandle with a NULL argument will give you the handle for the current executable. Then, passing that to GetModuleFileName will give you the fully qualified name of that executable. Just strip off the executable filename from the end and add your configuration file name.
However, that's been a bad idea for a long time now, since Windows provides per-application and per-user settings areas for this sort of stuff - you can generally get those locations with SHGetFolderLocation() and its brethren.
Use the first method only if this is for a personal project. If you plan to release your software to the wild, you should separate executable and configuration information as per Microsoft guidelines.
Regardless of that, it appears you now have the problem that you think the file is not being written to. You need to check that. When you open that file out.txt for write, it does so in the current directory. If you're running in the parent directory (with folder\bezier.exe), it will create it in the parent directory and looking for it in the folder directory is a waste of time.
If you are looking in the directory where you're running the program from, and it's still not being created, there are possible reasons for this. For a start, you should check (ie, capture and output) the return codes from all those f* functions, fopen, fprintf and fclose.

Reference a file in C static library

I created a static library in C using Visual Studio. This library contains a function which accesses a text file stored in that current directory. The library was built properly. But the problem is that when I call the function from outside other project it is not loading that text file( I linked the .lib file properly everything else is working except for loading of that file).
Any ideas how to load a text file from .lib file just by relative path??
Thanks in advance..
The following is the library test function definition
int test()
{
FILE *fp = fopen("hello.txt", "r");
if(!fp) printf("File Error");
return 0;
}
The test.lib file is built and created for this.
Just accessing the current folder hello.txt file but when this function is called from other Project. it is saying File Error.
Modify your code to look at the errno:
#include <errno.h>
#include <string.h>
...
if(!fp) printf("File error: %s\n", strerror(errno));
And then look up the meaning of the errno on your operating system to see what's going on.
I'm pretty sure the fact that you're calling this function from a library is a red herring.
What's most likely happening is that your hello.txt file is not in the working directory of the executing process. Go ahead and #include <windows.h> in your project, and use the GetCurrentDirectory function to see what the working directory is when you run your program. Most likely, it's not the same path as your text file.
To remedy this, you can do one of two things: you can change the startup settings of the program (whether that's from Visual Studio or a Windows shortcut) to specify the working directory (called "Start in:" for a Windows shortcut) to be the path to the text file you want to open, or you can figure out what working directory your program has been using and move your text file there instead.
Edit: Also, if you want the application to use its own directory (where the executable file actually resides) you can use the GetModuleFileName function to get the full path of the executable. Of course, you'll have to trim the filename of the program off the end of the string it produces, but that should be a piece of cake.
Check your file path and print an errno, I think you have a static file path

Unable to open a file with fopen()

I've been trying to open a file and output text, but I keep getting errors. So I thought I would start at the very beginning and just try opening the file. This is my code:
#include <stdio.h>
#include <stdlib.h>
#define CORRECT_PARAMETERS 3
int main(void)
{
FILE *file;
file = fopen("TestFile1.txt", "r");
if (file == NULL) {
printf("Error");
}
fclose(file);
}
When I run the file, "Error" gets printed to the console and that's it. The TestFile1.txt is in the same location as my .exe. How do I fix this?
Instead of printf("Error");, you should try perror("Error") which may print the actual reason of failure (like Permission Problem, Invalid Argument, etc).
How are you running the file? Is it from the command line or from an IDE? The directory that your executable is in is not necessarily your working directory.
Try using the full path name in the fopen and see if that fixes it. If so, then the problem is as described.
For example:
file = fopen("c:\\MyDirectory\\TestFile1.txt", "r");
file = fopen("/full/path/to/TestFile1.txt", "r");
Or open up a command window and navigate to the directory where your executable is, then run it manually.
As an aside, you can insert a simple (for Windows or Linux/UNIX/BSD/etc respectively):
system ("cd")
system("pwd")
before the fopen to show which directory you're actually in.
Your executable's working directory is probably set to something other than the directory where it is saved. Check your IDE settings.
A little error checking goes a long way -- you can always test the value of errno or call perror() or strerror() to get more information about why the fopen() call failed.
Otherwise the suggestions about checking the path are probably correct... most likely you're not in the directory you think you are from the IDE and don't have the permissions you expect.
Well, now you know there is a problem, the next step is to figure out what exactly the error is, what happens when you compile and run this?:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *file;
file = fopen("TestFile1.txt", "r");
if (file == NULL) {
perror("Error");
} else {
fclose(file);
}
}
In addition to the above, you might be interested in displaying your current directory:
int MAX_PATH_LENGTH = 80;
char* path[MAX_PATH_LENGTH];
getcwd(path, MAX_PATH_LENGTH);
printf("Current Directory = %s", path);
This should work without issue on a gcc/glibc platform. (I'm most familiar with that type of platform). There was a question posted here that talked about getcwd & Visual Studio if you're on a Windows type platform.
Try using an absolute path for the filename. And if you are using Windows, use getlasterror() to see the actual error message.
The output folder directory must have been configured to some other directory in IDE. Either you can change that or replace the filename with entire file path.
Hope this helps.

Resources