2012-05-04 2 views
8

나는 파일 이름이 내 파일 저장 얻기 위해이 코드를 작성 :Win32에서 GetSaveFileName을 사용하여 파일을 저장하는 방법은 무엇입니까?

#include "stdafx.h" 
#include <windows.h> 


int _tmain(int argc, _TCHAR* argv[]) 
{    
    OPENFILENAME ofn; 

    char szFileName[MAX_PATH] = ""; 

    ZeroMemory(&ofn, sizeof(ofn)); 

    ofn.lStructSize = sizeof(ofn); 
    ofn.hwndOwner = NULL; 
    ofn.lpstrFilter = (LPCWSTR)L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; 
    ofn.lpstrFile = (LPWSTR)szFileName; 
    ofn.nMaxFile = MAX_PATH; 
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 
    ofn.lpstrDefExt = (LPCWSTR)L"txt"; 

    GetSaveFileName(&ofn); 
    printf("the path is : %s\n", ofn.lpstrFile); 
    getchar(); 
    return 0; 
} 

을하지만 출력은 다음과 같습니다

the path is : H 

이유는 무엇입니까? 내가 뭔가 잘못하고 있는거야?

printf("the path is : %s\n", ofn.lpstrFile); 

는 printf와의 넓은 문자 버전을 사용해야합니다
나는 윈도우 7

+1

+1 완전한 예와 잘 공식화 된 질문. –

답변

8

이 줄에 비주얼 스튜디오 2008을 사용하고 있습니다.

wprintf(L"the path is : %s\n", ofn.lpstrFile); 
+1

+1 이번엔 ...이 시간. :) –

+1

'lpstrFile' 값을 포함한 나머지 코드는'_TCHAR'을 기반으로하므로'_tprintf'를 사용해야합니다 :'_tprintf (_T ("경로는 : % s \ n"), ofn .lpstrFile); –

+2

-1 버퍼가 너무 작기 때문에이 코드는 여전히 위험합니다. –

8

루트 문제는이 라인에 있습니다

char szFileName[MAX_PATH] = ""; 
... 
ofn.lpstrFile = (LPWSTR)szFileName; 
ofn.nMaxFile = MAX_PATH; 

이는 MAX_PATH 문자의 버퍼를 생성하지만 그것이 문자 폭 MAX_PATH 의 버퍼 년대 GetSaveFileName 기능을 알려줍니다. 다른 사람이 긴 경로 이름을 선택하면이 오류가 발생할 수 있습니다 (또는 자동으로 메모리를 트림합니다).

공짜는 캐스트입니다. 컴파일러 또는 라이브러리에 속지 마십시오. 그들은 그것을 좋아하지 않으며 결국에는 항상 복수 할 것입니다. 이 줄을 다음으로 바꾸십시오 :

이제 선택한 파일 이름이 넓은 문자 열로 반환됩니다. 당신이 8 비트 문자 대신 와이드 문자 문자열을해야하는 경우

wprintf(L"the path is : %s\n", ofn.lpstrFile); // though I'd use szFileName at this point 

것은, 당신이 WideCharToMultiByte는 사용할 수 있습니다 : 당신이 필요로하는 그 와이드 문자의 문자열을 인쇄 할 wprintf보다는 printf를 사용하는 토니 사자의 대답은 정확 . 하지만 일반적으로 와이드 캐릭터 API를 사용합니다.

정확히 무엇을하는지, 그리고 특별한 경우에 왜 필요한지 모르는 경우를 제외하고 절대 캐스트하지 마십시오.

-1

두 가지 모두 잘못되었으므로 간단한 C 포인터/스택 문제입니다.

이 배열과 포인터를 혼란
// WRONG: 
char szFileName[MAX_PATH] = ""; 

, 당신은 스택에 배열을 선언하지만, 다음 데이터 섹션에서 빈 문자열을 가리 키도록 메모리 주소를 변경합니다. 즉, 버퍼 오버플로입니다.

// RIGHT: 
char szFileName[MAX_PATH]; 
ZeroMemory(szFileName, MAX_PATH); 

이 코드는 스택에 문자 배열을 선언하고 모든 요소를 ​​널 종결 자로 초기화합니다.

희망 하시겠습니까?

+0

배열 초기화 자의 오른쪽에있는 리터럴 문자열은 특별한 의미가 있습니다.명령문'char szFileName [MAX_PATH] = ""'; 포인터를 만들지 * 않습니다 *. 'szFileName [0]을 '\ 0', 즉 널 종결 자로 초기화한다. –

관련 문제