我正在做一个试图镜像 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()
,但相反,您将i
与1
进行比较,并将该比较的结果用作数组的索引。这不会崩溃的唯一原因是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
进行索引。