out_of_range at memory location c++
out_of_range at memory location c++
在这个程序中,用户在命令行中输入两个字符串。其中一个是数字,另一个是字符串。该程序旨在根据电话拨号盘每个按钮上的数字/字母来检查输入的数字和字符串是否相等。我得到了一个例外,上面写着:
Unhandled exception at 0x775DDAE8 in Project10.exe: Microsoft C++ exception: std::out_of_range at memory location 0x0018F158.
非常感谢您的帮助:)
using namespace std;
bool checkPswd(string keyStrokes, string password) {
string temp;
string temp2;
bool temporary = 1;
string phoneButtons[10] = {
"", ""
"abc", "def", "ghi", "jkl",
"mno", "pqrs", "tuv", "wxyz"
};
for (int i = 0; i < keyStrokes.length(); i++) {
for (int j = 2; j < 10; j++) {
for (int k = 0; k < phoneButtons[j].length(); k++) {
temp = phoneButtons[j];
if (password.at(k) == temp.at(k)) {
temp2 = +(char)k;
}
else {
//do nothing
}
}
}
}
cout << temp2;
for (int m = 0; m < temp2.length(); m++) {
if (temp2.at(m) == keyStrokes.at(m)) {
//keep searching
}
else {
return 0;
}
}
return 1;
}
int main(int argc, char ** argv) {
if (argc != 3) {
cout << "Please input the key strokes from the phone and the password." << endl;
return 1;
}
string keyStrokes = argv[1];
string password = argv[2];
bool check;
check = checkPswd(keyStrokes, password);
if (check) {
cout << "Password Verified" << endl;
}
else {
cout << "Wrong Password" << endl;
}
return 0;
}
for (int k = 0; k < phoneButtons[j].length(); k++) {
k将在这里从0迭代到比`phoneButtons[j]中的字符数少1
if (password.at(k) // ... rest of the code is irrelevant
流行问答:如果password
的字符比phoneButtons[j]
少,你认为这里会发生什么?
for (int m = 0; m < temp2.length(); m++) {
if (temp2.at(m) == keyStrokes.at(m)) {
这里也有同样的bug。我还没有分析显示的代码的其他部分是否出现了相同的逻辑错误。
这就是为什么应该使用#include <algorithm>
,而不是使用这些容易出错的C样式for
循环。std::find()
比这种基于C风格循环的搜索更不容易出错。
问题的原因
手动循环多个数组并从中读取是很容易出错的。
- 您的循环不断覆盖
temp2
,而不是附加到它 - 稍后,您的代码假设
temp2
与keystrokes
的长度相同
这就是为什么你没有像以前那样"手工"做。很难完美地跟踪所有内容,也很难始终知道访问给定索引是安全的。
更好的方法
一个更好的方法是制作一个将一件事转换为另一件事的函数。您可以使用迭代器来实现一种非常通用的方法。迭代器可以引用许多数据结构,甚至可以读取/写入流。它非常灵活。
由于编译器可以"看到一切"并了解所有类型的一切,因此它可以生成非常安全的高效代码。
这里是一个基于迭代器的实现,它将字符转换为数字,然后比较数字。
现场演示
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
template<
typename InputIt,
typename OutputIt,
typename V = typename std::iterator_traits<InputIt>::value_type,
typename OutTag = typename std::iterator_traits<OutputIt>::iterator_category,
typename = typename std::enable_if<
std::is_same<OutTag, std::output_iterator_tag>::value>::type
>
OutputIt convertToDigits(InputIt st, InputIt en, OutputIt dest)
{
using ButtonPair = std::pair<char, int>;
using ButtonLookup = std::vector<ButtonPair>;
static ButtonLookup lookup{
{ 'a', 2 }, { 'b', 2 }, { 'c', 2 },
{ 'd', 3 }, { 'e', 3 }, { 'f', 3 },
{ 'g', 4 }, { 'h', 4 }, { 'i', 4 },
{ 'j', 5 }, { 'k', 5 }, { 'l', 5 },
{ 'm', 6 }, { 'n', 6 }, { 'o', 6 },
{ 'p', 7 }, { 'q', 7 }, { 'r', 7 }, { 's', 7 },
{ 't', 8 }, { 'u', 8 }, { 'v', 8 },
{ 'w', 9 }, { 'x', 9 }, { 'y', 9 }, { 'z', 9 }
};
auto ls = std::begin(lookup);
auto le = std::end(lookup);
std::for_each(st, en, [&](char c) {
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
auto m = std::find_if(ls, le, [&](auto const& p) {
return p.first == c;
});
if (m != le)
*dest++ = m->second;
});
return dest;
}
int main(int argc, char **argv)
{
if (argc != 3)
return 1;
std::vector<std::string> args(argv, argv + argc);
std::string const& numbers = args.at(1);
std::string const& characters = args.at(2);
std::cout << " Chars: "" << characters << '"' << std::endl;
std::cout << " Check: "" << numbers << '"' << std::endl;
std::vector<int> digits;
convertToDigits(std::begin(characters), std::end(characters),
std::back_inserter(digits));
for (int& digit : digits)
digit += '0';
std::cout << "Expect: "" << std::string(
std::begin(digits), std::end(digits)) << '"' << std::endl;
bool match = std::equal(std::begin(numbers), std::end(numbers),
std::begin(digits), std::end(digits));
return !match;
}
它的工作原理
convertToDigits
采用一对迭代器,指代要转换的范围的开始和结束。第三个参数是输出迭代器,用于存储输出。
main
函数为数字int
值设置一个vector
,并使用std::back_inserter
生成一个输出迭代器,每次存储向量时对其执行push_back
。
翻译器函数只是在查找表中进行线性搜索。我选择了线性搜索,因为列表太小了。它将被紧密地封装在内存中,并且开销非常低。无论如何,速度在这里无关紧要。它是瞬间的。
我将'0'
添加到数字值中以将其转换为ASCII,因此它们与命令行字符串相当。
剩下的是显而易见的,看看转换后的字符串是否与期望的字符串匹配,如果匹配,则使用0退出代码退出。
- 将数组信息存储到 c++ 向量中有一个"Access violation reading location"
- 例外:'Access violation reading location'
- 我在发布模式下运行时收到"Access violation reading location"错误 - C++
- 我在 C++ "out_of_range at memory location"有问题
- 链接器错误:"cannot move location counter backwards (from 200009f8 to 20000800)"
- FLEX/BISON在不同的文件夹中生成location.hh,position.hh,stack.hh
- 如何修复我的 c++ 毕达哥拉斯三重查找器中的'access violation reading location'错误?
- 矩阵 - "Access violation writing location 0x00900B0C" - C++ 中的错误
- Memcpy to mallocd location
- 如何修复此代码中的'Access violation reading location'
- Glgetuniform -location以外的采样器返回-1
- c++:链表错误" Access violation reading location"
- out_of_range at memory location c++
- msftedit "Access violation reading location 0x00000008"错误.dll SetWindowSub类中的RichEdit控件
- CreateBuffer 抛出一个"Access violation reading location"
- 如何找出导致"cv::Exception at memory location"的原因?
- 指针已初始化,但我有错误"Access violation reading location 0xCCCCCCCC".为什么?
- 序列化时"Access violation reading location 0xcdcdcdfd"
- Box2D 和 dll "Access violation reading location"
- Visual Studio 调试器的奇怪行为; "The network location cannot be reached" (ERROR_NETWORK_UNREACHABLE)