简体   繁体   English

使用递归时出现 substring 搜索问题

[英]Issue with substring search when using recursion

I have a program that simulates a bank.我有一个模拟银行的程序。 When I choose deposit amount, it asks me for searching a user by part of name.当我选择存款金额时,它要求我按名称的一部分搜索用户。

Here, I type 'aar' and this outputs the user without any issue.在这里,我输入“aar”,这会毫无问题地输出用户。

No issue here这里没有问题

Now, I start the program again and type 'ar'.现在,我再次启动程序并输入“ar”。 This gives me all users that have 'ar' as my substring.这为我提供了所有将“ar”作为我的 substring 的用户。

Again, no issue with this output同样,这个 output 没问题

After this, when I type 'aar' in order to select my user, it again displays all the users that were in the previous photo.此后,当我输入“aar”以输入 select 我的用户时,它会再次显示上一张照片中的所有用户。

The bug displayed here is an infinite loop这里显示的错误是一个无限循环

I am not sure where exactly I went wrong.我不确定我到底哪里出错了。 I'm still learning C++ and appreciate your assistance.我仍在学习 C++ 并感谢您的帮助。 Here's the code for the program.这是程序的代码。

#include <iostream>
#include <iomanip>      //used for setw which is used for formatting cout output
#include <cctype>
using namespace std;

// This Function searches if we have a match or if we have reached the end of string
bool isMatch(char name[], char search_str[])
{
    int i = 0;
    int idx = 0;

    if (search_str[idx] == '\0')
    {
        return true;
    }
    
    if(name[i] == '\0' && search_str[idx] != '\0')
    {
        return false;
    }

    if (name[i] == search_str[idx])
    {
        return isMatch(name + 1, search_str + 1);
    }

    return false;
}

bool IsSubString(char name[], char search_str[])
{
    /*
    Searches the character array for the first occurrence of the sequence specified by its arguments.
    */
    int i = 0;
    int idx = 0;

    for (int i = 0; search_str[idx] != '\0'; i++)
    {
        if (isupper(search_str[idx]))
        {
            search_str[idx] += 32;
        }
    }

    if (name[i] == '\0')
    {
        return false;
    }

    if (name[i] == search_str[idx])
    {
        if (isMatch(name, search_str))
        {
            return true;
        }
    }
    else
    {
        return IsSubString(name + 1, search_str);
    }

    return IsSubString(name + 1, search_str);

}

int select_user(char cust_names[][100], int num_cust)
{
    /*
    Selects a user by searching for part of their name
    */
    char search_user[100];
    int cust_idx = 0;
    int count = 0;
    int selected_user_id;

    while (count != 1)
    {
        cout << "Search user by part of name: ";
        cin.ignore();
        cin.getline(search_user, 100);
        cust_idx = 0;
        count = 0;
        selected_user_id = -1;
        for (cust_idx = 0; cust_idx < num_cust; cust_idx++)
        {
            if (IsSubString(cust_names[cust_idx], search_user))
            {
                selected_user_id = cust_idx;
                cout << "User match: " << cust_names[cust_idx] << endl;
                count++;
            }
        }
        if (count > 1)
        {
            cout << endl << "More than one user found with that substring. Please search again with more characters ************************* " << endl;
        }
        else if (count == 0)
        {
            cout << endl << "No user found with that substring. Please search again *************************" << endl;
        }
    }
    return selected_user_id;
}

void withdraw_from_account(double acct_bal[], double loan_bal[], int account_id, double withdraw_amount)
{
    //withdraw the amount if account has enough balance
    //otherwise, if withdraw amount is more than account balance, charge an overdraft fee and add extra withdrawn amount to loan dues
    double overdraft_fee = 35;
    if (withdraw_amount < 0)
    {
        cout << "Error: Cannot withdraw a negative amount *************************" << endl << endl;
        return;
    }

    acct_bal[account_id] = acct_bal[account_id] - withdraw_amount;

    if (acct_bal[account_id] < 0)
    {
        cout << "Withdrawing amount larger than current account balance. Additional overdraft fee of $35 shall be charged. *************************" << endl << endl;
        loan_bal[account_id] = -acct_bal[account_id] + overdraft_fee;
        acct_bal[account_id] = 0;
    }
}

void deposit_to_account(double acct_bal[], double loan_bal[], int account_id, double deposit_amount)
{
    //deposit the amount if account has no loans
    //otherwise, if deposit amount is more than outstanding loan, add extra amount to account balance
    if (deposit_amount < 0)
    {
        cout << "Error: Cannot deposit a negative amount *************************" << endl << endl;
        return;
    }
    if (loan_bal[account_id] == 0.0)
    {
        acct_bal[account_id] += deposit_amount;
    }
    else
    {
        loan_bal[account_id] -= deposit_amount;
        if (loan_bal[account_id] < 0)
        {
            acct_bal[account_id] = -loan_bal[account_id];
            loan_bal[account_id] = 0;
        }
    }
}

void print_account_details(char cust_names[][100], double acct_bal[], double loan_bal[], int num_cust)
{
    /*
    Prints account statements for all users
    */
    if (num_cust == 0)
    {
        //print header
        cout << "--------------------------------------------------------------------" << endl;
        cout << "\t\t\t ACCOUNT DETAILS " << endl;
        cout << "--------------------------------------------------------------------" << endl;
        cout << "CUSTOMER NAME -> ACCOUNT BALANCE -> LOAN DUE" << endl;
        cout << "--------------------------------------------------------------------" << endl;
        return;
    }

    print_account_details(cust_names, acct_bal, loan_bal, num_cust - 1);
    int print_idx = num_cust - 1;
    cout << std::left << setw(40) << cust_names[print_idx] << " $" << setw(20) << acct_bal[print_idx] << "$" << setw(20) << loan_bal[print_idx] << endl;
}


int print_menu()
{
    /*
    Prints the menu
    */
    int menu_select = -1;

    while (menu_select < 0 || menu_select > 3)
    {
        cout << "--------------------------------------------------------------------" << endl;
        cout << "\t\t MENU" << endl;
        cout << "--------------------------------------------------------------------" << endl;
        cout << "1: Show Account Details" << endl;
        cout << "2: Deposit amount to account" << endl;
        cout << "3: Withdraw amount from account" << endl;
        cout << "0: Exit" << endl;
        cout << "--------------------------------------------------------------------" << endl;
        cout << "Select menu option [1, 2, 3, 0] : ";
        cin >> menu_select;
        cout << "--------------------------------------------------------------------" << endl;
        if (menu_select < 0 || menu_select > 3)
            cout << "Error: Incorrect menu item selected. Please select again *************************" << endl << endl;
    }

    return menu_select;
}



int main()
{
    const int num_customers = 5;
    char customer_names[num_customers][100] = {
        "john fitzgerald kennedy",
        "william shakespeare",
        "salvador felipe jacinto dali domenech",
        "elvis aaron presley",
        "elizabeth alexandra mary windsor" };


    double customer_account_balances[num_customers] = { 100.5, 120.75, 50.2, 150.15, 200.99 };
    double customer_loan_dues[num_customers] = { 0.0, 0.0, 0.0, 0.0, 0.0 };


    cout << "************************* Welcome to BANK OF ANTARCTICA *************************" << endl << endl << endl;



    print_account_details(customer_names, customer_account_balances, customer_loan_dues, num_customers);
    cout << endl << endl << endl;
    double amount;
    int acct_id;
    int menu_select = -1;
    while (menu_select != 0)
    {
        menu_select = print_menu();
        switch (menu_select)
        {
        case 1:     // Show Account Details
            print_account_details(customer_names, customer_account_balances, customer_loan_dues, num_customers);
            cout << endl << endl << endl;
            break;
        case 2:     // Deposit amount to account
            acct_id = select_user(customer_names, num_customers);
            cout << "Please enter amount to DEPOSIT into the account of: " << customer_names[acct_id] << " :: $";

            cin >> amount;
            deposit_to_account(customer_account_balances, customer_loan_dues, acct_id, amount);
            print_account_details(customer_names, customer_account_balances, customer_loan_dues, num_customers);
            cout << endl << endl << endl;
            break;
        case 3:     // Withdraw amount from account
            acct_id = select_user(customer_names, num_customers);
            cout << "Please enter amount to WITHDRAW from the account of: " << customer_names[acct_id] << " :: $";

            cin >> amount;
            withdraw_from_account(customer_account_balances, customer_loan_dues, acct_id, amount);
            print_account_details(customer_names, customer_account_balances, customer_loan_dues, num_customers);
            cout << endl << endl << endl;
            break;
        }
    }


    cout << endl << endl << "Final Details:" << endl;
    print_account_details(customer_names, customer_account_balances, customer_loan_dues, num_customers);
    cout << endl << endl << endl;

    cout << "THANK YOU!!! for using BANK OF ANTARCTICA services" << endl;

    return 0;
}

Take a close look at this loop:仔细看看这个循环:

int i = 0;
int idx = 0;

for (int i = 0; search_str[idx] != '\0'; i++)
{
    if (isupper(search_str[idx]))
    {
        search_str[idx] += 32;
    }
}

The loop condition checks search_str[idx] != '\0' , yet nowhere in the loop, idx is changed (you only change i ).循环条件检查search_str[idx] != '\0' ,但循环中无处更改idx (您只更改i )。 So whenever the loop condition is true, you run into a neverending loop.因此,只要循环条件为真,您就会陷入永无止境的循环。

I would generally recommend to test the IsSubstring function in isolation before putting it into a larger program (using some test framework or just a simple program computing the IsSubstring on several test inputs and checking its result).我通常建议在将IsSubstring function 放入更大的程序之前对其进行隔离测试(使用一些测试框架或只是一个简单的程序在几个测试输入上计算 IsSubstring 并检查其结果)。

I guess this is some kind of homework assignment?我想这是某种家庭作业? Otherwise I would suggest to completely move away from your IsMatch/IsSubString methods and use std::string and its find function (or maybe contains in the future ).否则我会建议完全摆脱你的 IsMatch/IsSubString 方法并使用std::string和它的find function (或者 将来可能contains )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM