您的位置:首页 > 编程语言 > C语言/C++

一个基本算法题暴露出来的C++基础不扎实

2013-06-01 23:56 441 查看
好久没有写算法了,写算法都手生了,这可不利于找工作呀,打算坚持每周看一下算法方面的相关知识。今天是第一次,所以就入门一下吧,看了一下鸡兔同笼的问题。问题如下:

问题描述

一个笼子里面关了鸡和兔子(鸡有2 只脚,兔子有4 只脚,没有例外)。已经知道了笼

子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物

输入数据

第1 行是测试数据的组数n,后面跟着n 行输入。每组测试数据占1 行,包括一个正整

数a (a < 32768)。

输出要求

n 行,每行输出对应一个输入。输出是两个正整数,第一个是最少的动物数,第二个是

最多的动物数,两个正整数用空格分开。如果没有满足要求的情况出现,则输出2 个0。

输入样例

2

3

20

输出样例

0 0

5 10

题很简单,所以很快就写出了代码,如下:

#include <iostream>

int main(){
int cnt;
std::cin>>cnt;
for(int i=0;i<cnt;++i){
int legCnt = 0;
std::cin>>legCnt;
if(legCnt & 0x1){
std::cout <<0 <<" "<<0<<std::endl;
}else{
int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;
int cntMax = legCnt>>1;
std::cout << cntMin<<" " << cntMax<<std::endl;
}
}
}

运行了一下,结果竟然有问题,输入20时,输出时0 10,第一个最小的动物数明显计算有误,然后仔细看了一下代码, 问题出在一下语句中:

int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;

其实逻辑很简单,最小的动物数应该时除以4,如果还剩2条腿,则在加一。理论上是没有问题的,但是上面的语句就是输出有误。然后改动如下就可以了

int cntMin= (legCnt>>2) + ((legCnt&0x2) ? 1 :0);

可以看出是由于运算符号的优先级引起的问题,然后又温了一下书:

在C/C++中,上面语句中涉及的运算符有 >> , + , & 和 ? : 四个,这四个的优先级从高到低依次为:

+, >>, & , ? :

这样,int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;就被编译成一下运算顺序

int cntMin = ((legCnt>>(2+legCnt))&0x2)? 1 : 0;

所以才会得出20个腿算出的 最小可能动物数是 0。

其实问题很简单的, 但是反映出对于C++的运算优先顺序还是不够熟悉。以为自己做的不错,结果一个小问题,就能查出自己的基本功有问题呀。还是要多练习一下了。wiki中找到 C/C++的运算优先级列在如下:

优先级运算符叙述示例重载性结合性
1
::
作用域解析(C++专有)
Class::age = 2;
由左至右
2
++
后缀递增i++
--
后缀递减i--
{}
组合{i++;a*=i;}
()
函数调用或变量初始化c_tor(int x, int y) : _x(x), _y(y * 10) {}
[]
数组访问array[4] = 2;
.
以对象方式访问成员obj.age = 34;
->
以指针方式访问成员ptr->age = 34;
dynamic_cast
运行时检查类型转换(C++专有)Y& y = dynamic_cast<Y&>(x);
static_cast
未经检查的类型转换(C++专有)Y& y = static_cast<Y&>(x);
reinterpret_cast
重定义类型转换(C++专有)int const* p = reinterpret_cast<int const*>(0x1234);
const_cast
更改非常量属性(C++专有)int* q = const_cast<int*>(p);
typeid
获取类型信息(C++专有)std::type_info const& t = typeid(x);
3
++
前缀递增++i由右至左
--
前缀递减--i
+
一元正号int i = +1;
-
一元负号int i = -1;
!

not
逻辑非
!
的备用拼写
if (!done) …
~

compl
按位取反
~
的备用拼写
flag1 = ~flag2;
(type)
强制类型转换int i = (int)floatNum;
*
取指针指向的值int data = *intPtr;
&
取变量的地址int *intPtr = &data;
sizeof
某某的大小size_t s = sizeof(int);
new
动态内存分配(C++专有)long* pVar = new long;
new[]
动态数组内存分配(C++专有)long* array = new long[20];
delete
动态内存释放(C++专有)delete pVar;
delete[]
动态数组内存释放(C++专有)delete [] array;
4
.*
成员对象选择(C++专有)obj.*var = 24;由左至右
->*
成员指针选择(C++专有)ptr->*var = 24;
5
*
乘法int i = 2 * 4;
/
除法float f = 10.0 / 3.0;
%
模数(取余)int rem = 4 % 3;
6
+
加法int i = 2 + 3;
-
减法int i = 5 - 1;
7
<<
比特左移int flags = 33 << 1;
>>
比特右移int flags = 33 >> 1;
8
<
小于关系if (i < 42) …
<=
小于等于关系if (i <= 42) ...
>
大于关系if (i > 42) …
>=
大于等于关系if (i >= 42) ...
9
==

eq
等于关系
==
的备用拼写
if (i == 42) ...
!=

not_eq
不等于关系
!=
的备用拼写
if (i != 42) …
10
&

bitand
比特 AND
&
的备用拼写
flag1 = flag2 & 42;
11
^

xor
比特 XOR(独占or)
^
的备用拼写
flag1 = flag2 ^ 42;
12
|

bitor
比特 OR(包含or)
|
的备用拼写
flag1 = flag2 | 42;
13
&&

and
逻辑 AND
&&
的备用拼写
if (conditionA && conditionB) …
14
||

or
逻辑 OR
||
的备用拼写
if (conditionA || conditionB) ...
15
c?t:f
三元条件运算int i = a > b ? a : b;由右至左
16
=
直接赋值int a = b;
+=
以和赋值a += 3;
-=
以差赋值b -= 4;
*=
以乘赋值a *= 5;
/=
以除赋值a /= 2;
%=
以取余数赋值a %= 3;
<<=
以比特左移赋值flags <<= 2;
>>=
以比特右移赋值flags >>= 2;
&=

and_eq
以比特AND赋值
&=
的备用拼写
flags &= new_flags;
^=

xor_eq
以比特XOR赋值
^=
的备用拼写
flags ^= new_flags;
|=

or_eq
以比特OR赋值
|=
的备用拼写
flags |= new_flags;
17
throw
抛出异常throw EClass(“Message”);
18
,
逗号运算符for (i = 0, j = 0; i < 10; i++, j++) …由左至右
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: