Problems with if ....==NULL in C - c

I have this code, note that it is shortened down. The problem is if the file exists
it still overwrites it. Been 30 years since I did any programming so bear with me. Thanks!
FILE *openFil(FILE *open, char namn[]);
int main(int argc, const char * argv[])
{
FILE *openFil(FILE *open, char namn[]);
FILE *anmal =NULL;
char filNamn[] = "ANMAL.DAT";
postTypAnm pAnm;
anmal = openFil(anmal, filNamn);
}
FILE *openFil(FILE *pointer, char name[])
{
if ((pointer =fopen(name, "r+b"))== NULL)
if ((pointer =fopen(name, "w+b"))== NULL)
{
/* It Enters here as well, but it should not do that or????? */
printf("error\n");
exit(0);
}
return pointer;
}

If you're using the C11 standard you can use the "x" argument to specify that if the file exists the fopen() function will fail.
For reference: http://www.cplusplus.com/reference/cstdio/fopen/

Here's a working example.
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
bool openFile(FILE **ptr,
const char *fileName);
int main(int argc, const char * argv[]) {
FILE *anmal = NULL;
const char *fileName = "ANMAL.DAT";
if(!openFile(&anmal, fileName)) {
exit(EXIT_FAILURE);
}
}
bool openFile(FILE **ptr,
const char *fileName)
{
*ptr = fopen(fileName, "w+bx");
if(!*ptr) {
perror("Error opening file: ");
return false;
}
return true;
}
This is using the x extension in GNU C to test whether the file exists.
As other people have pointed out, there are numerous problems in your original code.
You've redeclared the function prototype for openFil within main.
In openFil there's no point in both accepting the FILE pointer as
a parameter and overwriting it with the return value. Especially if
you're expecting to input a NULL pointer and use the function to
initialise it. Either use a pointer-to-pointer as a parameter so you
can modify the pointer within the function, or ignore it completely
and set its value with the function's return value. Not both.
You're not actually testing for whether the file exists at all. According to the manual pages for fopen (man fopen) neither of the flags you used in opening the file (r+ and w+) care whether the file exists. r+ opens for reading/writing and always positions the stream at the beginning of the file. w+ opens for reading/writing, truncating the file if it exists already. This explains why you didn't get the effect you intended.

1.
"It Enters here as well, but it should not do that or?????"
No, It shouldn´t. If both pointers are NULL the opening of the streams to ANMAL.DAT were not successful, neither in w+b nor in r+b mode. Proof if the file really exist in the directory of the executable. Else try to use the entire path from the root directory to the file.
"The problem is if the file exists it still overwrites it."
Why do you know that the file is really overwritten in a proper manner?
Since if ((pointer =fopen(name, "r+b")) == NULL) and if ((pointer = fopen(name, "w+b"))== NULL) both fail, it seems that the ANMAL.DAT does not exist where fopen() searches for it or otherwise an error occurs when trying to open it (maybe has incorrect format or is corrupted?).
Place perror(name) in the error routine to check if errno was set to indicate an error at name.
2.
In the error routine: exit(0) is not correct if an error has happened. Use exit(EXIT_FAILURE).
Side note:
You have another prototype for the function openFil-> FILE *openFil(FILE *open, char namn[]); inside of main, which is redundant.
Also the identifier of the second parameter is different in the prototype before main to the identifier at the definition of openFil, namn in comparison to name.

Related

C fopen/fwrite driving me to madness - fwrite not writing

Ok, here is the deal...i remember creating a program past week that required me to open a file in binary mode and write data to it. At first, i tried using the fopen function, checking if the result is ok, then try to write data. I remember that at first try, the fwrite operation wasn't working. Then, after moving declaration of variables from a place to another, i was finally able to make the fwrite to insert data to the file.
Now, i need to create another similar program to do some other stuff, so i wanted to use the same allocation code (actually, i wanted to create a specific function to do the same), and here is what i was able to come up with:
#include <stdio.h>
int openfile(FILE *main, char *name, int option);
int main(void)
{
FILE *main;
int header_init;
int result;
switch (openfile(main,"main_file.bin",1)) {
case 1:
header_init = -1;
//fseek(main,0,SEEK_SET); --> useless
fwrite(&header_init,sizeof(int),1,main);
printf("ftell = %d\n",ftell(main)); break;
case 2:
fread(&header_init,sizeof(int),1,main);
printf("%d\n",header_init); break;
default:
printf("Error trying to open file\n");
}
printf("header_init is %d\n",header_init);
fclose(main); exit(0);
}
int openfile(FILE *main, char *name, int option)
{
int result_alloc;
int F_OK;
if (result_alloc = access (name, F_OK) != 0) {
printf("File not found, allocating a new one\n");
if ((main= fopen(name,"w+b")) != NULL) return 1;
}
else {
printf("File exist, allocating as r+b\n");
if ((main= fopen(name,"r+b")) != NULL) return 2;
}
printf("Failure trying to open");
return 0;
}
For some unfortunate reason, the fwrite operation is not writing -1 to the allocated file. My intention with this program is so that it will always check for existence of that specific file: if there is one in place, simply open it with r+b to allow update functions without overwriting the actual file contents. Otherwise, allocate a new one with a header value of -1 (i will use this file as a record file with chained list structure).
Seriously, i cannot understand why this is not working. The idea is the same of my previous program. The only thing that changed is that i created a function, because this is going to happen me later (because of the 3rd parameter that will allow me to reduce my code and make it more "readable" - at least this is the intention!). I HAVE to admit that i have some attention to details problem, but i am working hard to get better at it, i am probably missing something stupid in this code, but after hours looking at it i really wanted to ask here for some help. Thanks
Edit: I am running it under z/Linux. What i am trying to understand is, why the code above doesn't write -1 to the file, but the one below writes ok?
#include <stdio.h>
int main(void)
{
FILE *main;
int result_alloc;
int header_init;
int F_OK;
if (result_alloc = access ("test.bin", F_OK) != 0) {
printf("File not found, allocating a new one\n");
if ((main = fopen("test.bin","w+b")) == NULL) {
printf("Failure trying to open file");
return 1;
}
else {
header_init = -1;
printf("current pos is: w+b %d\n",ftell(main));
fwrite(&header_init,sizeof(int),1,main);
printf("current pos is: write header_init %d\n",ftell(main));
}
}
else {
if ((main = fopen("test.bin","r+b")) == NULL) {
printf("Failure trying to open file");
return 2;
}
else {
printf("current pos is: r+b %d\n",ftell(main));
fread(&header_init,sizeof(int),1,main);
printf("current pos is: read header_init %d\n",ftell(main));
}
}
}
The main issue that the assignment to the main variable inside of the openfile function is not seen by the calling function. Because C is pass by value, you're only changing the value of the function parameter, not the value of the variable that was passed in. So when openfile returns, the main variable inside of the main function is unchanged.
What you need to do is pass the address of that variable to the function, then within the function you dereference the local variable (which is a pointer) and assign a value to the dereferenced variable.
Also, it's not a good idea to have a variable with the same name as a function as it hides the function in that scope and can cause confusion.
So you would define your function as follows:
int openfile(FILE **fp, char *name, int option);
You would then call it like this (changing the name of the main variable to fp):
FILE *fp;
...
openfile(&fp,"main_file.bin",1)
Then inside of openfile, you dereference fp to change the value in the calling function:
*fp = fopen(name,"w+b")
The reason why the second code sample is working is that you're assigning directly to a local variable and then using that same variable later on in the function.
Also, you're "lucky" that the second piece of code is working because you did this:
int F_OK;
F_OK is already defined in unistd.h, where access() is defined. So by doing this you're redeclaring it and not giving it a value, causing undefined behavior. Get rid of this definition, and #include <unistd.h>, and the call to access() is guaranteed to work as expected.

How can I transfer files from one folder to another folder using (C) under UNIX?

I have a text file with the names of about 800 files I want to transfer from one folder to another. Basically, the text file looks like this :
file1.aaa (End of line)
file2.aaa
..
etc
I made this code, using the function 'rename' as everyone suggests on the internet :
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( void )
{
FILE *file = fopen ( "C:\\Users\\blabla\\ListOfFiles.txt", "r" );
char path1[100] = "C:\\blabla\\folder1\\";
char path2[100] = "C:\\blabla\\folder2\\";
char *s1;
char *s2;
char line [20]; /* the file names won't be any longer than that */
while(fgets(line, sizeof line,file) != NULL)
{
char *filePath1 = (char *) malloc((strlen(path1) + strlen(line) + 1) * sizeof(char));
char *filePath2 = (char *) malloc((strlen(path2) + strlen(line) + 1) * sizeof(char));
filePath1 = strcpy(filePath1, path1);
filePath2 = strcpy(filePath2, path2);
strcat(filePath1,line);
strcat(filePath2,line);
if (rename(filePath1, filePath2) != 0)
{
perror("wrong renaming");
getchar();
}
free(filePath1);
free(filePath2);
}
fclose (file);
return 0;
}
Now, when I print the filepaths I get the expected results, but the program stops running when it's supposed to run the 'rename' function, because of an invalid argument problem.
I looked at http://www.cplusplus.com/ and noticed that it says the arguments of rename() should be const char*, could this be where the problem come from ? But if so, I don't see how I could turn my arguments into 'const', since I need to update them as I read my initial text file.
The code that builds the file paths is horribly over-complicated but should work. To simplify it, remove the malloc() and just use two statically-sized arrays. Also, for the future, please don't cast the return value of malloc() in C.
You're misunderstanding the const thing, it means that rename() won't change the characters pointed at by its two arguments. It's a way to say "these two pointers point at data which is input-only to this function, there will be no attempt to modify that data from inside the function". You should always const argument pointers when possible, it helps make the code much clearer.
If you're getting "invalid argument", that probably means the files aren't being found. Print out the filenames to help you verify.
I suggest you to take a look at:
How can I copy a file on Unix using C?
And replace "/bin/cp" for "/bin/mv" in that code.
Hope it helps!

'fopen' in C can't open existing file in current directoy on Unix

I am using fopen(3) in C to read file and process it. The file is present in current working directory where the binary exists, but I am unable to read the file (Linux environment / Cygwin environment).
Here is the sample code:
C code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
FILE *inFile;
static char fileName[255];
int process_file(FILE *inFile)
{
char ch;
inFile = fopen(fileName,"r");
if (inFile == NULL)
{
perror(fileName);
exit(1);
}
else
{
// Process file
}
fclose(inFile);
return 0;
}
int main(int argc, char *argv[])
{
printf("Enter filename to process \n");
scanf("%s", fileName);
process_file(inFile);
getchar();
return 0;
}
I have file permissions set to 777 in the current directory. The resulting binary as well as my source code reside in this directory where the input file exits. Why is the file not opened?
Update :
This question was written in few years back and this code could be improved a lot.
1. The process file should accept char * or char array instead of file pointer
2. unused variables can be removed
3. unused libraries or include files can be removed
4. Can make use of argv to accept filename with path from cmdline
5. return instead of exit in process_file and also proper return code instead of returning 0 from process_file.
I should have asked this question little more elaborate...
I had three functions to process the same file, like process_fil1e1(), process_file2() and process_file3() even though I called fclose() in all three functions. Somehow the file handle was not closed that properly or the file pointer pointed to EOF or some undefined behavior. It was not working fine.
When I used a single process file and rewind() together, it worked fine...
Be sure to input file name with its extension. This may cause problems with reading the file.
If you know the extension of the file you can input only the name and after that make the program add the extension. After scanf("%s", fileName); add strcat(fileName, ".txt"); if you want to enter only the name without extension and the file you read has extension .txt.
Your inFile and fileName variables are extern so you don't need to have arguments for the function process_file();, any function can access those variables.
You can change function int process_file(); to void process_file(); and delete return 0, you don't need that.
You have declared the inFile and fileName as global. You should change your function prototype from
int process_file(FILE *inFile)
to
int process_file()
This would at least make your program more clear. Now regarding your problem: It would almost certain be that you are doing something wrong in the input file (like not putting in the file extension) in your input. Remember, you need to pass the complete file name (including the extension which on some systems like Windows (by default) would be hidden). Otherwise, the logic looks correct to me, and it should work fine.

Is this right? (Read in file in C)

For my assignment I have to create a program similar to the -wc unix command which counts words, lines, etc.
I have to read in flags and read in a text file.
I've set up all the flags and now I'm trying to read in a text file. I don't think I'm doing this right.
void readInFile(char** argv, int arg)
{
FILE *myFile;
char c;
myFile = fopen(argv[arg], "r");
if(!myfile)
{
printf("%s not found!", argv[arg]);
exit(EXIT_FAILURE);
}
}
in my main I call the function readInFile() and pass 2 arguments. Argv and the element where the file should be. So assume this to be correct.
I need help with actually opening up the file. I feel like my fopen() is wrong. I'm new to reading/writing files in C. Thanks alot!
I'm going to give you some general advice here.
Usually functions should do a single job. In this case, you are writing a function to read in a single file. So, don't pass a pointer to all the command-line arguments; pass in a single read-only pointer to the name of the file to open. Then in main() select the correct argument and pass that as the argument.
void readInFile(char const *filename)
Now, if this function will be reading in the file and doing nothing else, it needs to return the data somehow. But if this function will be doing the equivalent of wc, maybe it will read the file and print stuff, not return any data to the main() function. Then maybe the name should be improved:
void wordcount(char const *filename)
The actual call to fopen() looks fine to me.
You check for error, and then call exit() immediately. That's one way to do it. Another way to do it is to return an error code from your function, and have the caller (the main() function) check for failure, and handle the error there.
int wordcount(char const *filename)
{
// ... do stuff
if (failed)
return 1; // return nonzero error code on failure
// ... do more stuff
return 0; // success code
}
int main(int argc, char const **argv)
{
char const *filename;
int result;
filename = argv[1];
result = wordcount(filename);
if (result)
{
fprintf(stderr, "unable to open file '%s'\n", filename, result);
exit(result);
}
return 0;
}
For a program this simple, it doesn't matter much. But once you start building larger systems in software, you will be happier if your functions work well together, and part of that is making functions that return error codes rather than terminating your whole program on any error.
Why am I using 0 for the success code, and non-zero for failure? It's a common way to do it. It's easy to test for non-zero, like if (result) and there are many non-zero codes but only one zero, so you can return many different kinds of errors, but there is only one value needed for "success".
Note that instead of calling exit() from main(), you can just use the return statement. When you return 0 from main(), that signals success, and a non-zero value indicates an error. So you could just use return result; from main() if you like.
In my dummy code, I'm just returning 1 as the error code. But actually, when you call fopen() it returns an error code to you, in a global variable called errno. Probably a better option is to make your function return the actual error code as specified in errno. You could even modify the print statement in the main() function print the errno code, or use the strerror() function to turn that error code into a human-readable message.
Your call to fopen is correct, assuming that argv[arg] is a valid string which refers to a file that exists on the filesystem.
There is a small typo in the program snippet. if(!myfile) should prpbably be if(!myFile). With this change, I presume the code should work. Can you please elaborate the error faced by you?
P.S: I tried your program and it seems to work!

fopen doesn't open

I am using Code::Blocks and have set the command-line arugments via the IDE. I have also opened the executable with the proper argument and I can't manage to get a non-NULL on fopen() return. I've tried hard-coding the filename also with no success. The platform is Windows XP SP3.
The first is the one that fails, when i hardcoded it i used double backlash. Also i never knew if the second works because i never managed to start the process by opening the first one.
Obviously i put the text file in the same directory that the executable and rebuilt the executable many times, but it still doesn't work.
EDIT: I added the perror("fopen"); line in the if(finput==NULL) block. This is the output.
http://prntscr.com/h71pa
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define first_part_url "[url=http://magiccards.info/query?q="
#define second_part_url "&v=card&s=cname]"
#define end_bracket "[/url]\n"
#define output_file_prefix "output_"
char* get_card(FILE* finput);
int main(int n, char* arguments[])
{
FILE* finput;
FILE* foutput;
short int counter;
char* output_filename;
char* finalstring;
for(counter=1; counter<n; counter++)
{
finput=fopen(arguments[counter], "r");
if (finput==NULL)
{
printf("Unable to open ");
puts(arguments[counter]);
perror("fopen");
break;
}
strcpy(output_filename, output_file_prefix);
strcat(output_filename, arguments[counter]);
if((foutput=fopen(output_filename, "w"))==NULL)
{
printf("There was an error while trying to open ");
puts(arguments[counter]);
printf(" .\n");
break;
}
while(!feof(finput))
{
finalstring=get_card(finput);
fputs(finalstring, foutput);
while(((fgetc(finput))!='\n')||feof(finput));
}
printf("Autocarding ");
puts(arguments[counter]);
printf(" was a success.\n");
fclose(foutput);
}
if(finput!=NULL)
{
fclose(finput);
free(finalstring);
}
return 0;
}
char* get_card(FILE* finput)
{
char* currentcard;
char* finalstring;
currentcard=(char*)malloc(sizeof(char)*150);
fgets(currentcard, 150, finput);
/* Allocates the exact amount of space needed for the final string*/
finalstring=(char*)malloc(sizeof(char)*(strlen(first_part_url)+strlen(second_part_url)+strlen(end_bracket)+strlen(currentcard)));
/* Get all the final forum link together*/
strcat(finalstring, first_part_url);
strcat(finalstring, currentcard);
strcat(finalstring, second_part_url);
strcat(finalstring, end_bracket);
free(currentcard);
return finalstring;
}
The error you are getting, "No such file or directory" indicates that the file name you're trying to open doesn't exist.
In this case, it's probably because the program's current working directory is not the same as the directory containing the executable file.
This
finput=fopen(arguments[counter], "r");
Will only fail if you do not supply correct filenames (e.g. if there are non-ASCII characters in the names or the names do not include the correct path, fopen() opens files in the current directory if no path is specified in the file name).
This
output_filename=(char*)malloc(sizeof(arguments[counter]));
most likely does not allocate enough space for a name because arguments[counter] is a pointer, and sizeof() of a pointer is not the same as strlen(that_same_pointer) + 1.
This
output_filename=output_file_prefix;
loses the just allocated memory because you are reassigning the pointer output_filename to point to some other place, output_file_prefix ("output_").
After the above this
strcat(output_filename, arguments[counter]);
is likely going to crash your program because this is going to attempt to overwrite a string literal ("output_"), doing which causes undefined behavior per the C standard.
You have to allocate enough cumulative space for the strings that you want to concatenate and you have to concatenate them in the allocated space.
To save you even more trouble, here's another problem:
finput=fopen(arguments[counter], "r");
...
while(!feof(finput))
feof() only works after at least one read from a file. This has been asked ans answered multiple times.
Try changing
for(counter=1; counter<n; ++n)
{
to
for(counter=1; counter<n; ++counter)
It appears the code loops infinitely, therefore it would exhaust the possible elements in your argument array causing a NULL pointer to be returned.

Resources