fopen() function does not work as expected on my friends PC - c

I have written the following file:
#include <stdio.h>
#include "config.h"
FILE* fptr;
void writeConfig(const char* new_api_key) {
if ((fptr = fopen("../config.txt", "w")) == NULL) {
printf("Error creating config file");
} else {
fprintf(fptr, "%s", new_api_key);
fclose(fptr);
}
}
char* readConfig(char* buffer, size_t bufSize) {
if ((fptr = fopen("../config.txt", "r")) == NULL) {
return "error opening config file";
} else {
if ((fgets(buffer, bufSize, fptr)) == NULL) {
fclose(fptr);
return "error reading config file";
}
else {
fclose(fptr);
return buffer;
}
}
}
And on 3 different tested machines this code works. But on one of my friends PC it does not.
The code gets executed as following:
char buffer[50];
long long bufSize = 50;
char* message = "example123";
writeConfig(message);
printf(readConfig(buffer, bufSize));
As seen in the "writeConfig" function, this creates a new txt file named "config.txt" and then tries to read it via the "readConfig" function. Weird is, that the "writeConfig" function does not throw an error, even tho the file is not created in his case. Only the "readConfig" function throws the error "error opening config file" which means that fopen() returned NULL.
We have also tried manually creating the config.txt file but the code still failed at the "readConfig" function with the same error.
I have the feeling that it could be about some read and write permissions? But i can not come up with a solution.
(Both PC run Windows)
Any help is appreciated :)

Related

fopen() fails but seems to not return NULL?

I have got the following code:
#include <stdio.h>
#include "config.h"
#include <errno.h>
char buffer[50];
long long bufSize = 50;
FILE* fptr;
char* readConfig(char* buffer, size_t bufSize) {
fptr = fopen("config.txt", "rt");
if (fptr == NULL) {
return "error opening config file: %s", strerror(errno);
} else {
if ((fgets(buffer, bufSize, fptr)) == NULL) {
fclose(fptr);
return "error reading config file: %s", strerror(errno);
}
else {
fclose(fptr);
return buffer;
}
}
}
For test purposes I deleted the config.txt file so that the fopen() function should return NULL.
What wonders me is that fopen("config.txt", "rt"); fails, but when debugging the code it just skips the "if (fptr == NULL) {...}" part and directly jumps out of the function.
When going on with the debugging process, I get the following error when trying to work with the return Value of readConfig() "0xC0000005: Access violation reading location 0xFFFFFFFFA4E0EB70"
Cannot compile your code as you shared a snippet (no main()) and didn't include config.h.
#include <string.h> for strerror().
Suggest caller passes in local variables instead of global variables.
Instead of hard-coding the size in both buffer[50] and bufSize = 50; use sizeof to determine the size of the array. The other good alternative is to define a constant.
The fopen() mode "t" isn't standard, so either leave it out or tag your program with windows or whatever.
As you return on error, eliminate the unnecessary else & indentation.
The expression return "error opening config file: %s", strerror(errno); doesn't work the way you expect, it will evaluate the first part in void context then return the 2nd part strerror(errno). I was not able to otherwise reproduce any ill effects.
fgets() return NULL on eof or error but not appear to set errno. You can use feof() and/or ferror() to tell which if needed.
After the call to fgets() you call fclose() prior to inspecting errno, so it have the status of the fclose() call instead.
It's a bad design to return either error message or the value you read from the file as you cannot tell them apart. Changed to return NULL on success.
#include <errno.h>
#include <stdio.h>
#include <string.h>
char *readConfig(char *buffer, size_t bufSize) {
FILE* fptr = fopen("config.txt", "r");
if(!fptr)
return strerror(errno);
if(!fgets(buffer, bufSize, fptr)) {
fclose(fptr);
return "fgets eof/error";
}
fclose(fptr);
return NULL;
}
int main(void) {
char b[50];
const char *error = readConfig(b, sizeof b);
if(error) {
printf("error: %s\n", error);
return 1;
}
printf("%s", b);
}
Consider having caller open the file and pass in the FILE *. It gives you the flexibility, for instance, to use stdin as the file handle.
I prefer using goto instead of the multiple returns when resource cleanup is required. It's a bit more verbose here but each error case is handled the same way. When you swap the arguments you can document how they are related with recent compilers:
char *readConfig(size_t bufSize, char buffer[bufSize]) {
char *r = NULL;
FILE* fptr = fopen("config.txt", "r");
if(!fptr) {
r = strerror(errno);
goto out;
}
if(!fgets(buffer, bufSize, fptr)) {
r = "fgets eof/error";
goto out;
}
out:
fptr && fclose(fptr);
return r;
}

check if function was called before

Here is my basic code that I'm trying to work with.
void test(){
FILE *input;
input = fopen("input.txt.", "r");
}
So I'm trying to check if file was already opened before, meaning that void test() function was called once before. I realy have no idea how to do that, i tried it with while and if.
Like this.
void test(){
FILE *input;
int open = 0;
while (open == 0){
input = fopen("input.txt", "r");
if (input == NULL){
printf("File wasnt opened.\n");
}
if (input != NULL){
printf("File is opened.\n");
}
open = open + 1;
}
if(open!=0){
printf("file is already opened.\n");
}
}
Use a local static variable.
void test (void)
{
static bool called_before = false;
if(called_before)
{
do_this();
}
else
{
do_that();
called_before = true;
}
}
Supposing that your intent is for test to open the file just once but to read from the file each time it is called, you can make input static:
void test(void)
{
/* Since input is static, it will be initialized with NULL when the
program starts and we will retain its value between calls to
the function.
*/
static FILE *input = NULL;
// If input has not been set for an open file yet, try to open it.
if (!input)
{
input = fopen("input.txt", "r");
if (!input)
{
fprintf(stderr, "Error, unable to open input.txt.\n");
exit(EXIT_FAILURE);
}
}
for (int c = fgetc(input); c != EOF && c != '\n'; c = fgetc(input))
putchar(c);
putchar('\n');
}
Note static objects should generally be avoided, as they complicate program state and so may lead to more bugs. It is okay to play with them in student programs to learn how they work, but their use in real-world applications should be limited.

C language: reading a .txt file

I'm trying to write a program that reads a text file, using C with Visual Studio.
This is my current code (which doesn't work):
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *filePTR;
char fileRow[100];
filePTR = fopen_s(&filePTR, "text.txt", "r");
// Opens the file
if(filePTR){
while(!feof(filePTR)) {
// Reads file row
fgets(fileRow, 100, filePTR);
// Displays file row
printf("%s \n", fileRow);
}
printf("\nEnd of file.");
}
else {
printf("ERROR! Impossible to read the file.");
}
// Closes the file
fclose(filePTR);
return 0;
}
I'm getting the following warning:
'filePTR' may be '0': this condition does not meet the function specification 'fclose'.
What am I doing wrong? I haven't been programming in C since a while ...
The problems begin long before the fclose. This line is incorrect:
filePTR = fopen_s(&filePTR, "text.txt", "r");
It overwites the file pointer already assigned by passing a pointer as the function argument &filePTR.
The function returns an error status, not the file pointer. Please see the man page:
Return Value Zero if successful; an error code on failure.
Also, please see Why is while ( !feof (file) ) always wrong?
I suggest this:
#include <stdio.h>
#include <stdlib.h>
int main(void) { // correct definition
FILE *filePTR;
char fileRow[100];
if(fopen_s(&filePTR, "text.txt", "r") == 0) {
while(fgets(fileRow, sizeof fileRow, filePTR) != NULL) {
printf("%s", fileRow); // the string already contains a newline
}
fclose(filePTR); // only close if it was opened
printf("\nEnd of file.");
}
else {
printf("ERROR! Impossible to read the file.");
}
return 0;
}
Note that I moved the fclose call up. You can't close a file that you did not open.

How do I remove SEGFAULT here?

I created a function to print the contents of a file:
void readFile(char* filename)
{
int c ;
file = fopen(filename, "r");
printf("The contents of the file are:\n");
while((c = fgetc(file)) != EOF)
{
printf("%c", c);
}
return;
}
where file is a global variable. GDB gives output as follows:
_IO_getc (fp=0x0) at getc.c:39
39 getc.c: No such file or directory.
(gdb) bt
#0 _IO_getc (fp=0x0) at getc.c:39
#1 0x000000000040075e in readFile ()
#2 0x00000000004006d4 in main ()
However, the file is present and I get the SEGFAULT after printing the contents of the file. It might be because the buffer here (c) is small but I am not sure. Also, I don't know how do I fix this even if that were the case. Can anyone suggest how do I proceed?
EDIT
I call the readFile function only once. Here is my calling function:
int main(int argc, char* argv[])
{
char * filename;
filename = argv[1];
readFile(filename);
printf("File Handler: %ld", (long)file);
fclose(file);
return 0;
}
You're passing in a filename that doesn't exist or for some other reason cannot be opened. Get rid of the segfault by checking for errors (you'll need to #include <errno.h> and <string.h> too for this:
void readFile(char* filename)
{
int c ;
file = fopen(filename, "r");
if (file == NULL) {
printf("Cannot open file '%s' : %s\n", filename, strerror(errno));
return;
}
printf("The contents of the file are:\n");
while((c = fgetc(file)) != EOF)
{
printf("%c", c);
}
return;
}
Most likely your file is NULL and you are still trying to read it.
I simulated this behaviour (SEG fault) when I deleted this file.
If file exists then your code works fine.
Check what path you are passing.. If you are using single \ try with \\ and see if this works. First \ will work as escape sequence and final path will be send as D:\temp\use.dat to fopen.
readFile("D:\\temp\\user.dat");
Before you do anything with a file, you must ensure that you opened it successfully. This is done by checking that the file pointer received by calling fopen is not NULL.
Once you do this, you read using whatever function you choose until it returns a value that indicates failure to read — a NULL pointer for fgets, 0 or EOF for fscanf, or EOF for fgetc.
In any case, you challenge these return values in two ways. The first way is to check for read errors using ferror. The other way is to check whether the end of the file was reached using feof.
A complete program that should work, based upon your code:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
enum { OPEN_ERROR = 1, READ_ERROR };
enum { PARAM_EXIT = 1, OPEN_EXIT, READ_EXIT };
FILE *file = NULL;
int readFile(char* filename)
{
int c;
file = fopen(filename, "r");
if (file == NULL)
return OPEN_ERROR;
printf("The contents of file '%s' are:\n", filename);
while((c = fgetc(file)) != EOF)
printf("%c", c);
/*
* fgetc returns EOF on end of file and when an error occurs.
* feof is used to determine whether the end of the file was reached.
* Otherwise, we encountered a read error.
*/
if (feof(file))
c = 0;
else
c = READ_ERROR;
return c;
}
int main(int argc, char *argv[])
{
int status = 0;
if (argc == 1) {
fprintf(stderr, "usage: %s file\n", argv[0]);
return PARAM_ERROR;
}
/* Check that <program ""> wasn't used... */
if (argv[1][0] == '\0') {
fprintf(stderr, "error: empty filename detected, exiting. . .\n");
return PARAM_ERROR;
}
switch (readFile(argv[1])) {
case 0:
break;
case OPEN_ERROR:
fprintf(stderr, "error: file open failed - %s\n", strerror(errno));
status = OPEN_EXIT;
break;
case READ_ERROR:
fprintf(stderr, "error: file read failed - %s\n", strerror(errno));
status = READ_EXIT;
break;
default:
fprintf(stderr, "error: unknown error occurred, aborting...\n");
abort();
}
if (file != NULL)
fclose(file);
return status;
}
Of course, normally you would close the file in the same function in which it was opened (e.g. something like filep = openFile(...); readFile(filep); fclose(filep);, except error handling would be used of course).
I am completely changing my answer
Actually, the file that I was reading was open in gedit (which might explain why I was getting "NULL" even after printing the file contents. I closed the file and removed my NULL comparison code and it works perfectly fine.
Ok, from everybody's comments I got to know that you basically get a SEGFAULT when you read the contents of file that has NULL contents. I just made a simple fix in my while loop:
while((c != EOF))
{
printf("%c", c);
c = fgetc(file);
if(c == NULL)
break;
}
Problemo solved! (Although, the compiler gives me a warning of "comparison between pointer and integer".)

Debug Assertion Failed in Visual Studio c

int main(int argc, char* argv[])
{
FILE *pfd;//will get the file we are gone read from
char fileName[40];//get files name
char line[1024];
FILE *simulate;//will get the file we are gone read from
char line2[1024];
int arrSize=argc-2;
station * stations=( station * )malloc(sizeof(station)*(arrSize));//intilzing ther array
int i=2;//Auxiliary variable for the first for loop-reads information from all fiels
int j=0; //Auxiliary variable to help as clean the memory
ClientsLinkedList* data;
Link * temp;//temp varbale to help us clean the memory
Link * tempNext;
if(stations==NULL)
{
printf("Failed to allocate memory");
}
for(i;i<argc;i++)
{
data=CreateClientsLinkedList();
stations[i].m_clients=*data;
strcpy(fileName,argv[i]);
///* Open the file. If NULL is returned there was an error */
if((pfd = fopen("station.txt" , "r")) == NULL)
{
printf("Error Opening File.\n");
}
while( fgets(line, sizeof(line), pfd) != NULL )
{
ReadByCharName(line,stations,i);
}
fclose(pfd); /* Close the file */
}
////************************************************reading from simulation file*******************************************
/*** Open the file. If NULL is returned there was an error */
if((simulate = fopen("simulation.txt", "r")) == NULL)
{
printf("Error Opening File.\n");
}
while( fgets(line, sizeof(line2), simulate) != NULL )
{
ReadSimulation( line2,arrSize,stations);
}
fclose(simulate); /* Close the file */
////*********************************************clening memory****************************************
for(j;j<arrSize;j++)
{
temp=stations[j].m_clients.m_head;
while(temp!=NULL)
{
tempNext=temp->m_next;
free(temp);
temp=tempNext;
}
}
free(stations);
return 0;
}
this is the main of our program that shold get one simoulation file and unknow number of station files and initilizing the data structure from them.
but when we try to run the project we get a "Debug Assertion Failed" error.
please if you can help us to solve the priblem we need to submit the project by sunday.
thank you!
There is at least a bug here: stations[i].m_clients=*data;: i starts at 2, I believe.

Resources