Adjust Mfcapp

Hi,
Further to the thread

http://www.experts-exchange.com/questions/28693180/Test-against-App.html#a40896699

where to adjust, if I expect to also search record by "Name key" and "Number key"?
LVL 11
HuaMin ChenProblem resolverAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

sarabandeCommented:
you may use the following change of rc file

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#include "afxres.h"
#include "verrsrc.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE
BEGIN
    "#ifndef APSTUDIO_INVOKED\r\n"
    "#include ""targetver.h""\r\n"
    "#endif\r\n"
    "#include ""afxres.h""\r\n"
    "#include ""verrsrc.h""\r\n"
    "\0"
END

3 TEXTINCLUDE
BEGIN
    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
    "#define _AFX_NO_OLE_RESOURCES\r\n"
    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
    "\r\n"
    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
    "LANGUAGE 9, 1\r\n"    
    "#include ""res\\MfcApplication9.rc2""  // non-Microsoft Visual C++ edited resources\r\n"
    "#include ""afxres.rc""      // Standard components\r\n"
    "#if !defined(_AFXDLL)\r\n"
    "#include ""afxribbon.rc""   // MFC ribbon and control bar resources\r\n"
    "#endif\r\n"
    "#endif\r\n"
    "\0"
END

/////////////////////////////////////////////////////////////////////////////
#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME           ICON         "res\\MfcApplication9.ico"


#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About MfcApplication9"
FONT 8, "MS Shell Dlg"
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
    LTEXT           "MfcApplication9, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2015",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "OK",IDOK,113,41,50,14,WS_GROUP
END

IDD_MFCAPPLICATION9_DIALOG DIALOGEX 0, 0, 584, 265
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "MfcApplication9"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,474,244,50,14,NOT WS_VISIBLE
    PUSHBUTTON      "Cancel",IDCANCEL,527,244,50,14
    GROUPBOX        "Binary File Selection",IDC_GRP_RAD,10,18,261,105
    CONTROL         "Name Index",IDC_RAD_NAME,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,23,35,61,10
    CONTROL         "Number Index",IDC_RAD_NUMBER,"Button",BS_AUTORADIOBUTTON,23,55,61,10
    CONTROL         "Data Record",IDC_RAD_DATARECORD,"Button",BS_AUTORADIOBUTTON,23,75,61,10
    LTEXT           "File Number",IDC_STAT_NAME_FILENUM,112,36,39,8
    EDITTEXT        IDC_EDIT_NAME_FILENUM,155,34,29,14,ES_AUTOHSCROLL
    LTEXT           "File Number",IDC_STAT_NUMBER_FILENUM,111,55,39,8
    EDITTEXT        IDC_EDIT_NUMBER_FILENUM,155,52,29,14,ES_AUTOHSCROLL
    LTEXT           "File Path",IDC_STAT_FILE_PATH,22,96,28,8
    EDITTEXT        IDC_EDIT_FILE_PATH,62,94,199,14,ES_AUTOHSCROLL
    GROUPBOX        "Binary File Info",IDC_GRP_FILEINFO,276,17,301,105
    LTEXT           "Record Size",IDC_STAT_RECSIZE,296,31,52,8
    EDITTEXT        IDC_EDIT_RECSIZE,354,29,48,14,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY
    LTEXT           "Record Count",IDC_STAT_RECCOUNT,296,47,52,8
    EDITTEXT        IDC_EDIT_RECCOUNT,354,45,48,14,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY
    LTEXT           "Record Number",IDC_STAT_RECNUM,296,71,52,9,NOT WS_GROUP
    EDITTEXT        IDC_EDIT_RECNUM,354,69,48,14,ES_AUTOHSCROLL
    GROUPBOX        "",IDC_STATIC,295,57,244,9
    LTEXT           "Number Key",IDC_STAT_NUMKEY,296,106,52,8,NOT WS_GROUP
    EDITTEXT        IDC_EDIT_NUMKEY,354,104,75,14,ES_AUTOHSCROLL
    LTEXT           "Name Key",IDC_STAT_NAMEKEY,296,88,52,8,NOT WS_GROUP
    EDITTEXT        IDC_EDIT_NAMEKEY,354,86,112,14,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "Get Record",IDC_BUT_GETRECORD,520,68,50,14
    EDITTEXT        IDC_EDIT_OUTPUT,17,148,188,87,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY
    GROUPBOX        "Record Info",IDC_GRP_RECINFO,10,129,567,112
    EDITTEXT        IDC_EDIT_HEXINFO,206,148,371,87,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
    LTEXT           "Output",IDC_STAT_OUTPUT,99,138,52,8,NOT WS_GROUP
    LTEXT           "Hex Info",IDC_STAT_HEXINFO,340,138,52,8,NOT WS_GROUP
    LTEXT           "Num Items",IDC_STAT_NUMITEMS,424,31,43,8
    EDITTEXT        IDC_EDIT_NUMITEMS,469,29,48,14,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY
    LTEXT           "Item Number",IDC_STAT_ITEMNUM,424,71,43,9,NOT WS_GROUP
    EDITTEXT        IDC_EDIT_ITEMNUM,469,68,24,14,ES_AUTOHSCROLL
END

                                          

/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO     VERSIONINFO
  FILEVERSION       1,0,0,1
  PRODUCTVERSION    1,0,0,1
 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
 FILEFLAGS VS_FF_DEBUG
#else
 FILEFLAGS 0x0L
#endif
 FILEOS VOS_NT_WINDOWS32
 FILETYPE VFT_APP
 FILESUBTYPE VFT2_UNKNOWN
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904B0"
        BEGIN
            VALUE "CompanyName", "TODO: <Company name>"
            VALUE "FileDescription", "MfcApplication9"
            VALUE "FileVersion",     "1.0.0.1"
            VALUE "InternalName",    "MfcApplication9.exe"
            VALUE "LegalCopyright", "TODO: (c) <Company name>.  All rights reserved."
            VALUE "OriginalFilename","MfcApplication9.exe"
            VALUE "ProductName", "TODO: <Product name>"
            VALUE "ProductVersion",  "1.0.0.1"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x0409, 1200
    END
END

/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 163
        TOPMARGIN, 7
        BOTTOMMARGIN, 55
    END
    IDD_MFCAPPLICATION9_DIALOG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 577
        TOPMARGIN, 7
        BOTTOMMARGIN, 258
    END
END
#endif    // APSTUDIO_INVOKED



/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE
BEGIN
    IDS_ABOUTBOX            "&About MfcApplication9..."
END


#endif

#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#include "res\\MfcApplication9.rc2"  // non-Microsoft Visual C++ edited resources
#include "afxres.rc"      // Standard components
#if !defined(_AFXDLL)
#include "afxribbon.rc"   // MFC ribbon and control bar resources
#endif
#endif
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

Open in new window


in mfcapplication9dlg.h add new member function

     
const char * CStringToStdString(const CString & cstr);

Open in new window


below function StringToLongLong.

in mfcapplication9dlg.cpp

- add #include <vector> to include statements
- replace function StringToLongLong by

   
long long CMfcApplication9Dlg::StringToLongLong(const CString & strNum)
{
    int       len = strNum.GetLength();
    long long num = 0;
    for (int n = 0; n < len; ++n)
    {
        TCHAR digit = strNum[n];
        if (digit < _T('0') || digit > _T('9')) break;
        num *= 10;
        num += (digit - _T('0'));
    }
    return num;
}

Open in new window


- add function CStringToStdString below function LongLongToString

   
const char * CMfcApplication9Dlg::CStringToStdString(const CString & cstr)
{
    static std::vector<char> str;
    size_t len = cstr.GetLength();
    str.clear();
    str.resize(len+2, '\0');
    if (sizeof(TCHAR) == sizeof(wchar_t))
    {
        size_t sizConverted = 0;
        wcstombs_s(&sizConverted, &str[0], len+2, (const wchar_t*)(const TCHAR*)cstr, len);
    }
    else
    {

        strcpy_s(&str[0], str.size(), (const char*)(const TCHAR*)cstr);
    }
    return &str[0];
}

Open in new window


- add following code snippet at end of function OnBnClickedButGetRecord (above last statement UpdateData(FALSE); )

 
    else if (m_strNameKey.IsEmpty() == false)
    {
        std::string strName = CStringToStdString(m_strNameKey);
        std::string strFile = CStringToStdString(m_strFilePath);
        bool bShowRecord = false;
        if (m_radSelection == recordSelected)
        {
            int pos = m_strFilePath.Find(_T("\\fl"));
            if (pos > 0)
            {
                strFile = strFile.substr(0, pos+1) + "flname";
            }
            bShowRecord = true;
        }
        else
        {
            int pos = strFile.find(".idx");
            strFile.resize(pos);
        }
        std::string strresult;
        index_name  searchindex = { 0 };
        index_name  foundindex = { 0 };

        strncpy_s(searchindex.name, sizeof(searchindex.name), strName.c_str(), _TRUNCATE);
        bool bfound = binarySearch<index_name>(strFile, searchindex, strresult, foundindex);
        unsigned int recnum_w = foundindex.recnum;
        if (bfound && recnum_w > 0)
        {
            m_strRecNum    = LongLongToString(recnum_w);
            m_radSelection = recordSelected;

            UpdateData(FALSE);
            if (m_strRecNum.IsEmpty() == false)
            {
                OnBnClickedRadDatarecord();
                OnBnClickedButGetRecord();
            }
        }
    }
    else if (m_strNumKey.IsEmpty() == false)
    {
        std::string strNum = CStringToStdString(m_strNumKey);
        std::string strFile = CStringToStdString(m_strFilePath);
        bool bShowRecord = false;
        if (m_radSelection == recordSelected)
        {
            int pos = m_strFilePath.Find(_T("\\fl"));
            if (pos > 0)
            {
                strFile = strFile.substr(0, pos+1) + "flnumber";
            }
            bShowRecord = true;
        }
        else
        {
            int pos = strFile.find(".idx");
            strFile.resize(pos);
        }
        std::string strresult;
        index_number searchindex = { 0 };
        index_number foundindex = { 0 };

        searchindex.number = StringToLongLong(m_strNumKey);
        bool bfound = binarySearch<index_number>(strFile, searchindex, strresult, foundindex);
        unsigned int recnum_w = foundindex.recnum;
        if (bfound && recnum_w > 0)
        {
            m_strRecNum    = LongLongToString(recnum_w);
            m_radSelection = recordSelected;

            UpdateData(FALSE);
            if (m_strRecNum.IsEmpty() == false)
            {
                OnBnClickedRadDatarecord();
                OnBnClickedButGetRecord();
            }
        }
    }

Open in new window


Sara
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
HuaMin ChenProblem resolverAuthor Commented:
Many many thanks Sara.
I have done all you suggested and have got these.
Error      1      error C2039: 'CStringToStdString' : is not a member of 'CMfcApplication9Dlg'      c:\mfcapplication9 150704\mfcapplication9\mfcapplication9dlg.cpp      382      1      MfcApplication9
      2      IntelliSense: class "CMfcApplication9Dlg" has no member "CStringToStdString"      c:\MfcApplication9 150704\MfcApplication9\MfcApplication9Dlg.cpp      382      35      MfcApplication9
0
sarabandeCommented:
i told you
in mfcapplication9dlg.h add new member function  

const char * CStringToStdString(const CString & cstr);

did you forget to add the member function to class CMfcApplication9Dlg or did you put it outside of the class definition?

you may add the statement at end of class above function prototypes beginning with afx_msg.

class CMfcApplication9Dlg : public CDialogEx
{
     ....
     const char * CStringToStdString(const CString & cstr);

     afx_msg void OnBnClickedRadName();
     ....
};

Open in new window


Sara
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

HuaMin ChenProblem resolverAuthor Commented:
Good day Sara,
To the same Number highlighted below, to the record
30a
why do I get different record, after I've only put the Number, and then have pressed "Get record" button?
30b
0
sarabandeCommented:
why do I get different record, after I've only put the Number, and then have pressed "Get record" button?
each record has 10 items. if you don't set the item number you always see first item of the chosen record. there is only a chance 1 of 10 to see the right item this way. however we could enhance the functionality and search the record for the right item and put that into focus.

i see that your output window shows non-ansi letters for all members, even for the item::number it has special characters and not digits.  that shouldn't happen. perhaps you didn't have all my changes.

here is  the cpp file again:
// MfcApplication9Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "MfcApplication9.h"
#include "MfcApplication9Dlg.h"

#include "BinaryHeader.h"

#include <string>
#include <vector>
#include <sstream>
#include <utility>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include <sys/stat.h>

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
      CAboutDlg();

      // Dialog Data
      enum { IDD = IDD_ABOUTBOX };

protected:
      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

      // Implementation
protected:
      DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()

// CMfcApplication9Dlg dialog

CMfcApplication9Dlg::CMfcApplication9Dlg(CWnd* pParent /*=NULL*/)
      : CDialogEx(CMfcApplication9Dlg::IDD, pParent)
      , m_radSelection(0)
      , m_strNameFileNum(_T(""))
      , m_strNumberFileNum(_T(""))
      , m_strFilePath(_T(""))
      , m_strRecSize(_T(""))
      , m_strRecCount(_T(""))
      , m_strRecNum(_T(""))
      , m_strNumKey(_T(""))
      , m_strNameKey(_T(""))
      , m_strOutput(_T(""))
      , m_strHexInfo(_T(""))
      , m_strNumItems(_T(""))
      , m_strItemNum(_T(""))
{
      m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMfcApplication9Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_STAT_NAME_FILENUM, m_statNameFileNum);
    DDX_Control(pDX, IDC_STAT_NUMBER_FILENUM, m_statNumberFileNum);
    DDX_Control(pDX, IDC_EDIT_NAME_FILENUM, m_editNameFileNum);
    DDX_Control(pDX, IDC_EDIT_NUMBER_FILENUM, m_editNumberFileNum);
    DDX_Text(pDX, IDC_EDIT_NAME_FILENUM, m_strNameFileNum);
    DDX_Text(pDX, IDC_EDIT_NUMBER_FILENUM, m_strNumberFileNum);
    DDX_Text(pDX, IDC_EDIT_FILE_PATH, m_strFilePath);
    DDX_Radio(pDX, IDC_RAD_NAME, m_radSelection);
    DDX_Text(pDX, IDC_EDIT_RECSIZE, m_strRecSize);
    DDX_Text(pDX, IDC_EDIT_RECCOUNT, m_strRecCount);
    DDX_Control(pDX, IDC_EDIT_RECNUM, m_editRecNum);
    DDX_Text(pDX, IDC_EDIT_RECNUM, m_strRecNum);
    DDX_Control(pDX, IDC_EDIT_NUMKEY, m_editNumKey);
    DDX_Text(pDX, IDC_EDIT_NUMKEY, m_strNumKey);
    DDX_Control(pDX, IDC_EDIT_NAMEKEY, m_editNameKey);
    DDX_Text(pDX, IDC_EDIT_NAMEKEY, m_strNameKey);
    DDX_Text(pDX, IDC_EDIT_OUTPUT, m_strOutput);
    DDX_Text(pDX, IDC_EDIT_HEXINFO, m_strHexInfo);
    DDX_Control(pDX, IDC_EDIT_HEXINFO, m_editHexInfo);
    DDX_Text(pDX, IDC_EDIT_NUMITEMS, m_strNumItems);
    DDX_Control(pDX, IDC_STAT_ITEMNUM, m_statItemNum);
    DDX_Control(pDX, IDC_EDIT_ITEMNUM, m_editItemNum);
    DDX_Text(pDX, IDC_EDIT_ITEMNUM, m_strItemNum);
}

BEGIN_MESSAGE_MAP(CMfcApplication9Dlg, CDialog)
      ON_WM_SYSCOMMAND()
      ON_WM_PAINT()
      ON_WM_QUERYDRAGICON()
      //}}AFX_MSG_MAP
      ON_BN_CLICKED(IDC_RAD_NAME, &CMfcApplication9Dlg::OnBnClickedRadName)
      ON_BN_CLICKED(IDC_RAD_NUMBER, &CMfcApplication9Dlg::OnBnClickedRadNumber)
      ON_BN_CLICKED(IDC_RAD_DATARECORD, &CMfcApplication9Dlg::OnBnClickedRadDatarecord)
      ON_EN_KILLFOCUS(IDC_EDIT_NAME_FILENUM, &CMfcApplication9Dlg::OnEnKillfocusEditNameFilenum)
      ON_EN_KILLFOCUS(IDC_EDIT_NUMBER_FILENUM, &CMfcApplication9Dlg::OnEnKillfocusEditNumberFilenum)
      ON_BN_CLICKED(IDC_BUT_GETRECORD, &CMfcApplication9Dlg::OnBnClickedButGetRecord)
      ON_EN_KILLFOCUS(IDC_EDIT_FILE_PATH, &CMfcApplication9Dlg::OnEnKillfocusEditFilePath)
      ON_EN_KILLFOCUS(IDC_EDIT_RECNUM, &CMfcApplication9Dlg::OnEnKillfocusEditRecnum)
      ON_EN_KILLFOCUS(IDC_EDIT_NUMKEY, &CMfcApplication9Dlg::OnEnKillfocusEditNumkey)
      ON_EN_KILLFOCUS(IDC_EDIT_NAMEKEY, &CMfcApplication9Dlg::OnEnKillfocusEditNamekey)
END_MESSAGE_MAP()


// CMfcApplication9Dlg message handlers

BOOL CMfcApplication9Dlg::OnInitDialog()
{
      CDialog::OnInitDialog();

      // Add "About..." menu item to system menu.

      // IDM_ABOUTBOX must be in the system command range.
      ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
      ASSERT(IDM_ABOUTBOX < 0xF000);

      CMenu* pSysMenu = GetSystemMenu(FALSE);
      if (pSysMenu != NULL)
      {
            CString strAboutMenu;
            strAboutMenu.LoadString(IDS_ABOUTBOX);
            if (!strAboutMenu.IsEmpty())
            {
                  pSysMenu->AppendMenu(MF_SEPARATOR);
                  pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
            }
      }

      // Set the icon for this dialog.  The framework does this automatically
      //  when the application's main window is not a dialog
      SetIcon(m_hIcon, TRUE);                  // Set big icon
      SetIcon(m_hIcon, FALSE);            // Set small icon

      // TODO: Add extra initialization here
      m_radSelection = nameSelected;
      m_strFilePath = _T("C:\\dp4\\");
      UpdateData(FALSE);

      OnBnClickedRadName();

      return FALSE;  // return TRUE  unless you set the focus to a control
}

void CMfcApplication9Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
      if ((nID & 0xFFF0) == IDM_ABOUTBOX)
      {
            CAboutDlg dlgAbout;
            dlgAbout.DoModal();
      }
      else
      {
            CDialog::OnSysCommand(nID, lParam);
      }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMfcApplication9Dlg::OnPaint()
{
      if (IsIconic())
      {
            CPaintDC dc(this); // device context for painting

            SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

            // Center icon in client rectangle
            int cxIcon = GetSystemMetrics(SM_CXICON);
            int cyIcon = GetSystemMetrics(SM_CYICON);
            CRect rect;
            GetClientRect(&rect);
            int x = (rect.Width() - cxIcon + 1) / 2;
            int y = (rect.Height() - cyIcon + 1) / 2;

            // Draw the icon
            dc.DrawIcon(x, y, m_hIcon);
      }
      else
      {
            CDialog::OnPaint();
      }
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMfcApplication9Dlg::OnQueryDragIcon()
{
      return static_cast<HCURSOR>(m_hIcon);
}

void CMfcApplication9Dlg::EnableDisableFileNum()
{
      m_statNameFileNum.EnableWindow(m_radSelection == nameSelected);
      m_editNameFileNum.EnableWindow(m_radSelection == nameSelected);
      m_statNumberFileNum.EnableWindow(m_radSelection == numberSelected);
      m_editNumberFileNum.EnableWindow(m_radSelection == numberSelected);
      m_statItemNum.EnableWindow(m_radSelection == recordSelected);
      m_editItemNum.EnableWindow(m_radSelection == recordSelected);
      if (m_radSelection != recordSelected) m_strItemNum = "";
}

void CMfcApplication9Dlg::OnBnClickedRadName()
{
      // TODO: Add your control notification handler code here
      m_radSelection = nameSelected;
      EnableDisableFileNum();
      BuildFileName(_T("flname"));

}

void CMfcApplication9Dlg::OnBnClickedRadNumber()
{
      // TODO: Add your control notification handler code here
      m_radSelection = numberSelected;
      EnableDisableFileNum();
      BuildFileName(_T("flnumber"));
}

void CMfcApplication9Dlg::OnBnClickedRadDatarecord()
{
      // TODO: Add your control notification handler code here
      m_radSelection = recordSelected;
      EnableDisableFileNum();
      BuildFileName(_T("flout"));
}

void CMfcApplication9Dlg::OnEnKillfocusEditNameFilenum()
{
      // TODO: Add your control notification handler code here  
      BuildFileName(_T("flname"));
}

void CMfcApplication9Dlg::OnEnKillfocusEditNumberFilenum()
{
      // TODO: Add your control notification handler code here
      BuildFileName(_T("flnumber"));
}

void CMfcApplication9Dlg::OnEnKillfocusEditFilePath()
{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);
}

void CMfcApplication9Dlg::BuildFileName(const CString & strFileName)
{
      UpdateData(TRUE);
      CString strFileExt = _T(".idx");

      CString strFileNum;
      int     recsize = 0;

      if (m_radSelection == nameSelected)
      {
            recsize = (int)sizeof(index_name);
            if (m_strNameFileNum.IsEmpty() == false)
            {
                  strFileNum = _T("_");
                  strFileNum += m_strNameFileNum;
            }
      }
      else if (m_radSelection == numberSelected)
      {
            recsize = (int)sizeof(index_number);
            if (m_strNumberFileNum.IsEmpty() == false)
            {
                  strFileNum = _T("_");
                  strFileNum += m_strNumberFileNum;
            }
      }
      else
      {
            recsize = (int)sizeof(rec_struc);
            strFileExt = _T(".dat");
      }
      CString strFilePath = m_strFilePath;
      int pos = strFilePath.Find(_T("\\fl"));
      if (pos > 0)
      {
            strFilePath = strFilePath.Left(pos + 1);
      }
      strFilePath += strFileName;
      strFilePath += strFileNum;
      strFilePath += strFileExt;
      m_strFilePath = strFilePath;

      struct _stat64 fs = { 0 };
      char szPath[512] = { '\0' };
      if (sizeof(TCHAR) == 2)
      {
          size_t sizConverted = 0;
          wcstombs_s(&sizConverted, szPath, sizeof(szPath), (const wchar_t*)strFilePath, strFilePath.GetLength());
      }
      else
      {
          strcpy_s(szPath, sizeof(szPath), (const char *)(const TCHAR *)strFilePath);
      }
      m_strOutput = _T("");
      if (_stat64(szPath, &fs) != 0)
      {
          m_strOutput = _T("File <") + m_strFilePath + _T(">, File doesn't exist.");
      }
      else
      {
#ifdef UNICODE
          std::wostringstream wos1, wos2, wos3;
          wos1 << (size_t)(fs.st_size/recsize);
          m_strRecCount = wos1.str().c_str();
          wos2 << (size_t)(recsize);
          m_strRecSize = wos2.str().c_str();
          wos3 << NUM_ITEMS;
          m_strNumItems = wos3.str().c_str();
#else
          std::ostringstream oss1, oss2, oss3;
          oss1 << (size_t)(fs.st_size/recsize);
          m_strRecCount = oss1.str().c_str();
          oss2 << (size_t)(recsize);
          m_strRecSize = oss2.str().c_str();
          oss3 << NUM_ITEMS;
          m_strNumItems = oss3.str().c_str();
#endif
      }

      UpdateData(FALSE);


}

long long CMfcApplication9Dlg::StringToLongLong(const CString & strNum)
{
    int       len = strNum.GetLength();
    long long num = 0;
    for (int n = 0; n < len; ++n)
    {
        TCHAR digit = strNum[n];
        if (digit < _T('0') || digit > _T('9')) break;
        num *= 10;
        num += (digit - _T('0'));
    }
    return num;
}

CString CMfcApplication9Dlg::LongLongToString(long long num)
{
    CString str;
    while (num != 0)
    {
        TCHAR tc = (TCHAR)(num%10);
        str += (TCHAR)(_T('0') + tc);
        num /= 10;
    }
    if (str.IsEmpty() == false)
    {
        int len = str.GetLength();
        int pos = -1;
        TCHAR * pstr = str.GetBuffer(len);
        while (--len > ++pos)
        {
            const TCHAR tc = str[len];
            *(pstr+len) = *(pstr+pos);
            *(pstr+pos) = tc;
        }
    }
    return str;
}

const char * CMfcApplication9Dlg::CStringToStdString(const CString & cstr)
{
    static std::vector<char> str;
    size_t len = cstr.GetLength();
    str.clear();
    str.resize(len+2, '\0');
    if (sizeof(TCHAR) == sizeof(wchar_t))
    {
        size_t sizConverted = 0;
        wcstombs_s(&sizConverted, &str[0], len+2, (const wchar_t*)(const TCHAR*)cstr, len);
    }
    else
    {

        strcpy_s(&str[0], str.size(), (const char*)(const TCHAR*)cstr);
    }
    return &str[0];
}


void CMfcApplication9Dlg::OnBnClickedButGetRecord()
{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);
    if (m_strRecNum.IsEmpty() == false)
    {
        long long recnum = StringToLongLong(m_strRecNum);
        char szPath[512] = { '\0' };
        if (sizeof(TCHAR) == 2)
        {
            size_t sizConverted = 0;
            wcstombs_s(&sizConverted, szPath, sizeof(szPath), (const wchar_t*)m_strFilePath, m_strFilePath.GetLength());
        }
        else
        {
            strcpy_s(szPath, sizeof(szPath), (const char *)(const TCHAR *)m_strFilePath);
        }
        std::ifstream ifs(szPath, std::ios::binary | std::ios::in);
        int recsize = (m_radSelection == nameSelected)   ? sizeof(index_name) : 
                      (m_radSelection == numberSelected) ? sizeof(index_number) 
                                                         : sizeof(rec_struc);
        if (!ifs.seekg(recsize*recnum))
        {
            ifs.close();
            m_strOutput = _T("");
            m_strOutput = _T("File <") + m_strFilePath + _T(">, Cannot seek record at position <") + m_strRecNum + _T(" * ") + m_strRecSize + _T(">");
            m_editRecNum.SetFocus();
            UpdateData(FALSE);
            return;
        }
        std::string strBuf(recsize, '\0');
        if (!ifs.read(&strBuf[0], recsize))
        {
            ifs.close();
            m_strOutput = _T("");
            m_strOutput = _T("File <") + m_strFilePath + _T(">, Cannot read record <") + m_strRecNum + _T(">");
            m_editRecNum.SetFocus();
            UpdateData(FALSE);
            return;
        }
        if (m_radSelection == nameSelected)
        {
            index_name nameidx = { 0};
            memcpy(&nameidx, strBuf.c_str(), recsize);

            m_strOutput = _T("index_name::recnum = ") + LongLongToString(nameidx.recnum) + _T("\r\nindex_name::name = ") + CString(nameidx.name);
        }
        else if (m_radSelection == numberSelected)
        {
            index_number numidx = { 0};
            memcpy(&numidx, strBuf.c_str(), recsize);

            m_strOutput = _T("index_number::recnum = ") + LongLongToString(numidx.recnum) + _T("\r\nindex_number::number = ") + LongLongToString(numidx.number);
        }
        else if (m_radSelection == recordSelected)
        {
            rec_struc record = { 0 };

            memcpy(&record, strBuf.c_str(), recsize);
            int it = (int)StringToLongLong(m_strItemNum);
            if (it < 0 || it > NUM_ITEMS) it = 0;
            m_strOutput = _T("rec_struc::items[") + LongLongToString(it) + CString("]:") +
                          _T("\r\nitem::name = ") + CString(record.items[it].name) + 
                          _T("\r\nitem::number = ") + LongLongToString(record.items[it].number) + 
                          _T("\r\nitem::description = ") + CString(record.items[it].description);
        }

        FillHexInfo(recsize, &strBuf[0]);
    }
    else if (m_strNameKey.IsEmpty() == false)
    {
        std::string strName = CStringToStdString(m_strNameKey);
        std::string strFile = CStringToStdString(m_strFilePath);
        bool bShowRecord = false;
        if (m_radSelection == recordSelected)
        {
            int pos = m_strFilePath.Find(_T("\\fl"));
            if (pos > 0)
            {
                strFile = strFile.substr(0, pos+1) + "flname";
            }
            bShowRecord = true;
        }
        else
        {
            int pos = strFile.find(".idx");
            strFile.resize(pos);
        }
        std::string strresult;
        index_name  searchindex = { 0 };
        index_name  foundindex = { 0 };

        strncpy_s(searchindex.name, sizeof(searchindex.name), strName.c_str(), _TRUNCATE);
        bool bfound = binarySearch<index_name>(strFile, searchindex, strresult, foundindex);
        unsigned int recnum_w = foundindex.recnum;
        if (bfound && recnum_w > 0)
        {
            m_strRecNum    = LongLongToString(recnum_w);
            m_radSelection = recordSelected;

            UpdateData(FALSE);
            if (m_strRecNum.IsEmpty() == false)
            {
                OnBnClickedRadDatarecord();
                OnBnClickedButGetRecord();
            }
        }
    }
    else if (m_strNumKey.IsEmpty() == false)
    {
        std::string strNum = CStringToStdString(m_strNumKey);
        std::string strFile = CStringToStdString(m_strFilePath);
        bool bShowRecord = false;
        if (m_radSelection == recordSelected)
        {
            int pos = m_strFilePath.Find(_T("\\fl"));
            if (pos > 0)
            {
                strFile = strFile.substr(0, pos+1) + "flnumber";
            }
            bShowRecord = true;
        }
        else
        {
            int pos = strFile.find(".idx");
            strFile.resize(pos);
        }
        std::string strresult;
        index_number searchindex = { 0 };
        index_number foundindex = { 0 };

        searchindex.number = StringToLongLong(m_strNumKey);
        bool bfound = binarySearch<index_number>(strFile, searchindex, strresult, foundindex);
        unsigned int recnum_w = foundindex.recnum;
        if (bfound && recnum_w > 0)
        {
            m_strRecNum    = LongLongToString(recnum_w);
            m_radSelection = recordSelected;

            UpdateData(FALSE);
            if (m_strRecNum.IsEmpty() == false)
            {
                OnBnClickedRadDatarecord();
                OnBnClickedButGetRecord();
            }
        }
    }
    UpdateData(FALSE);
}

void CMfcApplication9Dlg::FillHexInfo(int recsize, char szBuf[])
{
    static CFont font;
    static bool  bInitFont = true;
    CClientDC dc(this);
    if (bInitFont)
    {
        int lfHeight = -MulDiv(6, GetDeviceCaps(dc.m_hDC, LOGPIXELSY), 72);

        LOGFONT logFont = { lfHeight, 0, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, 0, 0, DEFAULT_QUALITY, FIXED_PITCH, {'C', 'o', 'u', 'r', 'i', 'e', 'r', '\0' }};
        font.CreateFontIndirectW(&logFont);
        bInitFont = false;
    }
    m_editHexInfo.SetFont(&font);
    char hexdigits[] = "0123456789ABCDEF";
    std::string hexbuf(5*recsize, '\0');
    std::string strbuf(szBuf, recsize);
    char * p = &hexbuf[0];
    char * q = &strbuf[0];
    for (int n = 0, m = 0; n < recsize; ++n)    
    {
            *p++ = hexdigits[((*q)&0xf0)>>4];  // convert high half-byte
            *p++ = hexdigits[((*q)&0x0f)];         // convert low half-byte
            *p++ = ' ';
            q++;
            if ((n+1)%16 == 0 && (n+1) < recsize)
            {
                *p++ = ' ';
                for (int k = 0; m < recsize && k < 16; ++k, ++m)
                {
                    if (isprint((unsigned char)strbuf[m]))
                        *p++ = strbuf[m];
                    else 
                        *p++ = '.';
                }
                *p++ = '\r';
                *p++ = '\n';
            }
            else if (n+1 >= recsize)
            {
                int k;
                for (k = 0; k < 16 - (recsize - m); ++k) 
                {
                    *p++ = ' ';
                    *p++ = ' ';
                    *p++ = ' ';
                }
                *p++ = ' ';
                for (; m < recsize && k < 16; ++k, ++m)
                {
                    if (isprint((unsigned char)strbuf[m]))
                        *p++ = strbuf[m];
                    else 
                        *p++ = '.';
                }
            }
    }
    *p = '\0';
    int poslen = hexbuf.find('\0');
    if (poslen != (int)std::string::npos)
        hexbuf.resize(poslen);
    if (sizeof(TCHAR) == 2)
    {
        size_t nConverted = 0;
        wchar_t wbuf[16386] = { 0 };
        mbstowcs_s(&nConverted, wbuf, sizeof(wbuf)/sizeof(wbuf[0]), hexbuf.c_str(), hexbuf.length());
        m_strHexInfo = wbuf;
    }
    else
    {
        m_strHexInfo = (const TCHAR*)hexbuf.c_str();
    }
}

void CMfcApplication9Dlg::OnEnKillfocusEditRecnum()
{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);
    m_strNumKey = _T("");
    m_strNameKey = _T("");
    UpdateData(FALSE);
}


void CMfcApplication9Dlg::OnEnKillfocusEditNumkey()
{
    // TODO: Add your control notification handler code here      
    UpdateData(TRUE);
    m_strRecNum = _T("");
    m_strNameKey = _T("");
    UpdateData(FALSE);

}


void CMfcApplication9Dlg::OnEnKillfocusEditNamekey()
{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);
    m_strRecNum = _T("");
    m_strNumKey = _T("");
    UpdateData(FALSE);
}

Open in new window


Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Many thanks Sara.
I apply your codes to MfcApplication9Dlg.cpp file but I still get the following
31
0
sarabandeCommented:
there is something wrong with the record begin in the hex info.

the record count is an odd number what shouldn't be the case. the 1360 record size is wrong as well. it should be 10 times sizeof(struct item)- that means you have 136 bytes size for an item. but the 3 members of struct item should be

char name[21];
long long number;
wchar_t description[100];

that is 21 + 8 + 200 = 229

the member 'name' was aligned to next border of 4 bytes, hence we get 3 padding bytes between name and number. so the total size of struct item should be 232 bytes. you can see that i am right in the hex info window. a new item record begins in the second row at 9th byte with hex '58' what is an 'X'. the name is 'Xbcrd....' as can you see at the right. at end of 3rd row we have 4 zero bytes '00' at end. the first zero is the 21th byte of name which is terminating the string. the next 3 zeros are the padding bytes to next 4-byte border. then the long long number begins. it is 8 bytes long. after that you see the description which is wide (!) characters. you see that each character is followed by a zero character. that is how ascii characters were built in unicode. they keep the same code value but have two bytes now. you see the wide text quite good in the right part. the text stops with 3 zero bytes. the last two of them build the wide character terminator which has two zero bytes. the 'FE' bytes are the rest of the 'description' buffer which is not-initialized memory (probably made by string copy). that doesn't matter since the description orderly was terminated by the zeros. the 'FE' will fill up the 200 byte description. you only see 18 of them at the bottom row but you can see at the top rows how the item record ends. it finally has two zero bytes what is also due to the copy function of the wide string.

your struct size is 136 what means the description is a char buffer.

name is 21 + 3 padding bytes
number is 8 bytes
description is 100 bytes
that is 132 but since 132 is not a multiple of 8 you have 4 padding bytes at end.
so you are calculating with a size of 136.

to fix the thing you should change type of description from 'char' to 'wchar_t' in binaryheader.h

another thing you should fix is the statement (two occurences of the statement exist!!!)

unsigned int recnum_w = foundindex.recnum;

Open in new window


change 'unsigned int' to 'long long'.

also change

if (!ifs.seekg(recsize*recnum)) 

Open in new window


into

if (!ifs.seekg(recnum*recsize))

Open in new window


both changes are in mfcapplication9dlg.cpp.

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Many many thanks Sara.

To the struct like
struct item
{
	char name[21];
	long long number;
	wchar_t description[100];
	bool operator<(const item & it) const
	{
		return (strcmp(name, it.name) < 0);
	}
};

Open in new window

How to specifically change one name, to one given name, and to apply the change to all generated files?

Have a great weekend!
0
HuaMin ChenProblem resolverAuthor Commented:
I mean to do such change within one other project.
0
HuaMin ChenProblem resolverAuthor Commented:
Good day Sara,
this can be the last doubt of me to this thread.
0
sarabandeCommented:
if you want to change a name you have to update the total index file (the one without a number suffix) again, since the all the names in this file need to be sorted alphabetically.

for example if you want to change from 'Bt28UfPl091zzzT32' to 'Ki329Ghpi221aqT' in the index file you will have like

1 AaaaaXfd....
2 AabE2u...
....
x Bt28UfPl091zzzT32
....
y Ki01nojlziwishhszt87
....

position x is the record where the old name was located. position y is the position where the new name needs to get inserted. so, the task is to remove the record at x and move all records from x+1 to y one record back. finally insert the record with the new name at position y which is free since the before record was moved at position y-1. if x and y are exchanged, means the new key is less than the old one, you would move to the other direction.

if done so far the index file is ok. you now could update the item of the data record by changing old name to new name without any movement since the data records are not sorted.

does it make sense to also correct the index files with a number suffix? actually, that is difficult to decide. these index files actualy are only temporary helpers which we created since the savebinaryfile couldn't hold all keys in memory. so you could delete all the numbered files after merge since they are of little value because their contents was merged into the big index file. on the other hand the dialog program was able to read from those as well and if you don't update the files they would contain wrong keys and therefore have no value at all. so, it probably the best you would try to find out which of the numbered files contains the key to be updated, and then correct sorting same as with the total index file.

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
I think it is infeasible to do such change, right?
0
sarabandeCommented:
yes and no.

no, since we used a flat index file with a fixed sort order. these kind of index files are not suitable for updating keys.

yes, since key updates are a basic functionality of databases (and our index files + datafile is a little database).

normally index files were organized in bayer trees (b-tree).

here the records are buckets which contain multiple key records and pointers [p] to other records

record 1:   [2] G [4] P [8] U [9]
record 2:   [] A [] B [3] E [] F []
record 3:   [] C [] [D] []
record 4:   [5] I [6] M [7] O []
record 5:   [] H []          
record 6:   [] J [] K [] L []
record 7:   [] N []
record 8:   [] Q [] R [] S [] T []
record 9:   [10] X [11]
record 10: [] W []
record 11: [] Y [] Z []

you could do a binary search on those buckets as well. for example looking for key = H you would start with record 1 and compare all keys until you find P which is greater than H.  therefore goto record 4 and search for H until I which again is greater than H. go on with record 5 and you find the H.

of course the entries of a bucket would contain whole index_name struct and not only the names.

the advantage of a b-tree over a sorted flat file (array file) is that you (normally) could add and remove single entries to and from bucket and only have to write one or two records. that is since the buckets normally are not full what makes it simple to add one single new entry. and if a bucket contains more than one entry, it is also easy to remove an entry. updating of names therefore simply would remove the entry with the old name and would add a new entry with the new name. only if buckets on the deepest level are full, you would need to add more buckets and have some extra work to do. same applies if you want to "balance" a b-tree what means that you try to have all the records contain nearly the same amount on entries such that the depth of the tree is optimally small and that the tree is fast for searching  and for updates.

note,
Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Many thanks. How about that, I want to update one number value per one given existing name key?
0
sarabandeCommented:
since number value has it own index file as well, there is the same problem to make the index file sorted after updating the number. here is a function that should do such an update. you could add it to binaryfile.cpp.




void updateNumberKey(const std::string & strname, long long newnumber)
{
    std::string strresult; 
    long long foundpos = 0;
    index_name  searchindex = { 0 };
    strcpy_s(searchindex.name, sizeof(searchindex.name), strname.c_str());
    index_name  foundindex = { 0 };
    bool bfound = binarySearch<index_name>("c:\\dp4\\flnames.idx", 
        searchindex, strresult, foundindex, foundpos);
    if (!bfound) return;
    unsigned int recnum_w = foundindex.recnum;
    if (recnum_w == 0) return;
    std::ifstream ifs("c:\\dp4\\flout.dat", std::ios::binary | std::ios::in);  
    long long recpos = recnum_w;
    recpos *= sizeof(rec_struc);        
    if (!bfound) return;
    if (!ifs.seekg(recpos))
    {
        ifs.close();
        return;
    }
    rec_struc datarecord = { 0 };
    if (!ifs.read((char*)&datarecord, sizeof(rec_struc)))
    {
        ifs.close();
        return;
    }
    ifs.close();
    int n;
    for (n = 0; n < NUM_ITEMS; ++n)
        if (strname == datarecord.items[n].name)
            break;
    if (n >= NUM_ITEMS) return;
    index_number searcholdnumber = { 0 };
    index_number searchnewnumber = { 0 };
    index_number foundoldnumber = { 0 };  
    index_number foundnewnumber = { 0 };
    long long foundposold = 0;
    long long foundposnew = 0;
    foundoldnumber.number = datarecord.items[n].number;
    foundnewnumber.number = newnumber;
    // old number must exist
    if (!binarySearch<index_number>("c:\\dp4\\flnumbers.idx", 
        searcholdnumber, strresult, foundoldnumber, foundposold)) return;
    // new number may not exist
    if (binarySearch<index_number>("c:\\dp4\\flnumbers.idx", 
        searchnewnumber, strresult, foundnewnumber, foundposnew)) return;
    // ... but foundnewpos contains position where to insert
    std::fstream indexfile("c:\\dp4\flnumber.idx", std::ios::in | std::ios::out | std::ios::binary);
    int dir = 1;
    if (foundposnew < foundposold) dir = -1;
    foundnewnumber = foundoldnumber;
    foundnewnumber.number = newnumber;
    for (long long pos = foundposold; pos != foundposnew; pos += dir)
    {
        indexfile.seekg((pos+dir) * sizeof(index_number));
        if (!indexfile.read((char*)&foundoldnumber, sizeof(index_number)))
        {
            indexfile.close();
            return;
        }
        indexfile.seekp(pos*sizeof(index_number));
        if (!indexfile.write((char *)&foundoldnumber, sizeof(index_number)))            
        {
            indexfile.close();
            return;
        }
    }
    indexfile.seekp(foundposnew*sizeof(index_number));
    if (!indexfile.write((char *)&foundnewnumber, sizeof(index_number)))            
    {
        indexfile.close();
        return;
    }
    indexfile.close();
    std::ofstream datafile("c:\\dp4\\flout.dat", std::ios::binary | std::ios::out);  
    datafile.seekp(recpos);
    datafile.write((char*)&datarecord, sizeof(rec_struc)); 
    datafile.close();
}

Open in new window


in binaryheader.h you would add a prototype

void updateNumberKey(const std::string & strname, long long newnumber);

Open in new window


and enhance template function binarySearch by an additional argument:

template <class index>
bool binarySearch(const std::string & strindexprefix, const index & searchindex, std::string & strresult, index & foundindex, long long & foundpos)
{
    ...

the 'foundpos' is the record number where an index key was found or where a new index should be inserted. we need this return value for updating the index file with the new number value.

you have to set the foundpos at two locations with

foundpos = nmid;

first, when a key was found above 'return true;'
second, when a key was not found above 'return false;' at end of function binarySearch.

finally you have to add the additional argument to all calls of binarySearch in binaryfile.cpp and mfcapplication9dlg.cpp, for example like

       
 long long foundpos = 0;
        bool bfound = binarySearch<index_number>(strFile, searchindex, strresult, foundindex, foundpos);

Open in new window



note, the code is not tested and probably has some flaws. you could add a button 'Update Number' to the dialog form, and get name key and new number key from existing edit fields. then call the new function. you probably should change 'void' return of the function to 'std::string' return and return result or error message from function updateNumber.

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Many many thanks Sara.

You mean we do adjust the existing Mfc App to do that, right?
If I expect to have another project for such purpose ( which needs number parameters to update the index files), should I create one other Mfc App for this?
0
sarabandeCommented:
yes, you could do so.

you then could focus only on the flout.dat, flname.idx and flnumber.idx.

you can copy parts of the old form to the new form (select multiple controls with the mouse). that way also the ID numbers would be the same, but you would need to use the wizard for to creating members of the new dialog and to create the handler functions. if using as much old names as possible you could copy many of the old code to the new one. you probably also should make a copy of the binaryheader.h and binaryfile.h and add them to new project (tree and folder). alternatively you could copy the binaryheader.h and binaryfile.h to a folder - say binaryhelpers - parallel to the other project folders (remove old files from tree by right-click if already in the project, then right-click at project in tree and choose 'add ... existing item ...' at , navigate to folder of binaryheader and binaryfile, select them both and add them to project. change '#include "binaryheader.h" ' by '#include "..\binaryhelpers\binaryheader.h" ' everywhere.)

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Many thanks Sara.
There should be also codes to "refresh" all index files, after the change to the number keys, right?
0
sarabandeCommented:
since the numbered index files are all merged to the total index file, it is not necessary to 'update' their entries. the new program only should care for the 3 big files. you also wouldn't need the radio box controls to decide which file to evaluate but simply use input fields for key, number, record, item number such that the new functions you want to implement can be parameterized. instead of using a big output window you also could have output controls for the results you found. use buttons to invoke the functions you need.

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Many thanks Sara.

there should be no "foundpos" parameter to call binarysearch, can you please confirm?
0
sarabandeCommented:
you should add a long long return argument to binarySearch function for the new update function. the argument would take the 'nmid' variable to be returned to caller. the nmid is the record of the index file where a found entry was located or where a new key has to be inserted. see above. if you make a new project and use a copy of the binary helper sources you could do it only for the new project. if you want to share the binary sources between projects you should add it generally. see my comment above where all steps to do were described.

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Thanks. It means if the number is not found, we're doing insert for the new given number key, right?
0
sarabandeCommented:
as explained above, for updating the index file we need the record (number) where the old key (name or number) was in and the record where the new key should be inserted such the sorting is still correct. all records between must be moved by one record up or down depending on whether the new key is greater or less than the old key. the last value of 'nmid' before the loop breaks is exactly this record and we have to return it to the caller such that the move operations could be performed.

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Many thanks Sara.
Can I have more details to what the new argument is doing, within Binarysearch?
0
sarabandeCommented:
actually i have explained it twice and very detailed. so it rarely makes sense to repeat myself again. look at the code of function updateNumber where i used the found positions:

    // old number must exist
    if (!binarySearch<index_number>("c:\\dp4\\flnumbers.idx",
        searcholdnumber, strresult, foundoldnumber, foundposold)) return;
    // new number may not exist
    if (binarySearch<index_number>("c:\\dp4\\flnumbers.idx",
        searchnewnumber, strresult, foundnewnumber, foundposnew)) return;
    // ... but foundnewpos contains position where to insert
    std::fstream indexfile("c:\\dp4\flnumber.idx", std::ios::in | std::ios::out | std::ios::binary);
    int dir = 1;
    if (foundposnewfoundposold) dir = -1;
    foundnewnumber = foundoldnumber;
    foundnewnumber.number = newnumber;
    for (long long pos = foundposold; pos != foundposnew; pos += dir)
    {
        indexfile.seekg((pos+dir) * sizeof(index_number));
        if (!indexfile.read((char*)&foundoldnumber, sizeof(index_number)))
        {
            indexfile.close();
            return;
        }
        indexfile.seekp(pos*sizeof(index_number));
        if (!indexfile.write((char *)&foundoldnumber, sizeof(index_number)))            
        {
            indexfile.close();
            return;
        }
    }
    indexfile.seekp(foundposnew*sizeof(index_number));
    if (!indexfile.write((char *)&foundnewnumber, sizeof(index_number)))            

Sara
0
HuaMin ChenProblem resolverAuthor Commented:

you have to set the foundpos at two locations with

foundpos = nmid;

first, when a key was found above 'return true;'
second, when a key was not found above 'return false;' at end of function binarySearch.

finally you have to add the additional argument to all calls of binarySearch in binaryfile.cpp and mfcapplication9dlg.cpp, for example like
Many thanks Sara.
I've done the changes but I've got these
Error	1	error C2664: 'bool binarySearch<index_name>(const std::string &,const index &,std::string &,index &,index &)' : cannot convert argument 5 from '__int64' to 'index_name &'	c:\mfcapplication9 150705\mfcapplication9\binaryfile.cpp	31	1	MfcApplication9
Error	2	error C2664: 'bool binarySearch<index_number>(const std::string &,const index &,std::string &,index &,index &)' : cannot convert argument 5 from '__int64' to 'index_number &'	c:\mfcapplication9 150705\mfcapplication9\binaryfile.cpp	66	1	MfcApplication9
Error	3	error C2664: 'bool binarySearch<index_number>(const std::string &,const index &,std::string &,index &,index &)' : cannot convert argument 5 from '__int64' to 'index_number &'	c:\mfcapplication9 150705\mfcapplication9\binaryfile.cpp	69	1	MfcApplication9

Open in new window

0
sarabandeCommented:
the 5th argument in binarySearch function is 'long long &' not 'index &'.

Sara
0
HuaMin ChenProblem resolverAuthor Commented:
Sorry, I still get these

Error	1	error C2143: syntax error : missing ';' before ','	c:\mfcapplication9 150705\mfcapplication9\binaryfile.cpp	132	1	MfcApplication9
Error	2	error C2143: syntax error : missing ';' before '{'	c:\mfcapplication9 150705\mfcapplication9\binaryfile.cpp	134	1	MfcApplication9
	3	IntelliSense: expected an expression	c:\MfcApplication9 150705\MfcApplication9\BinaryFile.cpp	132	3	MfcApplication9

Open in new window

0
sarabandeCommented:
please post lines 120 - 140 of binaryfile.cpp

Sara
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.