我正在进行自我练习。参数是允许用户输入存储在向量中的名称。打印矢量中的名称列表可为您提供每个名称的位置。您可以选择通过提供名称的位置来加密列表中的名称。加密会将名称中的每个字母与另一个字符串(名称允许的字母)进行比较。当它找到字母表中的字母时,会从另一串随机字符中提取相应的字符,并将新字符分配到同一位置。
使用基于范围的for循环,我几乎可以正常工作了。通过添加输出语句,我可以看到代码正确地将名称的字符与允许的字母进行比较,并在加密密钥中找到相应的值。但是,当循环完成并再次打印名称列表时,要加密的名称中的字符将保持不变。
尝试解决该问题,我已注释掉基于for循环的范围,并尝试使用传统的for循环执行相同的操作。有了这段代码,我在加密过程中出错了:
位置1 A与@相同 抛出'std :: out_of_range'实例后调用终止 what():vector :: _ M_range_check:__n(26)> = this-> size()(2)
“位置1 A与@相同” 行是我添加的调试输出,以表明代码能够找到正确的字符串,字符串中的字母以及他们键入相应的字母。
对于理解我为什么会得到这些错误的任何帮助,将不胜感激。
这是我的代码:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
// Declare strings for Encryption and Decryption
string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "};
string key {"mnbvfghytcqwi1234567890`~!@#$%^&*()-=_+[]\{}|;':,./<>?"};
//Declare collection of names for the list
vector <string> names {};
//Declare character to hold the user menu selection
char selection {};
string user_input{};
string banner (50, '=');
//Print menu
do
{
cout << "\n" << banner << endl;
cout << "A - Add name to list" << endl;
cout << "P - Print all names in list" << endl;
cout << "E - Encrypt a name in the list" << endl;
cout << "D - Decrypt a name in the list" << endl;
cout << "S - Show details of a name in the list" << endl;
cout << "C - Clear all names in the list" << endl;
cout << "Q - Quit" << endl;
cout << banner << endl;
cout << "Selection: ";
getline(cin, user_input);
if (user_input.size() != 1)
{
cout << "Error 4: Menu selection must be a single character" << endl;
selection = '1';
}
else
{
for (auto c: user_input)
{
if (!isalpha(c))
{
cout << "Error 5: Menu selection must be an alphabetic character" << endl;
selection = '1';
}
else
selection = c;
}
}
// cin >> selection;
// cin.clear();
// cin.sync();
switch (selection)
{
case 'a':
case 'A':
{
string temp_name{};
bool invalid_name {false};
cout << "Enter full name: ";
getline(cin, temp_name);
if (!isalpha(temp_name[0]))
cout << "Error 2: Names must begin with an alphabetic character" << endl << endl;
else
{
for (auto c: temp_name)
{
if (!isalpha(c) && !isspace(c) && c != '-')
{
invalid_name = true;
break;
}
else
invalid_name = false;
}
if (invalid_name)
cout << "Error 3: Name contains invalid characters" << endl << endl;
else
{
temp_name.at(0) = toupper (temp_name.at(0));
for (size_t i {1}; i < temp_name.size(); i++)
{
size_t position{i-1};
if (isspace(temp_name.at(position)) || temp_name.at(position) == '-')
{
temp_name.at(i) = toupper(temp_name.at(i));
}
}
names.push_back(temp_name);
cout << "Added name #" << names.size() << endl;
}
}
break;
}
case 'p':
case 'P':
{
for (size_t i {0}; i < names.size(); i++)
cout << i+1 << ". " << names.at(i) << endl;
break;
}
case 'e':
case 'E':
{
size_t encrypt_input{}, key_position{}, name_position {}, name_size {};
cout << "Enter the position of the name to encrypt: ";
cin >> encrypt_input;
cin.clear();
cin.sync();
if (encrypt_input < 1 || encrypt_input > names.size())
cout << "Error 6: Invalid selection for name to encrypt" << endl << endl;
else
{
name_position = encrypt_input - 1;
name_size = names.at(name_position).size();
cout << "Encrypting name: " << names.at(name_position) << " of size " << name_size << endl << endl;
cout << "Position 1 " << names.at(name_position).at(0) << " is the same as ";
key_position = alphabet.find(names.at(name_position).at(0));
cout << key.at(key_position) << endl;
for (size_t i {0}; i < name_size; i++)
{
key_position = alphabet.find(names.at(name_position).at(i));
cout << "Finding " << names.at(key_position).at(i) << " in key at position " << key_position << endl;
cout << "Found encryption value of " << key.at(key_position) << " at position " << key_position << endl;
cout << "Changing " << names.at(key_position).at(i) << " to " << key.at(key_position) << endl;
names.at(name_position).at(i) = key.at(key_position);
}
/*
for (auto c: names.at(encrypt_input-1))
{
cout << "Converting " << c << " to ";
key_position = alphabet.find(c);
cout << key.at(key_position) << endl;
c = key.at(key_position);
cout << "C is now " << c << endl << endl;
}
*/
}
cout << names.at(encrypt_input-1) << endl;
break;
}
case 'q':
case 'Q':
cout << "Goodbye" << endl << endl;
break;
default:
cout << "Error 1: Invalid menu selection" << endl << endl;
break;
}
} while (selection != 'Q' && selection != 'q');
return 0;
}
答案 0 :(得分:0)
欢迎来到Stackoverflow!我完全同意PaulMcKenzie的观点,这么大的功能并不是出于各种原因才是最好的-直接的原因是它难以阅读且难以发现问题-但还有更多原因。
已经说过,您在E
案例中发现了一个错误。
for (size_t i {0}; i < name_size; i++)
{
key_position = alphabet.find(names.at(name_position).at(i));
cout << "Finding " << names.at(key_position).at(i) << " in key at position " << key_position << endl;
cout << "Found encryption value of " << key.at(key_position) << " at position " << key_position << endl;
cout << "Changing " << names.at(key_position).at(i) << " to " << key.at(key_position) << endl;
names.at(name_position).at(i) = key.at(key_position);
}
应该是
for (unsigned int i{ 0 }; i < name_size; i++)
{
key_position = alphabet.find(names.at(name_position).at(i));
cout << "Finding " << names.at(name_position).at(i) << " in key at position " << key_position << endl;
cout << "Found encryption value of " << key.at(key_position) << " at position " << key_position << endl;
cout << "Changing " << names.at(name_position).at(i) << " to " << key.at(key_position) << endl;
names.at(name_position).at(i) = key.at(key_position);
}
即key_position
在2个地方应为name_position
。
可能还有其他错误,但这应该可以避免崩溃并正确进行编码。
编辑:应OP的要求添加了一个新的代码片段。
int i = 0; // position counter
for (auto c: names.at(encrypt_input-1))
{
cout << "Converting " << c << " to ";
key_position = alphabet.find(c);
cout << key.at(key_position) << endl;
c = key.at(key_position);
cout << "C is now " << c << endl << endl;
names.at(name_position).at(i++) = c; // update the names variable.
}
这应该可以解决您在自动循环中提到的问题。
答案 1 :(得分:0)
您正在访问names
向量的无效位置,并且错误/异常显示该错误。
执行此操作时:
names.at( key_position ).at( i )
// ^^^
// It should be name_position
在此声明中
cout << "Finding " << names.at( key_position ).at( i ) << " in key at position " << key_position << endl;
您正在访问names
的无效索引,而该索引应该是:
names.at( name_position ).at( i )
,那将起作用,因为它访问有效的索引。
您在此声明中也犯了同样的错误:
cout << "Changing " << names.at( key_position ).at( i ) << " to " << key.at( key_position ) << endl;
更正这些,它应该可以工作!
提示:
是时候阅读How to debug small programs。
它可以帮助您更系统地找出程序的问题。
关于您的代码组织的一般几点:
main
函数混乱。case
语句中编写与每个switch
相对应的函数,例如addName()
,encryptName()
,decryptName()
等希望有帮助!
祝你好运!
编码愉快!