C++ 异常:字符串下标超出范围
我只是尝试编写一个简单的基于控制台的登录代码,而我被指定隐藏用户的密码,我编写了代码,但我在调试时遇到异常错误。我尝试了一些方法来解决它,但是失败了,不知道该怎么办。代码似乎有点混乱。我也尝试了所有的方法 及 也没有找到解决办法。所以,在这个问题上我需要帮助 编辑:当我使用固定大小的字符数组时,它工作得很好,但由于它的固定大小和内存问题,我在C++ 异常:字符串下标超出范围,c++,string,exception,C++,String,Exception,我只是尝试编写一个简单的基于控制台的登录代码,而我被指定隐藏用户的密码,我编写了代码,但我在调试时遇到异常错误。我尝试了一些方法来解决它,但是失败了,不知道该怎么办。代码似乎有点混乱。我也尝试了所有的方法 及 也没有找到解决办法。所以,在这个问题上我需要帮助 编辑:当我使用固定大小的字符数组时,它工作得很好,但由于它的固定大小和内存问题,我在 string data_handle::hidden_password() 以下代码的功能 #include <iostream> #inc
string data_handle::hidden_password()
以下代码的功能
#include <iostream>
#include <conio.h>
#include <exception>
#include <fstream>
#include <string>
using namespace std;
class username_data {
protected:
string username;
ifstream file;
public:
int is_user_matched(string); //the function will return the index at which the data is found
};
int username_data::is_user_matched(string user_input) {
int index = -1;
file.open("username.txt"); //to open user-name file for reading file
if (file.is_open()) { // if the file is open
for (int i = 0; getline(file, username); i++) { // to get data from the file
if (username == user_input) { //if both inputs matches then it will return the index
index = i;
break;
}
}
file.close(); //closing the file
}
else { //if the file is not open then it will throw user defined exception that file does not exist
throw "user-name file not found";
}
return index; //it will return the index at which the user-name is found otherwise it will return -1
}
class admin {
public:
bool check_admin(string); //function to check whether administrator logged in or not
};
bool admin::check_admin(string username) {
string file_data; //to get data from administrator file
bool is_found = false; //to check whether the data is found in the file and return whether it is present or not
ifstream admin_file; //to open the file
admin_file.open("admin.txt"); //opening administrator file
if (admin_file.is_open()) { //if administrator file is open
while (getline(admin_file, file_data)) { //to get data till user-name is not found or file is not giving any further data
if (file_data == username) { //if data is matches with the passed user-name then it will break the loop
is_found = true; //if data is found then the boolean will turn true and break the loop
break; //breaking the loop
}
}
admin_file.close(); //closing the file
}
else {
throw "administrator file not found"; //if anything wrong occurs then it will throw exception
}
return is_found; //to return true or false of data
}
class password_data {
string password;
ifstream file;
public:
int is_password_matched(string); //it will return the index at which the entered password is found
};
int password_data::is_password_matched(string user_input) {
int index = -1; //if the data is not found then it will return -1
file.open("password.txt"); //opening the password file
if (file.is_open()) { //it will return true if the file is open for reading
for (int i = 0; getline(file, password); i++) { //this will get input from the file and checks until the last data or the relevant file is found
if (password == user_input) { //if data is matched
index = i; //then it will store the input and the loop will broken down
break; //to break the loop
}
}
file.close(); //to close the program it will save from force closing of file which may leads to data corruption
}
else {
throw "password file not found"; //it will throw exception
}
return index; //to return the found index
}
class data_handle {
string entered_username;
username_data handler1; //to handle user-name data
password_data handler2; //to handle password data
string hidden_password(); //to return the string about the password
public:
bool is_admin_logged_in;
void user_input(); //this function will get user input
};
string data_handle::hidden_password() try {
string entered_password;
for (int i = 0; true; i++) {
entered_password[i] = _getch();
if (entered_password[i] != 8 && entered_password[i] != 13) { //8 is the ASCII of backspace and 13 is the ASCII of enter
cout << '*'; //password form
}
else if (entered_password[i] == 8) { //backspacing for erasing password
if (i >= 1) {
cout << "\b \b"; //only erase stars from console window
i -= 2; /* just for array overwriting -2 because when we press backspace it goes one index up(-1 for that) and
to go to the variable to be changed (-1 again for that too) so as a whole -1-1=-2*/
}
else {
i = -1; /* if the password array went to 0 index then by pressing backspace the index of array will go in negative values to restore them to 0
-1 is used because if index went -1 then when the loop starts the index i will be restored to 0 index*/
}
}
else if (entered_password[i] == 13) {
entered_password[i] = '\0'; // if user press enter then store \0 as null character
break; // terminating the loop
}
}
return entered_password;
}
catch (exception ex) { //if anything occurs like array index out of bounds
cout << ex.what() << " occurred\n\n";
return "";
}
void data_handle::user_input() try {
int idx1, idx2;
bool login_successful = false; //to control the login
do {
cout << "Enter user-name :\t";
getline(cin, entered_username); //to get the user-name from the user
cout << "Enter password :\t";
idx1 = handler1.is_user_matched(entered_username); //this function will pass the user-name to the handler for execution
idx2 = handler2.is_password_matched(hidden_password()); //to get the password from the user it will return the string and then pass it to the handler function
if ((idx1 != -1 && idx2 != -1) && idx1 == idx2) { //if handlers methods returned -1 then data does not exists in the file if any index is returned then it is in the file and both user-name and password must have same index
login_successful = true; //if it is true then the login will be successful
admin login_check; //a class to check whether administrator logged in or anyone else
is_admin_logged_in = login_check.check_admin(entered_username); //running the function
}
if (!login_successful) { //if login is not successful then it will print login failed
cout << "\n\nLogin Failed . . .\n\n";
}
else { //else it will print login successful
cout << "\nlogin successful!\n";
}
} while (!login_successful); //the loop will continue till user continues to enter wrong password
}
catch (const char * message) { //if any exception is thrown it will be handled by this catch like file is not opened then this setting will run
cout << message << " occurred\n";
}
catch (exception ex) { //if any other exception occurs
cout << "\n\n" << ex.what() << "occurred . . .\n\n";
}
默认构造的字符串为空。您不能使用输入的_密码[i]向其添加字符,因为其中没有字符。如果存在一个字符,它将替换该字符,但在您的情况下没有 将字符添加到字符串末尾的一种方法是
entered_password += _getch();
完成后,后面对输入的\u密码[i]的引用将引用此字符,并且应该可以。在隐藏的\u密码中,输入的\u密码最初为空,因此使用输入的\u密码[i]来分配不添加字符是超出范围的。要添加字符,您需要使用输入的密码+=。。。或输入了密码。请按回。。。相反
因此,应该使用std::cin.get而不是_getch从控制台读取字符。或者更好的方法是,您应该使用std::getline一次性将整个密码读入entered_password,让控制台处理backspaces,然后使用std::getline处理ENTER,然后您可以使用entered_password[…]循环输入的_password的字符根据需要。这是因为我使用字符串作为字符数组,我想这是由于使用固定大小的字符数组时进行了索引,所以效果很好。我也在更新问题。@tadman我更新了问题。谢谢你的帮助。如何进一步优化此代码。如果需要的话?