初学者质疑,关于循环效率。我已经开始用C ++编程(我的第一语言),并且一直在使用Bjarne Stroustrup的'Principles and Practice Using C ++'。我已经完成了前面几章的介绍,并且刚刚介绍了循环的概念。
关于循环的第一个练习问我以下内容: 字符'b'是char('a'+ 1),'c'是char('a'+ 2)等。使用循环写出 一个包含相应整数值的字符表:
a 97,b 98,...,z 122
虽然我使用大写字母,但我创建了以下内容:
int number = 64; //integer value for @ sign, character before A
char letter = number;//converts integer to char value
int i = 0;
while (i<=25){
cout << ++letter << "\t" << ++number << endl;
++i;
}
我是否应该只针对'i'存在于循环中,或者在类型之间进行转换时根本不可能?除了将字符值转换为它的整数对应部分(即与当前方法相反)或根本没有转换并且具有字母存储'@'之外,我真的不能想到上述任何其他方式。
答案 0 :(得分:22)
从jk开始,您甚至可以在循环中使用字母本身(字母&lt; ='z')。我也会使用for循环,但那只是我。
for( char letter = 'a'; letter <= 'z'; ++letter )
std::cout << letter << "\t" << static_cast<int>( letter ) << std::endl;
答案 1 :(得分:8)
您应首先瞄准清晰度,然后尝试进行微观优化。您可以更好地将其重写为for循环:
const int offsetToA = 65;
const int numberOfCharacters = 26;
for( int i = 0; i < numberOfCharacters; ++i ) {
const int characterValue = i + offsetToA;
cout << static_cast<char>( characterValue ) << characterValue << endl;
}
你可以在不同类型之间进行转换 - 这就是所谓的转换(上面代码中的static_cast
构造)。
答案 2 :(得分:2)
对于你的方式没有什么特别低效,但它肯定可以在chars和int之间进行转换(char是整数类型)。这意味着你只需要存储1个计数器,而不是存储3个(i,字母+数字)
另外,对于从固定的开始到结束的循环,'for'循环可能更惯用(尽管它可能你还没有遇到过这个!)
答案 3 :(得分:2)
这不是一个糟糕的方法,但你可以只使用一个这样的循环变量:
char letter = 65;
while(letter <= 65+25){
printf("%c\t%d\n", letter, letter);
++letter;
}
答案 4 :(得分:2)
如果你担心循环的效率,我会敦促你试试这个:
在IDE(如Visual Studio)下编译并运行此代码,并在开头设置断点。当你到达那里时,切换到反汇编视图(指令视图)并开始按F11(单步)键,并记住你击中它的次数。
您将看到它进入循环,将i
与25进行比较,然后开始执行cout
行的代码。这涉及递增letter
,然后进入cout的<<
例程。它在那里做了很多事情,可能会深入到子程序等等,最后回来,返回一个对象。然后它将"\t"
作为参数推送并将其传递给该对象,然后返回并执行之前所做的所有操作。然后它需要number
,递增它,并将其传递给接受整数的cout::<<
例程,调用函数将其转换为字符串(涉及循环),然后执行所有操作之前做过将该字符串循环到输出缓冲区并返回。
累?你还没有完成。必须输出endl
,当发生这种情况时,它不仅会将"\n"
放入缓冲区,而且会调用系统例程将该缓冲区刷新到您发送的文件或控制台。 I / O。你可能不会F11,但请放心,它需要很多周期,直到I / O完成才会返回。
到目前为止,你的F11计数应该在几千,或多或少的附近。
最后,你出来并转到++i
语句,该语句需要1或2条指令,然后跳回到循环的顶部以开始下一次迭代。
现在,你还在担心循环的效率吗?
有一种更简单的方法可以说明这一点,而且它同样具有指导性。围绕整个代码包裹一个无限循环,使其永远运行。在它运行时,点击IDE中的“暂停”按钮,然后查看调用堆栈。 (This is called a "stackshot".)如果你多次这样做,你会很清楚它是如何花费时间的。这是一个例子:
NTDLL! 7c90e514()
KERNEL32! 7c81cbfe()
KERNEL32! 7c81cc75()
KERNEL32! 7c81cc89()
MSVCRTD! 1021bed3()
MSVCRTD! 1021bd59()
MSVCRTD! 10218833()
MSVCRTD! 1023a500()
std::_Fputc() line 42 + 18 bytes
std::basic_filebuf<char,std::char_traits<char> >::overflow() line 108 + 25 bytes
std::basic_streambuf<char,std::char_traits<char> >::sputc() line 85 + 94 bytes
std::ostreambuf_iterator<char,std::char_traits<char> >::operator=() line 304 + 24 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Putc() line 633 + 32 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Iput() line 615 + 25 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::do_put() line 481 + 71 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::put() line 444 + 44 bytes
std::basic_ostream<char,std::char_traits<char> >::operator<<() line 115 + 114 bytes
main() line 43 + 96 bytes
mainCRTStartup() line 338 + 17 bytes
我做了很多次,而不是ONCE在外部i<=25
循环的代码中停止了。所以优化这个循环就像是一个很好的比喻:“理发减肥”。
答案 5 :(得分:1)
由于没有其他人提到它:具有固定数量的迭代,这也是使用do..while
进行后置条件迭代的候选者。
char letter = 'a';
do {
std::cout << letter << "\t" << static_cast<int>( letter ) << std::endl;
} while ( ++letter <= 'z' );
但是,如Patrick's answer所示,for
成语通常较短(在这种情况下为行数)。
答案 6 :(得分:1)
您可以将char提升为int ...
//characters and their corresponding integer values
#include"../../std_lib_facilities.h"
int main()
{
char a = 'a';
while(a<='z'){
cout<<a<<'\t'<<a*1<<'\n'; //a*1 => char operand promoted to integer!
++a;
}
cout<<endl;
}
答案 7 :(得分:0)
增加三个单独的变量可能有点令人困惑。这是一种可能性:
for (int i = 0; i != 26; ++i)
{
int chr = 'a' + i;
std::cout << static_cast<char>(chr) << ":\t" << chr << std::endl;
}
请注意,使用for
循环保留了在一个位置设置,测试和递增循环变量的所有逻辑。
答案 8 :(得分:0)
此时,我不会担心微优化,例如编写像这样的小循环的有效方法。你有什么允许for
循环很好地完成工作,但如果你对while
更熟悉,你应该使用它。但我不确定这是不是你的问题。
我认为你没有正确理解这个问题。您正在编写代码,知道'A'
是65.练习的重点是在您的系统上打印'A'
到'Z'
的值,而不知道它们具有什么价值。
现在,要获得字符c
的整数值,您可以执行:static_cast<int>(c)
。我相信这就是你所要求的。
我没有编写任何代码,因为这样做会更有趣。
专家提问:在C中,我知道'a'
... 'z'
不需要连续值('A'
... 'Z'
相同)。 C ++也是如此吗?我会这么认为,但是Stroustrup的书似乎不太可能假设这一点。
答案 9 :(得分:0)
感谢您的帮助..我写下的所有内容都是
int main()
{
char letter = 96;
int number = letter;
int i = 0;
while(i <26)
{
cout <<++letter <<":" <<++numbers <<" ";
++i;
}
效果很好......现在很容易理解。
答案 10 :(得分:0)
我试过这个并且工作得很好:
char a = 'a';
int i = a; //represent char a as an int
while (a <= 'z') {
cout << a << '\t' << i << '\n';
++a;
++i;
}
答案 11 :(得分:0)
使用C ++的编程原理和实践(第二版)| Bjarne Stroustrup
第4章-计算(尝试此#3-字符循环)
字符'b'是char('a'+ 1),'c'是char('a'+ 2),依此类推。 编写带有相应整数值的字符表的循环: a 97 b 98。 。 。 z 122
这就是我解决问题的方式(来自10年前:D)
我是一个新生,所以我现在才开始读这本书...只想输入我的解决方案
#include <iostream>
using namespace std;
int main()
{
int i = 0; // start from 0
while (i < 26) {
int char_val = 97; // try changing the val 97 to 'a', same result
cout << char('a' + i) << '\t' << int(char_val + i) << '\n';
++i;
}
return 0;
}
我首先分析了一个问题,即知道'a'的char值是97到'z'来解决它。根据此ASCII表
现在,我们对如何解决上述问题有了更清晰的了解。