我在撰寫用于編碼和解碼 Playfair 密碼的 C 程式的一部分時遇到了一些問題。我遇到問題的程式部分是第一步(不幸的是,我知道),它涉及洗掉所有空格、標點符號和非字母字符。這就是我所擁有的:
std::string step1(std::string plaintext)
{
plaintext.erase(remove_if(plaintext.begin(), plaintext.end(),
std::not1(std::ptr_fun(std::isalpha))));
plaintext.erase(remove_if(plaintext.begin(), plaintext.end(),
std::ptr_fun(std::ispunct)));
return plaintext;
}
輸出很好,除了它在清理后在字串的末尾添加字符。通常,額外的字符是在清理后的輸入末尾找到的字符的副本。對于我的一生,我無法弄清楚為什么會發生這種情況。有任何想法嗎?
uj5u.com熱心網友回復:
std::remove/_if()實際上并沒有洗掉任何東西,它只是將匹配的專案移動到容器的末尾,然后將迭代器回傳到該專案范圍的開頭。然后呼叫者可以使用該迭代器從容器中實際洗掉專案。
您正在將該迭代器傳遞給以std::string::erase()1 個迭代器作為輸入的多載。因此,它最多只會洗掉 1 個字符(如果std::remove_if()沒有找到任何內容,它將回傳字串的end()迭代器,呼叫erase()該迭代器是未定義的行為)。如果超過 1 個字符被“洗掉”到字串的末尾,則剩余的未洗掉字符將被留下。這就是您在輸出中看到的內容。
要擦除所有“已洗掉”字符,您需要使用std::string::erase()2 個表示范圍的迭代器的多載,例如:
std::string step1(std::string plaintext)
{
plaintext.erase(
std::remove_if(plaintext.begin(), plaintext.end(),
std::not1(std::ptr_fun(std::isalpha))
),
plaintext.end()
);
plaintext.erase(
std::remove_if(plaintext.begin(), plaintext.end(),
std::ptr_fun(std::ispunct)
),
plaintext.end()
);
return plaintext;
}
請注意,使用洗掉所有非字母字符std:::isalpha()將包括所有空格和標點符號,因此您的第二次搜索使用std::ispunct()將找不到任何要洗掉的內容,因此您可以完全洗掉該搜索,例如:
std::string step1(std::string plaintext)
{
plaintext.erase(
std::remove_if(plaintext.begin(), plaintext.end(),
std::not1(std::ptr_fun(std::isalpha))
),
plaintext.end()
);
return plaintext;
}
話雖這么說,在評論中指出,std::not1()并std::ptr_fun在現代C 中已被棄用。在 C 11 及更高版本中,您可以改用 lambda:
std::string step1(std::string plaintext)
{
plaintext.erase(
std::remove_if(plaintext.begin(), plaintext.end(),
[](unsigned char ch){ return !std::isalpha(ch); }
),
plaintext.end()
);
return plaintext;
}
在 C 20 及更高版本中,您可以使用std::erase_if():
std::string step1(std::string plaintext)
{
std::erase_if(plaintext,
[](unsigned char ch){ return !std::isalpha(ch); }
);
return plaintext;
}
uj5u.com熱心網友回復:
也許這太明顯了。但是對于這樣的任務有一個專門的功能。它被稱為:std::regex_replace。
這是非常通用且易于使用的。
使用正則運算式,您可以輕松定義要替換或不替換的內容。
請參見:
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string test{" ! Hello World 1234 ,;. "};
std::cout << std::regex_replace(test, std::regex(R"([^a-zA-Z] )"), "");
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/313535.html
上一篇:如何洗掉兩個單詞之間的所有空格?
下一篇:鏈表與二叉搜索樹插入時間復雜度
