如何计算字符串中连续的大写字母?



我正在做一个试图镜像 http://uic.edu/apps/strong-password/的项目。我似乎无法弄清楚如何计算连续的大写字母以及小写字母或数字。这就是我到目前为止所拥有的

bool IsUpper(char c) {
if ((c >= 65 && c <= 90))
return true;
else
return false;
}
void consecUpper(string s) {
int counter = 0;
for (int i = 0; i < s.length(); i++) {
if (IsUpper(s[i > 1])) {
counter++;

}
}
gotoxy(73, 14);
cout << counter;
}

我需要它做什么 1.通读字符串(完成) 2.如果实例中出现多个大写字符,则开始计数器。3. 输入任何其他字符时停止。4. 如果连续输入多个大写字母,则重新开始。

当前发生的情况是 1:如果检测到超过大写字符。计数器开始计算任何输入。 或 2:在第二个输入之后,如果输入多个大写字母,计数器保持在 0。

你的代码有几个问题 - 我不想粗鲁,但我建议你在尝试更复杂的项目之前更熟悉C++的基础知识。此外,您提出的算法存在问题。

让我们先看一下如何"在纸上"完成此操作,正如其他评论者所建议的那样,然后我们可以看看代码问题。

顺便说一下,我假设您要计算连续大写字母的总数,其中连续定义为后跟至少一个大写字母。这是您链接的参考应用的行为方式;例如,字符串"AAAA"有三个连续的字母,因为第一个"A"不被计算在内,而"AAAAbbbCC"将有四个连续的字母。

所以让我们开始吧。

假设我们有一个字符串,例如"ABAbbbCCddE"。我们希望找到此字符串中有三个连续的大写字母。我们从左边开始,有一个"A",所以我们知道我们看到了一个大写字母。这意味着如果我们继续看到更多的大写字母,我们希望开始计数。我们看到另一个首都,所以现在我们已经计算了一个。然后是另一个,所以我们数了两个。

然后我们看到一些小写字母,我们忽略了这些字母。然后,我们看到第一个"C",我们知道如果我们看到另一个大写字母,我们应该再次开始计数。我们这样做,所以我们数起来,有三个。现在我们跳过"d"并看到一个"E",但之后什么都没有,所以我们完成了。现在,这在代码中的外观如何?

好吧,首先让我指出您现有代码的一些事情。

首先,也是最次要的,是检查boolean是否true然后返回true是没有意义的 - 只需返回boolean即可。取而代之的是:

bool IsUpper(char c) {
if ((c >= 65 && c <= 90))
return true;
else
return false;
}

这样做:

bool IsUpper(char c) {
return (c >= 65 && c <= 90);
}

更重要的是,您根本没有正确索引数组。我对你在这里试图完成的事情感到非常困惑:

if (IsUpper( s[i > 1] ))

您应该使用s的第i个数组元素调用IsUpper(),但相反,您将i1进行比较,并将该比较的结果用作数组的索引。这不会崩溃的唯一原因是C++会将boolean值隐式转换为整数,零或一。

更简单地说,这就是分解的方式。

如果i小于或等于 1:

s[i > 1] -> s[false] -> s[0]

如果i大于 1:

s[i > 1] -> s[true] -> s[1]

话虽如此,我继续编写了这个算法:

#include <iostream>
using namespace std;
inline bool IsUpper(char c) {
return (c >= 65 && c <= 90);
}
void consecUpper(string s) {
int counter = 0;
for (int i = 1; i < s.length(); i++) {
if ( IsUpper(s[i-1]) && IsUpper(s[i]) ) {
counter++;
}
}
cout << counter;
}
int main(){
consecUpper("ABAbbbCCddE");
return 0;
}

如您所见,在循环中,我从i = 1开始,因为当我们在第一次调用IsUpper()时将其用作s索引时,我们将从i中减去 1。我们不能从零开始(也不需要),因为那样我们会得到一个索引 -1,这是无效的。从 0 开始并将s[i]s[i+1]进行比较同样有效,但您需要在i < s.length() - 1处停止循环。

此算法只是并排比较每个字符。如果前一个字符是大写的,而当前字符是大写的,那么我们向计数器添加一个。就是这样,我们完成了。

奖金:

此方法效率低下,因为我们需要对字符串的每个字符调用IsUpper()两次,除了第一个和最后一个字符。IsUpper()并不是计算成本最高的函数,但从理论上讲,如果您需要更复杂的评估,则可能是这样。相反,我们可以简单地设置一个标志来指示前一个字符是否为大写:

#include <iostream>
using namespace std;
inline bool IsUpper(char c) {
return (c >= 65 && c <= 90);
}
void consecUpper(string s) {
int counter = 0;
bool lastCharUpper = false;
for (int i = 0; i < s.length(); i++) {
if (IsUpper(s[i])){
if (lastCharUpper){
counter++;
}
lastCharUpper = true;
} else {
lastCharUpper = false;
}
}
cout << counter;
}
int main(){
consecUpper("ABAbbbCCddE");
return 0;
}

我怀疑这实际上可能比简单地为每个字符调用IsUpper()两次的效率略低,因为它只是两个比较并且可能会被内联。但是,如前所述,如果调用更复杂且更昂贵的函数,则可能需要使用标志方法。请注意,我们在此索引中从i = 0开始索引,因为我们不再使用i - 1进行索引。

最新更新