这是我的代码:
char filename[30];
FILE *fp;
printf(" Enter the filename: ");
gets(filename);
strcat(filename,".txt");
fp=fopen("e:\\filename","a+");
所以我的问题是我希望用户指定一个文件名,然后打开该文件并在上面写。但是每次我运行这段代码时,它都会打开一个名为:filename的文件,而不是打开字符串filename [30]上存在的值。
答案 0 :(得分:2)
您正在“在地雷上跳舞” ,并通过串联文本而不调用filename
中是否有足够的字符来调情未定义行为 strcat
。如果用户输入26个字符的filename
(或更多)怎么办? (提示:未定义的行为)
由于您正在使用gets
作为输入,因此情况变得更加复杂。 gets
如此不安全,容易被缓冲区溢出利用,因此已在C11中被完全删除。如果您的教授建议使用gets
,请找另一位教授。参见:Why gets() is so dangerous it should never be used!
相反,使用fgets
或POSIX getline
来读取filename
,同时用fgets
保护数组边界或动态分配filename
所需的存储空间对于getline
。
所有面向行的输入函数,例如fgets
和getline
读取并 include 尾随{{1 }}在它们填充的缓冲区中。您只需要从字符串末尾修剪'\n'
。您可以通过使用'\n'
获得长度并设置strlen
或使用buffer[strlen(buffer) - 1] = '\0';
函数来实现此目的,该函数在一个调用中提供更多功能。
将其完全放在一起,您可以执行以下操作(仅输出strcspn
而不是实际打开文件):
fopen
使用/输出示例
该示例仅显示将打开的内容(而不是实际打开文件),例如
#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);
}
然后检查您的代码是否接受25个字符的文件名和4个字符的扩展名,例如
$ ./bin/strcatext
Enter the filename: my_file_to_open
fp = fopen ("e:\my_file_to_open.txt","a+");
并拒绝26个字符的文件名,例如
$ ./bin/strcatext
Enter the filename: 1234567890123456789012345
fp = fopen ("e:\1234567890123456789012345.txt","a+");
仔细检查一下,如果还有其他问题,请告诉我。