Creating a new file every time a programme is run in c - c

I'm creating a programme that writes the results of a questionnaire to a .txt file and wondered if there was any way to create a new file with a new name every time the programme was run?
FILE *fp;
fp = fopen("results.txt","w");
How can the file reults.txt be saved under a different name each time?
so ive done the below which lets a user save the name of their results.
int main(int argc, char *argv[])
{
printf("Please enter a filename to save your results to\n");
char c;
FILE *fp;
if (argc >= 2){
fp = fopen(argv[1], "w");}
while ((c = getchar()) != EOF)
{
putc(c, fp);
}
but i get a core fault.

Use the standard C function meant to be used for this very purpose.
7.21.4.4 The tmpnam function
#include <stdio.h>
char *tmpnam(char *s);
The tmpnam function generates a string that is a valid file name and that is not the same
as the name of an existing file.
Notably, this family of functions have some security concerns addressed by CERT-C here. C11 provides safer versions called tmpfile_s and tmpnam_s, as part of the optional bounds-checking interface. But if your beginner-lever questionnaire program does not need commercial production quality protection against hackers, this shouldn't be a concern.

There is many ways to do this.
You can take the file name as an argument.
You can get the process id (with getpid()), and add it to the end of the name.
You can add an number at the end of the file and increment it each time the program is run (by looking into the directory)
...
Edit:
Answer to your first edit
You only open the file if argv < 2, so what will append if argv >= 2 ? What do you think will append when you do putc(c, fp); ?
If you want your program only run if there is enough arguments, check it at the beging, and exit if it's not ok, with a message to tell why it's not ok. :)
And, always check the return of functions like fopen, malloc,... To be sure everything is ok.

You can generate random number by using rand() function in C and append it to the filename at the end ! Or you can append currentmillis to your file name to get unique name every time ! Of course there are many ways of doing it !
Or char *tmpnam(char *str); can also be used!

Related

Making a C program take in a plain text file at execution time

I have an assignment that is requiring that my program takes in a plain text file at execution time and manipulates it to keep track of a vending machine inventory.
The file has to contain 12 rows with the details of each item in the machine that is used to populate data structs.
Would passing the file to the program require command line arguments or is it something different?
I am using a GCC compiler.
I have tried adding the address of the file to the execution command but nothing came of that.
I've assumed you need the file path to be accepted as an input to the program.
If so then it depends on how you would like to pass this information to the program, but I'm not convinced that passing command line arguments could be considered an runtime input from user. However you could pass a path to the file as an command line argument, and access it using argc and argv arguments of the main function :
int main(int argc, char *argv[])
{
//argv[0] is always name of the program
//argv[1] is the first command line argument
//and so on up to argc-1 (argv[argc-1] is the last argument)
//so, in the simplest form do:
if (argc < 2) return -1; // check if any argument was passed, as pm100 said in comments to this answer.
FILE *f = fopen(argv[1], "rb"); // change "rb" to mode you need
if (f==NULL) return -1; // file could not be opened
// process the file as you need from here
...
}
The alternative approach, reading user input at runtime using fgets could be found here. Then pass the string you got from user as an first argument to fopen.
You can, of course, mix these two approaches (checking if any command-line args were passed, and if not ask for user input) but this probably would be an overkill for a homework.
If you just need to load file from a fixed place in your filesystem, and filename won't change then simply change argv from my example to your filename or path:
int main()
{
const char filename[] = "your_file_name_here";
FILE *f = fopen(filename, "rb"); // change "rb" to mode you need
if (f==NULL) return -1; // file could not be opened
// process the file as you need from here
...
}

'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.

displaying contents of a file on monitor in C

I'm trying to recreate a program I saw in class.
The teacher made a file with 10 lines, he showed us that the file was indeed created, and then he displayed its contents.
My code doesn't work for some reason, it just prints what looks like a"=" a million times and then exits.
My code:
void main()
{
FILE* f1;
char c;
int i;
f1=fopen("Essay 4.txt","w");
for(i=0;i<10;i++)
fprintf(f1," This essay deserves a 100!\n");
do
{
c=getc(f1);
putchar(c);
}while(c!=EOF);
}
What is the problem? as far as I can see I did exactly what was in the example given.
The flow is as such:
You create a file (reset it to an empty file if it exists). That's what the "w" mode does.
Then you write stuff. Note that the file position is always considered to be at the very end, as writing moves the file position.
Now you try to read from the end. The very first thing you read would be an EOF already. Indeed, when I try your program on my Mac, I just get a single strange character just as one would expect from the fact that you're using a do { } while. I suggest you instead do something like: for (c = getc(f1); c != EOF; c = getc(f1)) { putchar(c) } or similar loop.
But also, your reading should fail anyway because the file mode is "w" (write only) instead of "w+".
So you need to do two things:
Use file mode "w+".
Reset the file position to the beginning of the file after writing to it: fseek(f1, 0, SEEK_SET);.

Reading from files passed as command line arguements

I am trying to parse a given textfile, but so far, my program does not seem to be reading properly.
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fr; //file pointer
int buildingFloors = 1;
printf("sanity check\n");
fr = fopen (argv[0], "r");
fscanf(fr, "%d", &buildingFloors );
printf("%d\n", buildingFloors);
fclose(fr);
return 0;
}
I compile the program and run it on my redhat linux machine with the following command:
./sjf file.text
file.text is a text document with a "4" as the first character. So I would expect my output to be
sanity check
4
However, when I run my program I instead get
sanity check
1
Which implies that fscanf didn't properly read in the first character -- 4. Do I have some syntax error that's preventing the expected code functionality? Am I supposed to scanf for a character, and then convert that to an int somehow?
argv[0] is the name of the program (./sjf in your case), so you're trying to read in your own program's executable. Use argv[1] instead to get the first real program argument.
One thing which immediatly comes to mind is that the program args include the executable name as the first element
argv[0] is "sjf"
argv[1] is "file.text"
so you should be using
fr = fopen (argv[1], "r");
Remember when debugging to always try and narrow the problem down, if you know the location of the error the cause often becomes obvious or at least investigatable.
In this case you should check argc >= 2, print out argv[1] to ensure you are trying to open the right file, then also check that the file was opened successfully.
Finally check the fscanf error codes to see that fscanf was able to read the number.
Your code looks clear and straight-forward, but there is one important thing missing: error handling.
What happens if the file you want to open does not exist? fopen returns NULL in that case.
What happens if the file does not start with a number? fscanf returns the number of fields that have been successfully read, so you should check that the return value is at least 1.
You need to somehow handle these cases, probably by printing some error message and exiting the program. When you do that, be sure to include the relevant information in the error messages. Then you will find the bug that the other answers have already mentioned.

Opening a file in C through a proccess

I am trying to create a a program that does the following actions:
Open a file and read one line.
Open another file and read another line.
Compare the two lines and print a message.
This is my code:
#include <stdio.h>
#include <string.h>
int findWord(char sizeLineInput2[512]);
int main()
{
FILE*cfPtr2,*cfPtr1;
int i;
char sizeLineInput1[512],sizeLineInput2[512];
cfPtr2=fopen("mike2.txt","r");
// I open the first file
while (fgets(sizeLineInput2, 512, cfPtr2)!=NULL)
// I read from the first 1 file one line
{
if (sizeLineInput2[strlen(sizeLineInput2)-1]=='\n')
sizeLineInput2[strlen(sizeLineInput2)-1]='\0';
printf("%s \n",sizeLineInput2);
i=findWord(sizeLineInput2);
//I call the procedure that compares the two lines
}
getchar();
return 0;
}
int findWord(char sizeLineInput2[512])
{
int x;
char sizeLineInput1[512];
File *cfPtr1;
cfPtr1=fopen("mike1.txt","r");
// here I open the second file
while (fgets(sizeLineInput1, 512,cfPtr1)!=NULL)
{
if (sizeLineInput1[strlen(sizeLineInput1)-1]=='\n')
sizeLineInput1[strlen(sizeLineInput1)-1]='\0';
if (strcmp(sizeLineInput1,sizeLineInput2)==0)
//Here, I compare the two lines
printf("the words %s and %s are equal!\n",sizeLineInput1,sizeLineInput2);
else
printf("the words %s and %s are not equal!\n",sizeLineInput1,sizeLineInput2);
}
fclose(cfPtr1);
return 0;
}
It seems to have some problem with file pointers handling. Could someone check it and tell me what corrections I have to do?
Deconstruction and Reconstruction
The current code structure is, to be polite about it, cock-eyed.
You should open the files in the same function - probably main(). There should be two parallel blocks of code. In fact, ideally, you'd do your opening and error handling in a function so that main() simply contains:
FILE *cfPtr1 = file_open("mike1.txt");
FILE *cfPtr2 = file_open("mike2.txt");
If control returns to main(), the files are open, ready for use.
You then need to read a line from each file - in main() again. If either file does not contain a line, then you can bail out with an appropriate error:
if (fgets(buffer1, sizeof(buffer1), cfPtr1) == 0)
...error: failed to read file1...
if (fgets(buffer2, sizeof(buffer2), cfPtr2) == 0)
...error: failed to read file2...
Then you call you comparison code with the two lines:
findWord(buffer1, buffer2);
You need to carefully segregate the I/O operations from the actual processing of data; if you interleave them as in your first attempt, it makes everything very messy. I/O tends to be messy, simply because you have error conditions to deal with - that's why I shunted the open operation into a separate function (doubly so since you need to do it twice).
You could decide to wrap the fgets() call and error handling up in a function, too:
const char *file1 = "mike1.txt";
const char *file2 = "mike2.txt";
read_line(cfPtr1, file1, buffer1, sizeof(buffer1));
read_line(cfPtr2, file2, buffer2, sizeof(buffer2));
That function can trim the newline off the end of the string and deal with anything else that you want it to do - and report an accurate error, including the file name, if anything goes wrong. Clearly, with the variables 'file1' and 'file2' on hand, you'd use those instead of literal strings in the file_open() calls. Note, too, that making them into variables means it is trivial to take the file names from the command line; you simply set 'file1' and 'file2' to point to the argument list instead of the hard-wired defaults. (I actually wrote: const char file1[] = "mike1.txt"; briefly - but then realized that if you handle the file names via the command line, then you need pointers, not arrays.)
Also, if you open a file, you should close the file too. Granted, if your program exits, the o/s cleans up behind you, but it is a good discipline to get into. One reason is that not every program exits (think of the daemons running services on your computer). Another is that you quite often use a resource (file, in the current discussion) briefly and do not need it again. You should not hold resources in your program for longer than you need them.
Philosophy
Polya, in his 1957 book "How To Solve It", has a dictum:
Try to treat symmetrically what is symmetrical, and do not destroy wantonly any natural symmetry.
That is as valid advice in programming as it is in mathematics. And in their classic 1978 book 'The Elements of Programming Style', Kernighan and Plauger make the telling statements:
[The] subroutine call permits us to summarize the irregularities in the argument list [...]
The subroutine itself summarizes the regularities of the code.
In more modern books such as 'The Pragmatic Programmer' by Hunt & Thomas (1999), the dictum is translated into a snappy TLA:
DRY - Don't Repeat Yourself.
If you find your code doing the 'same' lines of code repeated several times, write a subroutine to do it once and call the subroutine several times.
That is what my suggested rewrite is aiming at.
In both main() and findWord() you should not use strlen(sizeLineInputX) right after reading the file with fgets() - there may be no '\0' in sizeLineInput2 and you will have strlen() read beyond the 512 bytes you have.
Instead of using fgets use fgetc to read char by char and check for a newline character (and for EOF too).
UPD to your UPD: you compare each line of mike2.txt with each line of mike1.txt - i guess that's not what you want. Open both files one outside while loop in main(), use one loop for both files and check for newline and EOF on both of them in that loop.

Resources