删除[]搞砸了我的程序。发生了什么事情?

delete[] messes up my program. what's happening?

本文关键字:发生了 什么 程序 我的 删除      更新时间:2023-10-16

我正在尝试编写一个函数,检查字符串是否只有大写字母,并且字符串中的每个字母的数量是否相同。即AXXA是有效字符串,但AXX不是。

我的checkUpper函数运行良好。但是我的checkLetters函数只有在我的程序第一次运行时才能工作。

当我在函数返回之前删除了delete[]时,它会一直工作。但我知道这会导致内存泄漏。

我只想问是什么原因导致它第一次才起作用?为什么每次删除删除[]后都能正常工作?

任何帮助都将不胜感激。非常感谢。

#include <iostream>
#include <string>
#include <ctype.h>
using namespace std;enter code here
string input;
int NumOfLetters;
//check if everything is uppercase;
bool checkUpper(string input){
    for(int i=0;i<input.length();i++)
        if(!isupper(input[i])) return false;
    return true;
}
//check to see if there are the same number of runners for each team;
bool checkLetters(string input){
    char* Letters= new char[input.length()];//worst case, all letters are used once;
    NumOfLetters=0; //letter counter
    for(int i=0; i<input.length();i++){
        if(Letters[NumOfLetters]!=input[i]){
            Letters[NumOfLetters]=input[i]; //putting different letters in Letters
            NumOfLetters++;
        }
    }
    int *CountLetters= new int[NumOfLetters]; //used to count each letter
    for(int i=0; i<NumOfLetters;i++){
        for(int j=0;j<input.length();j++)
            if(Letters[i]==input[j])CountLetters[i]++; //counting each letter
    }
    for(int i=0; i<NumOfLetters;i++){
        if(CountLetters[i]!=CountLetters[0]){ //comparing number of each letters to the first one;
            delete[] Letters;
            delete[] CountLetters;
            return false;
        }
    }
    delete[] Letters;
    delete[] CountLetters;
    return true; 
}

int main(){
    while(true){
        cout<<"Enter a string of uppercase characters to indicate places(enter done to terminate):";
        cin>>input;
        if(input=="done") break;
        if(!checkUpper(input)){
            cout<<"Uppercase letters ONLY! try again.n";
            continue;
        }
        if(!checkLetters(input)){
            cout<<"Each team must have the same number of runners! try again.n";
            continue;
        }
        //to be filled;
    }
    return 0;
}

我一眼就看不出问题,但有很多评论:

  • 切勿写入裸newdelete。在非常的情况下,使用std::make_unique或类似方法。然而,对于该应用,std::stringstd::vector将更好
  • 如注释中所述,您没有将CountOfLetters的内容初始化为零(new不会为您执行此操作)
  • checkLetters中的第一个循环(初始化Letters的地方)需要是一个双循环。(你并没有检查这个字母以前从未见过——只是它不是一个未初始化的值!)
  • 您应该更喜欢将字符串作为常量引用传递

最后,checkLetters使用std::map:会更好

    bool checkLetters(const std::string& input) {
        if (input.length() == 0)
           return true;  // Just in case no characters at all.
        std::map<char,int> counts;
        for (const char c : input) {
            // No point in running over the string twice.  Do it in one go.
            if (!std::upper(c)) return false;
            // If there is an entry in the map, increment it.  If not,
            // create it (with value zero), and then increment.
            counts[c]++;
        }
        // input[0] would blow up if the string is length zero and we hadn't checked above
        const int target = counts[input[0]];
        for (const auto& keyvalue : counts)
        {
            const int value = keyvalue.second;
            if (value != target)
                return false;
        }
        return true;
   }

EDIT:我把问题误读为"输入中的每个字母都必须只有一个计数"。这是我的新答案:

我浏览了一下你的代码,纠正了你的错误。我基本上重写了您原始代码的部分内容,并制作了一个简单的checkLetters函数。根本不需要使用动态分配,除非特定情况需要。

您所能做的就是维护一个map<char,int>,它存储输入中每个字母的计数。在对输入进行交互之后,我们保留一个变量mustHaveCnt,它是每个字母必须具有的计数。现在,遍历映射中的所有字母,如果计数超过mustHaveCnt变量,则返回false。否则,答案是正确的

此外,我已经重写了您的输入条件。当输入为"完成"时,它会正确终止

#include <iostream>
#include <string>
#include <ctype.h>
#include <map>
using namespace std;
//check if everything is uppercase;
bool checkUpper(string input){
    for(int i=0;i<input.length();i++)
        if(!isupper(input[i])) return false;
    return true;
}
//Checks if the input has the same number of runners
//use must have the header file 'map' included, e.i write "#include <map>" at the top
bool checkLetters(string input){
    map<char,int> storeCnt;
    for(int i=0;i<input.size();i++)
        storeCnt[input[i]]++; //Increment the count of each letter found
    int mustHaveCnt=storeCnt.begin()->second; //The second entry stores the count
    for(map<char,int>::iterator it= ++storeCnt.begin(); it!=storeCnt.end(); it++) //Iterate and check cnt
        if(it->second != mustHaveCnt)
            return false; //terminate here since the count does not match
    return true;
}
int main(){
    cout<<"Enter a string of uppercase characters to indicate places(enter done to terminate):n";
    string input; //Let's avoid global declaration, unless needed
    cin>>input;
    while(input.compare("done")!=0)
    {
        int flag=1;
        if(!checkUpper(input)){
            cout<<"Uppercase letters ONLY! try again.n";
            flag=0;
        }
        if(flag && !checkLetters(input)){
            cout<<"Each team must have the same number of runners! try again.n";
            flag=0;
        }
        if(flag)
            cout<<"Valid String!n";
        cin>>input;
    }
    return 0;
}