C语言程序中fopen写入文件失败,请求问题排查与解决
问题排查与修复:密码验证后文件创建写入失败
你遇到的文件创建写入功能异常,主要是代码里的几个细节问题导致的,我帮你逐一拆解:
1. CreateFile 打开的文件句柄未关闭,导致 fopen 无法访问文件
你用 CreateFileA 创建文件后,没有调用 CloseHandle(h) 关闭这个句柄。由于 CreateFile 默认的共享模式是 NULL(不允许其他句柄访问该文件),后续调用 fopen 会因为文件已被当前进程占用而失败,fp 会变成 NULL,这时执行 fprintf 就会触发未定义行为(程序崩溃或无写入效果)。
2. 局部变量重定义覆盖了文件指针
在 if (fp == NULL) 的代码块里,你重新定义了 FILE *fp;,这会覆盖外面声明的同名指针变量。即使 fopen 成功,后续操作的也是这个局部变量,逻辑上会出现混乱。
3. 缺少关键的错误检查
你没有检查 CreateFileA 和 fopen 的返回值是否成功:
- 如果目标目录(比如
C:\\Users\\shai\\Desktop\\Create\\)不存在,CreateFileA会返回INVALID_HANDLE_VALUE,无法创建文件; - 如果
fopen失败(比如文件被占用),直接调用fprintf会出问题。
4. 密码验证的小问题(额外提示)
你调用 strcmp 时写了 strcmp(SecretPass, &Userinput),Userinput 是数组名,本身就是指向数组首元素的指针,不需要加 &,改成 strcmp(SecretPass, Userinput) 才对。另外,fgets 会读取输入的换行符(如果输入长度小于缓冲区大小),可能导致密码匹配失败——可以用 strcspn 去掉 Userinput 里的换行符。
修复后的完整代码
#include <stdio.h> #include <Windows.h> #include <string.h> #pragma warning(disable:4996) int main() { char SecretPass[7] = "Az1236"; char Userinput[7]; int ResultCMP; printf_s("Insert Pass:"); fgets(Userinput, 7, stdin); // 去掉fgets读入的换行符,避免密码匹配失败 Userinput[strcspn(Userinput, "\n")] = '\0'; // 修正strcmp的参数,不需要&Userinput ResultCMP = strcmp(SecretPass, Userinput); if (ResultCMP == 0) { int msg = MessageBox(NULL, "You Got In", "Wow", MB_ICONEXCLAMATION); if (msg == IDOK) { printf_s("Great! \n"); char *szFileName = "C:\\Users\\shai\\Desktop\\Create\\kilroy.txt"; // 先检查文件是否存在 FILE *fp = fopen(szFileName, "r"); if (fp == NULL) { // 先确保目录存在(如果目录不存在,CreateFile会失败) char dirPath[MAX_PATH]; strcpy(dirPath, szFileName); // 去掉文件名,只保留目录 char *lastSlash = strrchr(dirPath, '\\'); if (lastSlash != NULL) { *lastSlash = '\0'; // 创建目录,已存在的话不会报错 CreateDirectoryA(dirPath, NULL); } // 直接用fopen创建写入(更简洁的C标准库方案) fp = fopen(szFileName, "w+"); if (fp != NULL) { fprintf(fp, "testtest"); puts("Done"); fclose(fp); } else { printf("Failed to open file for writing!\n"); } } else { printf("File exists!\n"); fclose(fp); // 记得关闭已打开的文件 } } else { printf_s("Wrong pass!"); getchar(); } } else { // 新增密码错误的提示,否则用户看不到反馈 printf_s("Wrong password!\n"); getchar(); } getchar(); return 0; }
额外说明
- 我用了更简洁的
fopen直接创建文件的方案,如果你一定要保留CreateFile的逻辑,记得在创建后立即调用CloseHandle(h)释放句柄,再用fopen打开; - 添加了创建目录的逻辑,因为如果
Create文件夹不存在,任何文件创建操作都会失败; - 完善了错误提示,方便你快速定位问题;
- 修复了密码验证里的换行符问题,避免用户输入正确密码但匹配失败的情况。
内容的提问来源于stack exchange,提问作者Xozu
相关产品推荐
相关产品推荐

