std::map {'0',0} 对在字符 '0' 用作查找时导致逻辑错误
std::map {'0',0} pair causes logic error when the char '0' is used as a lookup
我创建了一个使用 char 和 int 映射的函数,这样当一个数字作为字符串传递时,我可以检查每个字符以确保它是一个 int。然后我获取该字符串并将其转换为纯 int。出于某种原因,当它检查“0”时,它会在找到时抛出错误。我知道有更好的方法可以做到这一点,而且我已经在我的大型项目中实施了很多。关于正在发生的事情,这是一个纯粹的学术问题。
main.cpp
#include <iostream>
#include <string>
#include <map>
class Logic {
public:
Logic();
std::map <char, int> IsNumber;
bool CheckForInterger(std::string);
int StringToInt(std::string);
};
Logic::Logic() {
IsNumber = { { '0',0 },{ '1',1 },{ '2',2 },{ '3',3 },{ '4',4 },{ '5',5 },
{ '6',6 },{ '7',7 },{ '8',8 },{ '9',9 } };
}
bool Logic::CheckForInterger(std::string word) {
for (char character : word) {
if (IsNumber[character]) {
//do nothing and check next char
}
else {
std::cout << "\n\"" << character << "\" is not a Number.\n\n";
return true;
}
}
return false;
}
int Logic::StringToInt(std::string word) {
int number;
number = std::stoi(word, nullptr, 10);
return number;
}
int main() {
Logic ThisRound;
bool notint;
bool quit = false;
std::string newnumber;
do {
do {
std::cout << "Enter a number: ";
std::getline(std::cin, newnumber);
std::cout << std::endl;
notint = ThisRound.CheckForInterger(newnumber);
} while (notint);
int newint = ThisRound.StringToInt(newnumber);
std::cout << "Your int is: " << newint << std::endl;
std::cout << "Enter Another y/n: ";
std::string choice;
std::getline(std::cin, choice);
std::cout << std::endl;
quit = (choice == "y") ? true : false;
} while (quit);
return 0;
}
您应该只使用 isdigit(character)
而不是 IsNumber[character]
。根本不需要 IsNumber
地图。
给定的map::operator[]
key
returns 值与之关联。因此,对于 isNumber['0']
它 returns 0
和对于 isNumber['5']
returns 5
等。在 if
语句的上下文中,任何非零值都被视为 true
,零被视为 false
.
如果 map::operator[]
找不到 key
,它会创建一个具有值类型默认构造函数的新条目。在您的情况下,isNumber['a']
将在您的 IsNumber
映射中创建一个默认值为 0 的新条目。因此,isNumber['a']
和 isNumber['0']
变得无法区分(无需进一步修改 IsNumber
)
您可能想要做的是仅检查给定键是否在映射中,如果失败则不修改映射。为此,您想改用 map::find()
函数。它 returns 一个 map::iterator
它找到的元素,或者一个值 map::end()
如果它失败了。因此你可以写:
if (IsNumber.find(character) != IsNumber.end() ) {
//do nothing and check next char
}
我创建了一个使用 char 和 int 映射的函数,这样当一个数字作为字符串传递时,我可以检查每个字符以确保它是一个 int。然后我获取该字符串并将其转换为纯 int。出于某种原因,当它检查“0”时,它会在找到时抛出错误。我知道有更好的方法可以做到这一点,而且我已经在我的大型项目中实施了很多。关于正在发生的事情,这是一个纯粹的学术问题。
main.cpp
#include <iostream>
#include <string>
#include <map>
class Logic {
public:
Logic();
std::map <char, int> IsNumber;
bool CheckForInterger(std::string);
int StringToInt(std::string);
};
Logic::Logic() {
IsNumber = { { '0',0 },{ '1',1 },{ '2',2 },{ '3',3 },{ '4',4 },{ '5',5 },
{ '6',6 },{ '7',7 },{ '8',8 },{ '9',9 } };
}
bool Logic::CheckForInterger(std::string word) {
for (char character : word) {
if (IsNumber[character]) {
//do nothing and check next char
}
else {
std::cout << "\n\"" << character << "\" is not a Number.\n\n";
return true;
}
}
return false;
}
int Logic::StringToInt(std::string word) {
int number;
number = std::stoi(word, nullptr, 10);
return number;
}
int main() {
Logic ThisRound;
bool notint;
bool quit = false;
std::string newnumber;
do {
do {
std::cout << "Enter a number: ";
std::getline(std::cin, newnumber);
std::cout << std::endl;
notint = ThisRound.CheckForInterger(newnumber);
} while (notint);
int newint = ThisRound.StringToInt(newnumber);
std::cout << "Your int is: " << newint << std::endl;
std::cout << "Enter Another y/n: ";
std::string choice;
std::getline(std::cin, choice);
std::cout << std::endl;
quit = (choice == "y") ? true : false;
} while (quit);
return 0;
}
您应该只使用 isdigit(character)
而不是 IsNumber[character]
。根本不需要 IsNumber
地图。
给定的map::operator[]
key
returns 值与之关联。因此,对于 isNumber['0']
它 returns 0
和对于 isNumber['5']
returns 5
等。在 if
语句的上下文中,任何非零值都被视为 true
,零被视为 false
.
如果 map::operator[]
找不到 key
,它会创建一个具有值类型默认构造函数的新条目。在您的情况下,isNumber['a']
将在您的 IsNumber
映射中创建一个默认值为 0 的新条目。因此,isNumber['a']
和 isNumber['0']
变得无法区分(无需进一步修改 IsNumber
)
您可能想要做的是仅检查给定键是否在映射中,如果失败则不修改映射。为此,您想改用 map::find()
函数。它 returns 一个 map::iterator
它找到的元素,或者一个值 map::end()
如果它失败了。因此你可以写:
if (IsNumber.find(character) != IsNumber.end() ) {
//do nothing and check next char
}