MFC中关于CString和char*之间的问题,为什么都是不成功?
CStringstrfilename;char*path;CFileDialogfiledlg(1,0,0,4|2,_T("mp3音乐文件|*.mp3||"),0,0,1...
CString strfilename;
char* path;
CFileDialog filedlg(1,0, 0, 4|2,_T("mp3音乐文件|*.mp3||"),0,0, 1);
if(filedlg.DoModal() == IDOK)
{
strfilename = filedlg.GetPathName();
path = (LPSTR)(LPCTSTR)strfilename;
FILE* fp = fopen(path,"r");
CString tmp;
tmp.Format(L"文件为[%s],fp的值为%d",path,fp);
AfxMessageBox(tmp,MB_OK);
}
从输出中可以看出CString和char*之间好像成功转换,但为什么fp始终为0,也就是说文件没有成功打开,但文件存在的呀,也没有被使用。。。请指教下。。想不通呀 展开
char* path;
CFileDialog filedlg(1,0, 0, 4|2,_T("mp3音乐文件|*.mp3||"),0,0, 1);
if(filedlg.DoModal() == IDOK)
{
strfilename = filedlg.GetPathName();
path = (LPSTR)(LPCTSTR)strfilename;
FILE* fp = fopen(path,"r");
CString tmp;
tmp.Format(L"文件为[%s],fp的值为%d",path,fp);
AfxMessageBox(tmp,MB_OK);
}
从输出中可以看出CString和char*之间好像成功转换,但为什么fp始终为0,也就是说文件没有成功打开,但文件存在的呀,也没有被使用。。。请指教下。。想不通呀 展开
7个回答
展开全部
基本如魔高丈所言。
但在使用C语言的文件关联函数时,不能硬编码为_wfopen,否则工程项目是“非UNICODE字符集”的话,又会出错。
VC中的_t函数(...)和_T("XXX")、TEXT("XXX")等,其中心思想都是无论工程是何种类型的字符集,都不需要更改源代码,就能编译通过。楼主既然开始就使用了_T("..."),后面的C文件操作函数也可以使用_t函数。对此VC不仅将尽可能多的API定义成了_t函数,也将这一思想尽可能的覆盖到了C函数。因此魔高丈if语句中的代码可以改下:
if(filedlg.DoModal() == IDOK)
{
strfilename = filedlg.GetPathName();
FILE* fp = _tfopen((LPCTSTR)strfilename,_T("r"));
CString tmp;
tmp.Format(_T("文件为[%s],fp的值为%d"),strfilename,fp);
AfxMessageBox(tmp,MB_OK);
}
_wfopen(..., _T("r"));
函数用_wfopen会使后面的_T("r")参数面临非常尴尬的局面。
----------------------
CString一些用法:
1)CString重载了类型操作符LPCTSTR:
CString str(_T("123"));
LPCTSTR pStr = (LPCTSTR)str;
以上第二行代码意义为,str调用了operator LPCTSTR()函数,返回了一个指向缓冲区的指针,该指针是LPCTSTR。
2)对于LPTSTR的指针类型,CString没有简单重载操作符,必须通过调用GetBuffer(int nBytes)获取到缓冲区的指针,类型为LPTSTR。
用完后,应该调用ReleaseBuffer。
GetBuffer时CString会锁定内存块,因此用完应该调用ReleaseBuffer释放,很多人都不知道GetBuffer后要释放,其实大多数情况下可能会正常工作,因为一般析构函数会解决该问题,但在一些情况下会出问题,如果不知道CString的机理,根本无法进行调试纠错。
3)CString对API函数的支持:
如新建控制台工程,勾选“MFC”选项,源代码如下:
// StringDemo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "StringDemo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
CStringA strTextA("中国");
CStringW strTextW(L"");
DWORD dwBufSize = (strTextA.GetLength() + 1) * sizeof(WCHAR);
nRetCode = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)strTextA, strTextA.GetLength() + 1, strTextW.GetBuffer(dwBufSize), dwBufSize / sizeof(WCHAR));
strTextW.ReleaseBuffer();
if (!nRetCode) {
strTextW.Format(L"调用MultiByteToWideChar错误,错误码#%u", GetLastError());
}
//项目必须使用UNICODE字符集,否则AfxMessageBox不支持LPCWSTR类型参数
AfxMessageBox((LPCWSTR)strTextW);
}
//该示例反应了CString能很好地支持WIN32 API函数的调用。
return nRetCode;
}
但在使用C语言的文件关联函数时,不能硬编码为_wfopen,否则工程项目是“非UNICODE字符集”的话,又会出错。
VC中的_t函数(...)和_T("XXX")、TEXT("XXX")等,其中心思想都是无论工程是何种类型的字符集,都不需要更改源代码,就能编译通过。楼主既然开始就使用了_T("..."),后面的C文件操作函数也可以使用_t函数。对此VC不仅将尽可能多的API定义成了_t函数,也将这一思想尽可能的覆盖到了C函数。因此魔高丈if语句中的代码可以改下:
if(filedlg.DoModal() == IDOK)
{
strfilename = filedlg.GetPathName();
FILE* fp = _tfopen((LPCTSTR)strfilename,_T("r"));
CString tmp;
tmp.Format(_T("文件为[%s],fp的值为%d"),strfilename,fp);
AfxMessageBox(tmp,MB_OK);
}
_wfopen(..., _T("r"));
函数用_wfopen会使后面的_T("r")参数面临非常尴尬的局面。
----------------------
CString一些用法:
1)CString重载了类型操作符LPCTSTR:
CString str(_T("123"));
LPCTSTR pStr = (LPCTSTR)str;
以上第二行代码意义为,str调用了operator LPCTSTR()函数,返回了一个指向缓冲区的指针,该指针是LPCTSTR。
2)对于LPTSTR的指针类型,CString没有简单重载操作符,必须通过调用GetBuffer(int nBytes)获取到缓冲区的指针,类型为LPTSTR。
用完后,应该调用ReleaseBuffer。
GetBuffer时CString会锁定内存块,因此用完应该调用ReleaseBuffer释放,很多人都不知道GetBuffer后要释放,其实大多数情况下可能会正常工作,因为一般析构函数会解决该问题,但在一些情况下会出问题,如果不知道CString的机理,根本无法进行调试纠错。
3)CString对API函数的支持:
如新建控制台工程,勾选“MFC”选项,源代码如下:
// StringDemo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "StringDemo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
CStringA strTextA("中国");
CStringW strTextW(L"");
DWORD dwBufSize = (strTextA.GetLength() + 1) * sizeof(WCHAR);
nRetCode = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)strTextA, strTextA.GetLength() + 1, strTextW.GetBuffer(dwBufSize), dwBufSize / sizeof(WCHAR));
strTextW.ReleaseBuffer();
if (!nRetCode) {
strTextW.Format(L"调用MultiByteToWideChar错误,错误码#%u", GetLastError());
}
//项目必须使用UNICODE字符集,否则AfxMessageBox不支持LPCWSTR类型参数
AfxMessageBox((LPCWSTR)strTextW);
}
//该示例反应了CString能很好地支持WIN32 API函数的调用。
return nRetCode;
}
展开全部
你直接把path定义成TCHAR*就行了,这样也不用字符串转换了,不知道你是不是用的vs2005以上版本,是的话里面的函数基本都支持宽字符了,也不要花费精力去字符串转换了
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
你的字符集不统一。
你的工程设置的是Unicode字符集,但path是char类型的,是多字符集,fopen也是多字符集函数,所以用fopen就有问题了,应该统一都用Unicode字符集。
可以修改如下:
CString strfilename;
TCHAR* path;
CFileDialog filedlg(1,0, 0, 4|2,_T("mp3音乐文件|*.mp3||"),0,0, 1);
if(filedlg.DoModal() == IDOK)
{
strfilename = filedlg.GetPathName();
path = strfilename.GetBuffer(0);
FILE* fp = _wfopen(path,_T("r"));
CString tmp;
tmp.Format(L"文件为[%s],fp的值为%d",path,fp);
AfxMessageBox(tmp,MB_OK);
}
你的工程设置的是Unicode字符集,但path是char类型的,是多字符集,fopen也是多字符集函数,所以用fopen就有问题了,应该统一都用Unicode字符集。
可以修改如下:
CString strfilename;
TCHAR* path;
CFileDialog filedlg(1,0, 0, 4|2,_T("mp3音乐文件|*.mp3||"),0,0, 1);
if(filedlg.DoModal() == IDOK)
{
strfilename = filedlg.GetPathName();
path = strfilename.GetBuffer(0);
FILE* fp = _wfopen(path,_T("r"));
CString tmp;
tmp.Format(L"文件为[%s],fp的值为%d",path,fp);
AfxMessageBox(tmp,MB_OK);
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
其实,我个人觉得CString并不实用。
我一般都用TCHAR szBuf[MAX_PATH] = {0};
虽然存在缓冲区溢出的风险,大不了出现了Bug再现调试:)
如果调用API函数,传递CString是不行的,只能传TCHAR
至于ASCII和Unicode之间的麻烦,用_T()宏不就搞定了吗?!
我一般都用TCHAR szBuf[MAX_PATH] = {0};
虽然存在缓冲区溢出的风险,大不了出现了Bug再现调试:)
如果调用API函数,传递CString是不行的,只能传TCHAR
至于ASCII和Unicode之间的麻烦,用_T()宏不就搞定了吗?!
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
你都用了CFileDialog了,为什么不用CFile来打开文件呢?这样就不存在Cstring到char *的转换了。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询