删除全部为 uppercase/lowercase 的单词。 C++
Removing words that are all uppercase/lowercase. C++
程序读取文件,如果用户添加参数 upper 或 lower,它将删除全部大写或全部小写的单词。
即。 "Hello World.... HELLO WORLD.... hello world"
'upper word' 会输出 "Hello World.... .... hello world"
'lower word' 会输出 "Hello World.... HELLO WORLD.... "
截至目前,我的代码确实取消了大写单词,但假设只有当后面的字符不是大写时它才会中断循环。
问题是,如果它是一个像 "AABBaabb" 这样的字符串,程序应该忽略它,因为它混合了大小写。相反,它会打印 "Baabb".
这是函数。
for (int i = 0; i < copyText.length(); i++)
{
if (!ispunct(copyText[i]) || !isspace(copyText[i]))
{
while (isupper(copyText[i]) || isdigit(copyText[i]))
{
if (islower(copyText[i + 1]))
{
break;
}
else
copyText.erase(copyText.begin() + i);
}
}
}
首先,第一个 if 语句中的条件将始终计算为 True。这 ! (not) 将首先应用,因此条件本质上是 "if it's not punctuation or it's not a space." 因为它不能同时是标点符号和 space,所以这始终为真。我认为您要做的是检查字符是否是标点符号或 space 以外的字符。你可以这样做
if(!(ispunct(copyText[i]) || isspace(copyText[i])))
或者这个。
if(!ispunct(copyText[i]) && !isspace(copyText[i]))
你的 while 循环正在做的是,只要 copyText[i] 是大写或数字,如果非常下一个字符 - copyText[i + 1] - 是小写,则中断,否则删除当前字符.这就是为什么它在开始删除之前不查看单词的其余部分的原因。这是您的算法的修改版本,它可能有效也可能无效(我还没有测试过),但它显示了我将如何开始修改您的方法以使其发挥作用。
for (int i = 0; i < copyText.length(); i++)
{
while (!ispunct(copyText[i]) && !isspace(copyText[i]))
{
bool delChar = True;
for (int j = 1; i+j < copyText.length(); j++) {
if (ispunct(copyText[i+j]) || isspace(copyText[i+j])
break;
if (islower(copyText[i+j]))
delChar = False;
}
if (delChar)
copyText.erase(copyText.begin() + i);
}
}
现在,如果它按照我的预期运行,它会解决您的问题,但它仍然无法在所有情况下运行。例如,考虑单词 "aabbAABB"。该算法将从第一个大写字母开始读取,读取到最后,并决定删除该字符。您将只剩下 "aabb"。您可以添加另一个内部 for 循环以从当前字符向后读取以防止出现这种情况。
编辑:将 if 语句更改为 while 循环,因为我忘记了删除一个字符对其他字符索引的影响。
您可以执行以下步骤:
- std::regex_iterator to collect words by pattern
\w+
. std::match_results 存储匹配项的位置和长度。
- std::all_of + std::isupper/std::islower 检测 uppercase/lowercase 个词。
- std::basic_string::erase 逐个删除单词(不要忘记在每次删除后更新位置偏移量)。
程序读取文件,如果用户添加参数 upper 或 lower,它将删除全部大写或全部小写的单词。
即。 "Hello World.... HELLO WORLD.... hello world"
'upper word' 会输出 "Hello World.... .... hello world"
'lower word' 会输出 "Hello World.... HELLO WORLD.... "
截至目前,我的代码确实取消了大写单词,但假设只有当后面的字符不是大写时它才会中断循环。
问题是,如果它是一个像 "AABBaabb" 这样的字符串,程序应该忽略它,因为它混合了大小写。相反,它会打印 "Baabb".
这是函数。
for (int i = 0; i < copyText.length(); i++)
{
if (!ispunct(copyText[i]) || !isspace(copyText[i]))
{
while (isupper(copyText[i]) || isdigit(copyText[i]))
{
if (islower(copyText[i + 1]))
{
break;
}
else
copyText.erase(copyText.begin() + i);
}
}
}
首先,第一个 if 语句中的条件将始终计算为 True。这 ! (not) 将首先应用,因此条件本质上是 "if it's not punctuation or it's not a space." 因为它不能同时是标点符号和 space,所以这始终为真。我认为您要做的是检查字符是否是标点符号或 space 以外的字符。你可以这样做
if(!(ispunct(copyText[i]) || isspace(copyText[i])))
或者这个。
if(!ispunct(copyText[i]) && !isspace(copyText[i]))
你的 while 循环正在做的是,只要 copyText[i] 是大写或数字,如果非常下一个字符 - copyText[i + 1] - 是小写,则中断,否则删除当前字符.这就是为什么它在开始删除之前不查看单词的其余部分的原因。这是您的算法的修改版本,它可能有效也可能无效(我还没有测试过),但它显示了我将如何开始修改您的方法以使其发挥作用。
for (int i = 0; i < copyText.length(); i++)
{
while (!ispunct(copyText[i]) && !isspace(copyText[i]))
{
bool delChar = True;
for (int j = 1; i+j < copyText.length(); j++) {
if (ispunct(copyText[i+j]) || isspace(copyText[i+j])
break;
if (islower(copyText[i+j]))
delChar = False;
}
if (delChar)
copyText.erase(copyText.begin() + i);
}
}
现在,如果它按照我的预期运行,它会解决您的问题,但它仍然无法在所有情况下运行。例如,考虑单词 "aabbAABB"。该算法将从第一个大写字母开始读取,读取到最后,并决定删除该字符。您将只剩下 "aabb"。您可以添加另一个内部 for 循环以从当前字符向后读取以防止出现这种情况。
编辑:将 if 语句更改为 while 循环,因为我忘记了删除一个字符对其他字符索引的影响。
您可以执行以下步骤:
- std::regex_iterator to collect words by pattern
\w+
. std::match_results 存储匹配项的位置和长度。 - std::all_of + std::isupper/std::islower 检测 uppercase/lowercase 个词。
- std::basic_string::erase 逐个删除单词(不要忘记在每次删除后更新位置偏移量)。