Open and edit external file which has variable name in C - c

Quick question, since I only managed to find answers on the googlemobil regarding C++: Is there any way to open and edit files in C, where the file has a variable name?
Let's make it a bit clearer: I have a prompt, which checks if the user gives a filename or not. If no filename has been entered, the program automatically opens a client.conf file I created in the same directory; now this was the easy part of the if-else statement.
However, IF a name has been given, how do I make my program create a file givenInput.conf in the same directory, and send data to it? I suppose the r/w interaction would be the same as with the first case of the if-statement, using fopen(), however fopen() uses as first parameter const char *restrict filename, and I am trying to make something for chars that are NOT constants...
In C++ there is a way to bypass this by creating a separate (empty) array, pasting the input and then just adding the string suffix to it; also, it uses a C++ specific function (whom name I forgot, sorry ^^) to parse the variable filename....
Any ideas how to manage this in regular, plain good'ol C? I'm new to the C programming language, please be gentle for a newbie ;)

You can send in a non-constant string where a constant string is expected and there is no need for a cast. So just open the file using a string you have constructed in whatever manner suits you best:
char filename[1024];
getFilenameSomehow(filename, 1024);
fopen(filename, "w");
You may not, however, send in a constant string where a non-constant string is expected.
const char *myConst = "May not be changed";
memset(myConst, 'X', strlen(myConst)); // Error! You may not modify a const string.

You can cast your variable to const char *
char file_var_name[100];
scanf("%99s", file_var_name);
fopen((const char *) file_var_name, "r");

You can read the input using command line arguments to main() i.e. using argc and argv . Read this for more details
Use strcat (present in string.h) to concatenate ".conf" at the end of filename.
Read here about strcat.

Related

Write an entire program to a file in C

I'm quite new to C programming, but I'm starting to get the hang of it.
For a school assignment, I have written a code in C to play Blackjack.
One of the requirements for the assignment, is that is has to have an option that saves the entire output (everything that's shown in cmd when the program is build and run).
I can't find how to do this anywhere.
Is there a way to write the entire output into a file?
Thanks in advance!
There are 3 ways to achieve what you want.
Use a file. This is the way I recommend. You will need the functions fopen to open a file and enter link description here to print the data in the file. I suggest you read the documentation of the functions in the links and look at the examples.
Redirect stdout to a file using freopen. This basically puts everything that you see now in the console in a file, by adding just one line.
Redirect the output of the program in a file. This is more a shell thing than a C programming technique, but I think it is worth mentioning. In an *NIX environment, the command ./a.out > file.txt will redirect the output of a.out to a file called file.txt in a similar manner freopen does.
You can pipe the stdout and stderr to a file when you build and run. For example, on Linux using the bash shell you can do try this (where the "build_script" is what you use to build and the "a.exe" is the program name):
$ ./build_script >& build_out.txt
$ ./a.exe >& run_out.txt &
The ">&" tells bash to pipe both stdout and stderr to the file. The final "&" in the second line tells bash to run the program in the background. It's hard to tell if this answer will suit your purposes since it's not clear exactly how the game is played from what you have posted. E.g., if you need to use stdin/stdout to play the game then maybe piping the "a.exe" stdout to a file might not work...
I'm assuming simple output redirection is not an option:
$ app > file.txt
Probably, you are using printf to print data to console. Instead of printf, you can use fprintf. fprintf can write data to an arbitrary file, just like printf does to the standard output (which is also a file), in this case the console.
You must first open the file where you will write the output. The command fopen will do this for you:
// this will open or create the file as text to write data.
FILE *f = fopen("my-file.txt", "w");
With the f variable (which you should check for NULL in case of error), you can pass it to fprintf to write data:
fprintf(f, "my super string: %s", string);
Note that despite the first argument being a FILE*, everything else behaves like printf. Actually you can think of printf as a wrapper where the first argument of the fprintf is always stdout.
Do not forget to close your file after you write data!
fclose(f);
This can be done once, after all the data is written to file.
Check the man pages for more info about these commands.
There are more complex (not that much actually) ways of accomplishing this, like using freopen, but I'm leaving this out of the answer. If you need more, update your answer.
EDIT
In your comment, you said you must save or not the output to a file at the end of the program. Well, the file management stuff above you still be usefull. The changes are the following:
You must store the output somewhere in order to decide whether to write to a file or not at the end of the program. Probably you are doing some data formatting with printf. You will have to change your calls from printf to snprintf. This command will write your data to a string, just as printf does prior to output it to the stdout, but it will skip the print-to-output- part.
Then, store the buffer at a list of strings and at the end of the program you write this list to the file or not.
This has some complications: you need a list of strings (a dynamically allocated array of arrays will be enough, actually); how big must your buffer be?
snprintf will return the size required to print the passed data to the buffer, no matter if the buffer is larger or smaller then the given one. But, if it is smaller, you will have to increase its size (reallocating it) and call again snprintf:
char *buffer = malloc(sizeof(char) * 41); // 40 chars + \0!
int size;
if ( size = snprintf(buffer, 41, "your format here", args) > 40 ) {
buffer = realloc(buffer, sizeof(char) * (size + 1));
snprintf(buffer, size + 1, "your format here", args);
}
// now your buffer have the correct data!
// print it to stdout!
puts(buffer);
// store it at the string list.
// execise!
Is left as an exercise wrapping this piece of code in a command to avoid repeat it everywhere you print anything. Also, it is an exercise to create the list of strings.
When you decide to write data to file, instead of use fprintf you can use fputs, as data is already formatted.
I don't know if there is an easier way. I think not.

how to check if there's a string in the command line

I have this command line:> write_strings "Hello World!" a.txt b.txt dir/a.txt.
all the elements (command, string, file names) go into an array of char pointer. how can I take an element and check if it's a string or a file name?
I don't mean the exact code lines, buts just need the idea. the program should return an error if there's no string.
You can use an API such as stat or access to check if the file pointed to by a path exists. There is no fundamental distinction between filepaths and regular strings when they are passed to your process.
If you're using the standard main(int argc, char *argv[]) convention, you can loop through argv, checking each one to see if it's a file via one of the previously-mentioned system calls.
Every string that can be passed on a command line is a potential pathname, since the only restriction in both cases is that there can't be any NULs.
A program with a command line syntax in which a specific argument might or might not be used as a pathname (depending on some vague definition of "filename-ish strings" or even a file existence test) is a bad design. Each argument should have a meaning defined by its order in the argument list, or by being associated with an option like -m msg or -o outputfile.
A well-behaved unix program will let the user create a file called Hello world! if he wants.
not regarding how meaningful the program might or might not be - you can compare the single characters of your char *argv[] by looping through them via argv[i][j]. If every string includes a ".txt" you do not have a string, which is not a filename in your context

Reading and writing a file with special characters in c

Using the C language, I am trying to manipulate some files generated by openssl and containing a lot of (very) special characters. But the end of file seems to be prematurely detected.
For example see an extract of my program, that is supposed to copy a file to another :
(for simplicity reasons I do not show the test of the opening of the file but I do that in my program)
char msgcrypt[FFILE];
FILE* fMsg = fopen(f4Path,"r");
while(fgets(tmp,FFILE,fMsg) != NULL) strcat(msgcrypt,tmp);
fclose(fMsg);
FILE* fMsg2 = fopen(f5Path,"w");
fprintf(fMsg2,"%s",msgcrypt);
fclose(fMsg2);
here is the content of the file located at f4Path :
Salted__X¢~xÁïÈú™xe^„fl¯�˜<åD
now the content of the file located at f5Path :
Salted__X¢~xÁïÈú™xe^„fl¯
Notice that 4 characters are missing.
Do someone have an idea?
But the end of file seems to be prematurely detected
Sounds familiar.
Use fopen(f4Path, "rb") when opening the file. This has real significance on Windows.
Don't use string functions (fprintf, strcat, fgets etc) they will choke on NUL characters. Use fread and fwrite instead.
strcat tries and copy a nul-terminated char *. Which means, if it encounters a 0, which it probably has done here, it will stop copying.
You'd better use open read, memcpy and write.
That character it stops on I copied into a hex editor, and it ends up being EF BF BD, a BOM if I'm not mistaken. As a result, reading the file as a text file fails. I don't see any NULL characters (unless copying and pasting got rid of them).
The answer (as has already been discussed) is to not treat it as a text file, and avoiding the str functions won't do any harm either.
The first thing I'd do though is add a check for how may characters are read, that way you'll know where the data is being truncated. Right now it could be in any of: read, strcat, write.

How to get a file's name from FILE* struct in C

Is it possible to retrieve a file's name in C? If a file is created like the following:
FILE *f = fopen ("foo.txt", "r");
And the "foo.txt" comes from a variable out of scope. Is there a way to retrieve it from the FILE struct?
You can't in fact retrieve the file names from your FILE objects.
However, if the name being passed to fopen is important to you, and that variable is out of scope for whatever reason, you could always wrap a FILE* in a struct, ie.
struct file_with_name {
FILE *f;
char *name; /* OR char name[MAX] */
}
At least that's what I'd do but it depends on what you're actually trying to do.
Unfortunately, on many systems a filename is just a pointer to an inode. And if those filesystems support hard links, that means that there are multiple filenames per real file. Also, you can open a file and then remove the file in which case there wouldn't even be a filename, just a descriptor. For these reasons, you can't go from a file descriptor to a file name.
Its not possible to get the filename out of a FILE handle. You should store the filename yourself if you later need to use it.
Since FILE objects may be created from things that have no name associated with them (in particular, from a raw file descriptor with fdopen()), they do not always have a name to get.
In general, it's not possible. The closest you can try, on Linux, is:
char buf[PATH_MAX];
snprintf(buf, sizeof buf, "/proc/self/fd/%d", fileno(f));
readlink(buf, buf, sizeof buf);
Reusing buf like that is horribly ugly, but as far as I can tell, it's legal and not undefined behavior per POSIX.

How To read/write C array stored in text file created through bin2C utility

I am creating a application, input to which is a C file having an array ( which is created with bin2C.exe ) , the code segment of the C file is:-
unsigned int MyArray[] = { 0x00000001,0x00000002,0x00000005 ...};
now I need to read this array as a text file and story its value in an int array. Then I need to modify that array and put it back to text file so that the final output would look like:-
unsigned int MyArray[] = { 0x39481212,0x33943121,0x3941212 ...};
Please let me know how can I do this in C/VisualC++ as my application is in VC++ with MFC?
Regards,
Vikas
input
open the file (fopen) in text mode and read the lines (fgets and sscanf)
store array
you cannot have an array with unspecified size. You must either use a size limit and leave some elements unused, or use malloc and friends and manage storage for the array manually
modify
use +, -, * and other operators along with sqrt, abs, sin and other functions available in the Standard Library to massage the data (you can create some functions of your own too)
put it back
It's better to write to a new file and if everything went ok, delete the old file and rename the new one ... so open the new file (fopen with "w" for mode parameter) at the beginning when opening the input; if the input is not the array line write (fputs) it back directly, otherwise write the 'massaged' line; read and write all the other lines.
(C++?) with MFC
The above is for C. It might work for C++ with or without MFC
Regards
Have fun!
I think the best way was to read and use fprintf/sprintf functions to get and put the data as int from file.

Resources