如何避免长切换语句?C++

Tyl*_*aff 8 c++ performance switch-statement

我正在为我班上的"字典"工作.我有一个调用的int数组NumOfWordsInFile[],NumOfWordsInFile[0]对应于A.txt中有多少个单词,NumOfWordsInFile[25]对应于Z.txt

就像现在一样,我有一个巨大的开关,用于26种不同的字母条件.我有一个叫做的函数AddWord(string word).AddWord获取传递给它的单词的第一个字母,并将其插入相应的.txt文件中.现在这是问题所在.每次在A.txt中添加一个单词时,我必须增加NumOfWordsInFile[0]1.我能想到的唯一方法是使用这些巨大的开关.我还有一个deleteWord函数,NumOfWordsInFile[]如果删除该单词,则相反递减.现在我不想要两个26箱开关,但问题是我不知道怎么做.现在我可以为删除功能做同样的事情,但我真的不希望有更多的代码行来完成.有一个更好的方法吗?

AddWord功能中的开关示例:

case 'w':
    if (numOfWordsInFile[22] < maxWordsPerFile) {
        fout.open(fileName.data(), ios::app);
        fout << word << " " << endl;
        numOfWordsInFile[22]++;
        if (totalWordsInDict < maxWordsInDict) {
            totalWordsInDict++;
        }
        return(Dictionary::success);
    } else {
        return(Dictionary::failure);
    }

case 'x':
    if (numOfWordsInFile[23] < maxWordsPerFile) {
        fout.open(fileName.data(),ios::app);
        fout << word << " " << endl;
        numOfWordsInFile[23]++;
        if (totalWordsInDict < maxWordsInDict) {
            totalWordsInDict++;
        }
        return(Dictionary::success);
    } else {
        return(Dictionary::failure);
    }
Run Code Online (Sandbox Code Playgroud)

删除功能.

bool Dictionary::DeleteAWord(string word)
{
    ofstream fout;
    ifstream fin;
    string x;
    string fileName="#.txt";
    int count=0;
    vector <string> words;
    bool deleted=false;

    fileName[0]=toupper(word[0]);
    fin.open(fileName.data()); //makes the file depending on the first letter of the argument "word"

    while (fin >> x)
    {
        words.push_back(x);
        count++;//number of elements in vector
    }
    if (SearchForWord(x))
    {
        for ( ;count > 0; count--)
        {
            if (words[count-1] == word)
            {
                // cout << "Found word " << word << " during search, now deleting" << endl;
                words.erase(words.begin()+(count-1));
                deleted = true;

                /*
                    This clearly doesn't work and is what I need help with, I know why it
                    doesn't work but I don't know how to make it better than having another
                    huge switch.
                */
                numOfWordsInFile[toupper(word[0])]--;
                /*

                */

                totalWordsInDict--;
                fin.close();
            }
        }

        if (deleted)
        {
            fout.open(fileName.data());
            for (int i = 0; i < words.size(); i++)
                fout << words[i] << endl;
            return(Dictionary::success);
        }
        return(Dictionary::failure);
    }
    return(Dictionary::failure);
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*ley 7

只是快速看一下,看起来你正在使用字母表中字母的位置来做事情.

您可以使用以下语句替换所有switch语句:

int letter = (int)(ActualLetter - 'a');

if(numOfWordsInFile[letter]<maxWordsPerFile){
 fout.open(fileName.data(),ios::app);
 fout<<word<<" "<<endl;
 numOfWordsInFile[letter]++;
 if(totalWordsInDict<maxWordsInDict){
   totalWordsInDict++;
 }
 return(Dictionary::success);
}else{
 return(Dictionary::failure);
}
Run Code Online (Sandbox Code Playgroud)

ActualLetter就像是'a',例如.

在相关的说明中,将来如果您实际上有大型switch语句,请考虑将代码封装在函数中:

switch (letter)
{
    case 'a':
      LetterA();
      break;

    case 'b':
      LetterB();
      break;

    ...
}
Run Code Online (Sandbox Code Playgroud)

或者甚至更好,您可以使用多态来根据特定的派生类将C++调度到您想要的方法:

class BaseLetter
{
   ...
public:
   virtual void DoStuff() = 0;
};

class LetterA : public BaseLetter
{
public:
   void DoStuff();
};

class LetterB : public BaseLetter
{
public:
    void DoStuff();
};

void Foo(BaseLetter *letter)
{
    // Use dynamic dispatch to figure out what to do
    letter->DoStuff();
}
Run Code Online (Sandbox Code Playgroud)

请注意,动态调度确实会产生(轻微)性能损失,而上述实际使用它是一个非常糟糕的地方.解决方案I,RedX和其他人发布的解决方案更适合您的具体示例.


Oli*_*rth 6

在最实际的字符编码,你很可能会同时使用C或C++遇到,'a''z'是连续的,这样你就可以得到数组索引边做简单的使用(c - 'a'),在这里c就是char你要找的.


Eri*_*rik 6

struct FileInfo {
  int NumWords;
  std::string Filename;
};

std::map<char, FileInfo> TheFiles; 

FileInfo & FI = TheFiles[letter];
// Work with FI.NumWords and FI.Filename
Run Code Online (Sandbox Code Playgroud)

或者:

std::vector<FileInfo> TheFiles;
FileInfo & FI = TheFiles[std::tolower(Letter) - 'a'];
Run Code Online (Sandbox Code Playgroud)


che*_*cal 3

字符基本上是数字。“a”是 97,“b”是 98,依此类推。最简单的方法是简单地将 every 替换为numOfWordsInFile[n],并且numOfWordsInFile[current_char - 'a']每种情况重复的整个代码可能驻留在一个函数中,如下所示:

   int AddWord(char current_char) {
    if(numOfWordsInFile[current_char - 'a']<maxWordsPerFile){
     fout.open(fileName.data(),ios::app);
     fout<<word<<" "<<endl;
     numOfWordsInFile[current_char - 'a']++;
      if(totalWordsInDict<maxWordsInDict){
       totalWordsInDict++;
     }
     return(Dictionary::success);
    }else{
     return(Dictionary::failure);
    }
   }
Run Code Online (Sandbox Code Playgroud)

对于更通用的解决方案,请阅读哈希映射和函数指针(例如,当您可能想要为每个字符分配不同的函数时)。