简体   繁体   中英

How can I iterate over CString and compare its characters to int?

I'm writing a dialog based MFC application in Visual Studio 2017 in C++. In the dialog I added a list control where the user can change the values of the cells as shown in the picture below: 在此处输入图片说明

after he changes the values, I want to check if those values are valid (so if he accidentally pressed the wrong button he will be notified). For this purpose I'm iterating over the different cells of the list and from each cell I extract the text which is written in it into a CString type variable. I want to check that this variable has only 8 characters which are '1' or '0'. The problem with the code I've written is that I get weird values when I try to print the different characters of the CString variable.

The Code for checking the validity of the CString :

void CEditableListControlDlg::OnBnClickedButton4()
{
    // TODO: Add your control notification handler code here

    // Iterate over the different cells
    int bit7Col = 2;
    int bit6Col = 3;
    int bit5Col = 4;
    int bit4Col = 5;
    int bit3Col = 6;
    int bit2Col = 7;
    int bit1Col = 8;
    int bit0Col = 9;

    for (int i = 0; i < m_EditableList.GetItemCount(); ++i) {
        CString bit7 = m_EditableList.GetItemText(i, bit7Col);
        CString bit6 = m_EditableList.GetItemText(i, bit6Col);
        CString bit5 = m_EditableList.GetItemText(i, bit5Col);
        CString bit4 = m_EditableList.GetItemText(i, bit4Col);
        CString bit3 = m_EditableList.GetItemText(i, bit3Col);
        CString bit2 = m_EditableList.GetItemText(i, bit2Col);
        CString bit1 = m_EditableList.GetItemText(i, bit1Col);
        CString bit0 = m_EditableList.GetItemText(i, bit0Col);      

        CString cvalue = bit7 + bit6 + bit5 + bit4 + bit3 + bit1 + bit0;
        
        std::string value((LPCSTR)cvalue);

        int length = value.length();

        if (length != 7) {
            MessageBox("Register Value Is Too Long", "Error");
            return;
        }

        
        for (int i = 0; i < length; i++) {
            if (value[i] != static_cast<char>(0) || value[i] != static_cast<char>(1)) {
                    char c = value[i];
                    MessageBox(&c, "value"); // this is where I try to print the value
                    return;
            }
        }
    }
}

Picture of what get's printed in the message box when I try to print one character of the variable value . I expect to see '1' but instead I see in the message box '1iiiiii`: 在此处输入图片说明

I've tried extracting the characters directly from the variable cvalue of type CString like this:

cvalue[i]

and it's length I got by using

strlen(cvalue[i])

but I've got the same result. I've also tried accessing the characters in the variable cvalue of type CString as follows:

cvalue.GetAt(i)

and to get it's length by using: cvalue.GetLength()

But again, I've got the same results.

Perhaps anyone could advice me how can I check that the characters in the variable cvalue of type CString are '0' or '1'?

Thank you.

You don't need to use std::string to process your strings in this case: CString works fine.

Assuming that your CString cvalue is the string you want to check, you can write a simple loop like this:

// Check cvalue for characters different than '0' and '1'
for (int i = 0; i < cvalue.GetLength(); i++)
{
    TCHAR currChar = cvalue.GetAt(i);
    if ((currChar != _T('0')) && (currChar != _T('1')))
    {
        CString message;
        message.Format(_T("Invalid character at position %d : %c"), i, currChar);
        MessageBox(message, _T("Error"));
    }
}

The reason for the apparently weird output in your case is that you are passing a pointer to a character that is not followed by a null-terminator:

// Wrong code
char c = value[i];
MessageBox(&c, "value");

If you don't want to build a CString with a formatted message containing the offending character, like I did in the previous sample code, an alternative could be creating a simple raw char array storing the character you want to output followed by the null-terminator:

// This is an array storing two chars: value[i] followed by '\0' (null)
char s[2] = {value[i], '\0'};

MessageBox(s, "value");

PS I used TCHAR in my code sample instead of char , to make the code more easily portable to Unicode builds. Think of TCHAR as a preprocessor macro that maps to char for ANSI/MBCS builds (which seems your current case), and to wchar_t for Unicode builds.


A Brief Note on Validating User Input

With the above answer, I tried to strictly address your specific problem with CString character validation. But, if you can take a look from a broader perspective, I would definitely consider validating the user input before storing it in the list-view control. For example, you could handle the LVN_ENDLABELEDIT notification from the list-view control, and reject invalid input values.

Or, considering that the only valid values for each bit are 0 and 1, you could let the user select them from a combo-box .

Doing that starting from the MFC's CListCtrl is non-trivial work; so, you may also consider using other open-source controls, like this CGridListCtrlEx control available from CodeProject .

As you write in your last paragraph, "check that the characters in the variable cvalue of type CString are '0' or '1' ?".

That's exactly how. '0' is the character 0. But you check for the integer 0 , which is equal to the character '\\0' . That's the end-of-string character.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM