如何遍历 CString 并将其字符与 int 进行比较?
How can I iterate over CString and compare its characters to int?
我在 Visual Studio 2017 年用 C++ 编写了一个基于对话框的 MFC 应用程序。在对话框中,我添加了一个列表控件,用户可以在其中更改单元格的值,如下图所示:
在他更改值后,我想检查这些值是否有效(这样如果他不小心按错了按钮,他会收到通知)。为此,我遍历列表的不同单元格,并从每个单元格中提取写入其中的文本到 CString
类型变量中。我想检查这个变量是否只有 8 个字符,即“1”或“0”。我编写的代码的问题是,当我尝试打印 CString
变量的不同字符时,我得到了奇怪的值。
校验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;
}
}
}
}
当我尝试打印变量 value
的一个字符时,消息框中打印的内容的图片。我希望看到“1”,但我在消息框中看到“1iiiiii”:
我试过直接从 CString
类型的变量 cvalue
中提取字符,如下所示:
cvalue[i]
这是我用
得到的长度
strlen(cvalue[i])
但我得到了相同的结果。我还尝试访问 CString
类型的变量 cvalue
中的字符,如下所示:
cvalue.GetAt(i)
并使用以下方法获取长度:
cvalue.GetLength()
但同样,我得到了相同的结果。
也许有人可以告诉我如何检查 CString
类型的变量 cvalue
中的字符是“0”还是“1”?
谢谢。
正如您在最后一段中所写,“检查 CString
类型的变量 cvalue
中的字符是 '0'
还是 '1'
?”。
就是这样。 '0'
是字符 0。但是您检查整数 0
,它等于字符 '[=16=]'
。那是 end-of-string 字符。
在这种情况下,您不需要使用 std::string
来处理您的字符串:CString
工作正常。
假设您的 CString cvalue
是您要检查的字符串,您可以编写一个简单的循环,如下所示:
// 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"));
}
}
在你的案例中输出明显奇怪的原因是你传递了一个指向 not 后跟 null-terminator:[=29 的字符的指针=]
// Wrong code
char c = value[i];
MessageBox(&c, "value");
如果您不想像我在前面的示例代码中所做的那样使用包含违规字符的格式化消息构建 CString
,另一种方法是创建一个简单的原始 char
存储要输出的字符的数组,后跟 null-terminator:
// This is an array storing two chars: value[i] followed by '[=12=]' (null)
char s[2] = {value[i], '[=12=]'};
MessageBox(s, "value");
P.S.
我在我的代码示例中使用 TCHAR
而不是 char
,以使代码更容易移植到 Unicode 构建。将 TCHAR
视为预处理器宏,它映射到 char
用于 ANSI/MBCS 构建(这似乎是您当前的情况),并映射到 wchar_t
用于 Unicode 构建。
关于验证用户输入的简要说明
通过上述回答,我试图通过 CString
字符验证来严格解决您的具体问题。但是,如果你能从更广阔的角度来看,我肯定会考虑 validating 用户输入 before 将其存储在 list-view 控制。例如,您可以处理来自 list-view 控件的 LVN_ENDLABELEDIT
notification,并拒绝无效的输入值。
或者,考虑到每个位的唯一有效值是 0 和 1,您可以让用户 select 他们来自 combo-box。
从 MFC 的 CListCtrl
开始这样做是 non-trivial 的工作;因此,您也可以考虑使用其他 open-source 控件,例如 CGridListCtrlEx
control available from CodeProject.
我在 Visual Studio 2017 年用 C++ 编写了一个基于对话框的 MFC 应用程序。在对话框中,我添加了一个列表控件,用户可以在其中更改单元格的值,如下图所示:
在他更改值后,我想检查这些值是否有效(这样如果他不小心按错了按钮,他会收到通知)。为此,我遍历列表的不同单元格,并从每个单元格中提取写入其中的文本到 CString
类型变量中。我想检查这个变量是否只有 8 个字符,即“1”或“0”。我编写的代码的问题是,当我尝试打印 CString
变量的不同字符时,我得到了奇怪的值。
校验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;
}
}
}
}
当我尝试打印变量 value
的一个字符时,消息框中打印的内容的图片。我希望看到“1”,但我在消息框中看到“1iiiiii”:
我试过直接从 CString
类型的变量 cvalue
中提取字符,如下所示:
cvalue[i]
这是我用
得到的长度strlen(cvalue[i])
但我得到了相同的结果。我还尝试访问 CString
类型的变量 cvalue
中的字符,如下所示:
cvalue.GetAt(i)
并使用以下方法获取长度:
cvalue.GetLength()
但同样,我得到了相同的结果。
也许有人可以告诉我如何检查 CString
类型的变量 cvalue
中的字符是“0”还是“1”?
谢谢。
正如您在最后一段中所写,“检查 CString
类型的变量 cvalue
中的字符是 '0'
还是 '1'
?”。
就是这样。 '0'
是字符 0。但是您检查整数 0
,它等于字符 '[=16=]'
。那是 end-of-string 字符。
在这种情况下,您不需要使用 std::string
来处理您的字符串:CString
工作正常。
假设您的 CString cvalue
是您要检查的字符串,您可以编写一个简单的循环,如下所示:
// 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"));
}
}
在你的案例中输出明显奇怪的原因是你传递了一个指向 not 后跟 null-terminator:[=29 的字符的指针=]
// Wrong code
char c = value[i];
MessageBox(&c, "value");
如果您不想像我在前面的示例代码中所做的那样使用包含违规字符的格式化消息构建 CString
,另一种方法是创建一个简单的原始 char
存储要输出的字符的数组,后跟 null-terminator:
// This is an array storing two chars: value[i] followed by '[=12=]' (null)
char s[2] = {value[i], '[=12=]'};
MessageBox(s, "value");
P.S.
我在我的代码示例中使用 TCHAR
而不是 char
,以使代码更容易移植到 Unicode 构建。将 TCHAR
视为预处理器宏,它映射到 char
用于 ANSI/MBCS 构建(这似乎是您当前的情况),并映射到 wchar_t
用于 Unicode 构建。
关于验证用户输入的简要说明
通过上述回答,我试图通过 CString
字符验证来严格解决您的具体问题。但是,如果你能从更广阔的角度来看,我肯定会考虑 validating 用户输入 before 将其存储在 list-view 控制。例如,您可以处理来自 list-view 控件的 LVN_ENDLABELEDIT
notification,并拒绝无效的输入值。
或者,考虑到每个位的唯一有效值是 0 和 1,您可以让用户 select 他们来自 combo-box。
从 MFC 的 CListCtrl
开始这样做是 non-trivial 的工作;因此,您也可以考虑使用其他 open-source 控件,例如 CGridListCtrlEx
control available from CodeProject.