这是一个在Windows中打开文件对话框并返回文件名为
的字符串的函数#include <windows.h>
#include <commdlg.h>
#include <string.h>
char* openFileDlg(char FileTypes[]);
char* openFileDlg(char FileTypes[]){
OPENFILENAME ofn;
char szFile[260];
HWND hwnd;
HANDLE hf;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
strcpy(ofn.lpstrFilter,FileTypes);
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if(GetOpenFileNameA(&ofn)){
char *toReturn;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
}
else{
return NULL;
}
}
当我调用此函数并打开文件时,进程结束并返回值3(这意味着存在错误)。如何执行此函数以返回包含所选文件路径的字符串?
编辑:我已将代码更改为此代码,但仍然无效:
#include <windows.h>
#include <commdlg.h>
#include <string.h>
void openFileDlg(char *toReturn[],char FileTypes[]);
void openFileDlg(char *toReturn[],char FileTypes[]){
OPENFILENAME ofn;
/*
Code for the settings of the GetOpenFileNameA, irrelevant in this question.
If you really need to know what's here, look at the code above.
*/
if(GetOpenFileNameA(&ofn)){
strcpy(*toReturn,ofn.lpstrFile);
}
else{
sprintf(*toReturn,"");
}
}
我还应该说,如果我按下打开文件对话框中的取消按钮而不是选择文件,它可以正常工作。经过一些测试后,我发现导致错误的是strcpy(*toReturn,ofn.lpstrFile);
行。
答案 0 :(得分:5)
指针变量toReturn
并不指向任何地方,在没有初始化的情况下以任何方式使用它(即使其指向某个有效且足够大的地方)将导致未定义的行为
你真的有两个解决方案:
动态分配内存并返回指向该内存的指针。这当然要求调用者在完成操作后释放内存。
让函数接受另外两个参数:指向缓冲区的指针和缓冲区的长度。然后将字符串复制到该缓冲区中,并返回一个布尔值&#34; true&#34;或&#34;假&#34;成功/失败状态。
我推荐第二号解决方案。
在不相关的说明中,您无需使用昂贵的sprintf
函数,只需strcpy
(或strncpy
,如果您使用第二种解决方案)会做的。
在这两种情况下,您还必须记住C中的字符串的实际长度比例如1。 strlen
报告终止'\0'
字符。
答案 1 :(得分:3)
通常,如果要在C中返回字符串,我将使用以下方法之一:
1)传入字符串缓冲区以便写入:
int openFileDlg(char FileTypes[], char* toReturn, int bufLen) {
/* ... */
snprintf(toReturn, bufLen, /* what you want to print */);
return ERROR; // status-code
}
/* ... */
char errorBuf[80];
int result;
result = openFileDlg(..., errorBuf, sizeof(errorBuf));
2)分配内存,希望调用者释放它:
char* openFileDlg(char FileTypes[]) {
/* ... */
char *toReturn = malloc(/* big enough */);
sprintf(toReturn, /* what you want to print */);
return toReturn;
}
/* ... */
char* error = openFileDlg(...);
if (error) {
/* ... */
free(error);
}
个人而言,我更喜欢(1)因为它更安全。选项(2)对函数的API更好,但如果忘记释放返回的缓冲区,则存在内存泄漏的风险。在一个更大的项目中(特别是有多人参与其中),这是一个非常现实的风险。
(我意识到这和Joachim的答案几乎一样,但是当我写作时,他的表现很快)
答案 2 :(得分:1)
您没有为返回值分配内存。如果你知道ofn.lpstrFile
的长度,你可以这样做:
char *toReturn = malloc( (sizeOfLpstrFile + 1) * sizeof(char)) ;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
我仍然认为这是一个坏主意,因为调用函数必须释放从界面中看不明显的内存。