1

我在将 vs2012 中的 std::getline 函数与 MFC 应用程序一起使用时遇到问题。相同的代码在 vs2010 中运行,这就是为什么我确信这不是代码本身的问题。

void AddImage::OnClickedIdbAiRegistration(){
CFileDialog file(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "(*.dat)|*.dat||");
file.DoModal();
UpdateData();
m_ai_file=file.GetPathName();
UpdateData(FALSE);
std::string buf=m_ai_file;
if(filecnt(buf, "Dat")){
    std::ifstream file(buf);
    AfxMessageBox(buf.c_str());
    std::getline(file, buf);//Here is my problem
    AfxMessageBox(buf.c_str());
    file.close();
    }
}

第一个 AfxMessageBox 返回文件路径(正确且有效的 ASCII 文件)。我永远无法到达第二个 AfxMessageBox,因为 getline 产生:

program.exe 中 0x000007FEF7B4AAEE (msvcp110.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0xFFFFFFFFFFFFFFFF。

和 vs11 将我重定向到 xiosbase 第 443 行

    locale __CLR_OR_THIS_CALL getloc() const
    {   // get locale
    return (*_Ploc);/*THIS IS LINE 443*/
    }

对于项目属性,我使用“在共享 dll 中使用 MFC”和“多线程 DLL”和子系统“Windows”

附加程序代码,包括:

#include <afxwin.h>
#include <afxframewndex.h>
#include <afxcmn.h>
#include <afxdialogex.h>

#include <iostream>
#include <string>
#include <sstream>
#include <regex>
#include <fstream>
#include <time.h>
#include <Windows.h>

usign namespace std;

class AddImage:public CDialog{
        DECLARE_DYNAMIC(AddImage)
    public:
        AddImage(CWnd* pParent = NULL);
        virtual ~AddImage();
        enum {IDD=IDD_ADD_IMAGE};
    protected:
        virtual void DoDataExchange(CDataExchange* pDX);
        DECLARE_MESSAGE_MAP()
    public:
        CString m_ai_file;
    };

AddImage::AddImage(CWnd* pParent):CDialog(AddImage::IDD, pParent){
    m_ai_file=_T("");
    }

AddImage::~AddImage(){
    }



bool filecnt(string path, string type){
    if(filepathcnt(path, type)){
        if(GetFileAttributes(path.c_str())==-1){
            return(FALSE);
            }
        else{
            return(TRUE);
            }
        }
    else{
        return(FALSE);
        }
    }

bool filepathcnt(string path, string type){
    if(type==""){
        tr1::regex regex("[[:print:]]+\\.[[:alnum:]]+");
        if(regex_match(path.begin(), path.end(), regex)){
            return(TRUE);
            }
        else{
            return(FALSE);
            }
        }
    else if(type=="-"){
        tr1::regex regex("[[:print:]]+");
        if(regex_match(path.begin(), path.end(), regex)){
            return(TRUE);
            }
        else{
            return(FALSE);
            }
        }
    else{
        string upper=type;
        string lower=type;
        transform(upper.begin(), upper.end(), upper.begin(), toupper);
        transform(lower.begin(), lower.end(), lower.begin(), tolower);
        tr1::regex norm_regex("[[:print:]]+\\."+type);
        tr1::regex upper_regex("[[:print:]]+\\."+upper);
        tr1::regex lower_regex("[[:print:]]+\\."+lower);
        if(regex_match(path.begin(), path.end(), upper_regex) || regex_match(path.begin(), path.end(), lower_regex) || regex_match(path.begin(), path.end(), norm_regex)){
            return(TRUE);
            }
        else{
            return(FALSE);
            }
        }
    }

有人知道出了什么问题吗?

4

5 回答 5

1

我现在已经通过使用 VS10 解决了这个问题。该算法在那里没有任何问题。但我认为这不是解决方案!

它可以在同一台 PC 上与 vs10 一起使用,这也告诉我这不是 PC 的问题。

于 2012-12-21T18:16:19.047 回答
0

也许在之前包含文件路径的字符串中写入行内容不是一个好主意。尝试以下操作:

CString csFilePath("C:\\example.txt");
ifstream infile;
infile.open(csFilePath);

std::string strLine;
std::getline(infile, strLine);

顺便问一下,您是否复制并粘贴了您的代码?正如你所写:

使用命名空间标准;

而不是使用命名空间标准;

于 2012-11-30T13:17:48.470 回答
0

首先让我们简化问题:

只需硬编码路径并在新的控制台项目中运行它:(我添加了更多保护代码)


    String buf="the data file path";
    std::ifstream file(buf);
    if(!file.is_open())
        return FALSE;
    while(file.good())
    {
        cout << buf << endl;
        std::getline(file, buf);
        cout << buf << endl;
    }
    file.close();

结果是什么?如果问题仍然存在,您可以在第二个 cout << buf << endl 设置一个调试点,以检查是否为 buf 分配了一个值。

您还应该按以下方式保护 FileDialog:或者一旦单击“取消”,它将失败。


(dlg.DoModal()==IDOK)
  FilePathName=dlg.GetPathName();
  //....other opertiaon
} 

于 2012-11-27T07:28:00.970 回答
0

当您打开一个文件对象时,您应该在尝试使用它之前始终确保它是有效的。

if (file.bad())
    AfxMessageBox("Bad file");
else
{ // existing code follows

PS 你有两个file在同一个代码块中命名的对象。请不要这样做,即使编译器能够保持正确,它也可能会造成混淆。

于 2012-11-26T19:13:58.100 回答
0

它正在工作,但不再有效。

对于调试和发布配置,将编译标志(在项目属性 > 配置属性 > C++ > 代码生成 > 运行时库中)从/MD(多线程 DLL)更改为/MDd(多线程调试 DLL)。

这至少应该在 VisualStudio 2012 中工作。

于 2015-05-27T14:18:28.620 回答