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,也就是说文件没有成功打开,但文件存在的呀,也没有被使用。。。请指教下。。想不通呀
展开
 我来答
silvergingko
推荐于2016-10-27 · TA获得超过5945个赞
知道小有建树答主
回答量:688
采纳率:0%
帮助的人:868万
展开全部
基本如魔高丈所言。
但在使用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;
}
美丽生灵
2010-01-29 · TA获得超过455个赞
知道小有建树答主
回答量:279
采纳率:0%
帮助的人:171万
展开全部
你直接把path定义成TCHAR*就行了,这样也不用字符串转换了,不知道你是不是用的vs2005以上版本,是的话里面的函数基本都支持宽字符了,也不要花费精力去字符串转换了
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
魔高丈
2010-01-29 · TA获得超过9506个赞
知道大有可为答主
回答量:2066
采纳率:0%
帮助的人:3466万
展开全部
你的字符集不统一。
你的工程设置的是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);
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
夺魂狼剑
2010-01-29 · TA获得超过1273个赞
知道小有建树答主
回答量:796
采纳率:0%
帮助的人:796万
展开全部
其实,我个人觉得CString并不实用。

我一般都用TCHAR szBuf[MAX_PATH] = {0};
虽然存在缓冲区溢出的风险,大不了出现了Bug再现调试:)

如果调用API函数,传递CString是不行的,只能传TCHAR
至于ASCII和Unicode之间的麻烦,用_T()宏不就搞定了吗?!
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
tianjun9
2010-01-29 · TA获得超过306个赞
知道答主
回答量:101
采纳率:0%
帮助的人:41.9万
展开全部
你都用了CFileDialog了,为什么不用CFile来打开文件呢?这样就不存在Cstring到char *的转换了。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(5)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式