You are "Tap Dancing on a Landmine" and flirting with Undefined Behavior by concatenating text without checking if there are sufficient character available in filename
before calling strcat
. What if the user enters a 26-character filename
(or more)? (hint: undefined behavior)
This is compounded by the fact you are using gets
for input. gets
is so insecure and so prone to exploit by buffer overrun it has been completely removed in C11. If your professor is suggesting the use of gets
-- go get another professor. See: Why gets() is so dangerous it should never be used!
Instead use fgets
or POSIX getline
to read the filename
while protecting your arrays bounds with fgets
or dynamically allocating as much storage as needed for filename
in the case of getline
.
All line-oriented input functions like fgets
and getline
read and include the trailing '\n'
in the buffers they fill. You simply need to trim the '\n'
from the end of the string. You can do so by getting the length with strlen
and setting buffer[strlen(buffer) - 1] = '\0';
or by using the strcspn
function which provides a bit more functionality in one call.
Putting it altogether, you could do something similar to the following (that just outputs the fopen
call rather than actually opening the file):
#include <stdio.h>
#include <string.h>
#define MAXC 30 /* if you need a constant, #define one (or more) */
#define FEXT ".txt" /* (including string constants) */
int main (void) {
char filename[MAXC];
size_t available = MAXC - 1, /* chars available in filename */
length = 0,
extlen = strlen (FEXT);
FILE *fp;
fputs (" Enter the filename: ", stdout); /* no conversion needed */
if (!fgets (filename, MAXC, stdin)) {
fputs ("(user canceled input)\n", stderr);
return 1;
}
/* trim '\n' from end of filename saving length using strcspn() */
filename[(length = strcspn (filename, "\r\n"))] = 0;
if (available - length < extlen) {
fprintf (stderr, "error: insufficient space available for '%s'.\n",
FEXT);
return 1;
}
strcat (filename, FEXT);
/* just output what would be done */
printf ("fp = fopen (\"e:\\%s\",\"a+\");\n", filename);
}
Example Use/Output
The example simply prints what it would open (rather than actuall opening the file), e.g.
$ ./bin/strcatext
Enter the filename: my_file_to_open
fp = fopen ("e:\my_file_to_open.txt","a+");
And then check that your code will accept a 25-character filename plus 4-character extension, e.g.
$ ./bin/strcatext
Enter the filename: 1234567890123456789012345
fp = fopen ("e:\1234567890123456789012345.txt","a+");
And rejects a 26-character filename, e.g.
$ ./bin/strcatext
Enter the filename: 12345678901234567890123456
error: insufficient space available for '.txt'.
Look things over and let me know if you have further questions.