c++_primer(2)变量和基本类型


本文主要内容变量和基本类型

练习2.1:类型int、long、long long和short的区别是什么?无符号类型和带符号类型的区别是什么?float和double的区别是什么?

int、long、long long和short它们的尺寸可能不一样,C++标准给出了最小尺寸要求,编译器可以给予更大的尺寸。无符号类型只能表示大于等于0的数。float和double的尺寸通常不一样,float通常有7个有效位,double通常有16个。

练习2.2:计算按揭贷款时,对于利率、本金和付款分别应选择何种数据类型?说明你的理由。

使用double,因为都要使用小数。

练习2.3:读程序写结果。

1
2
3
4
5
6
7
8
unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl; --> 32
std::cout << u - u2 << std::endl; --> 4294967264 2^32-2?
int i = 10, i2 = 42;
std::cout << i2-i<std::endl; -- 32
std::cout << i - i2<<std::endl; --> -32
std::cout << i - u<< std::endl; --> 0
std::cout << u - i<<std::endl; --> 0

练习2.4:编写程序检测你的估计是否正确,如果不正确,请仔细研读本节直到弄明白问题所在。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

int main()
{
unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl;
std::cout << u - u2 << std::endl;

int i = 10, i2 = 42;
std::cout << i2-i<<std::endl;
std::cout << i - i2<<std::endl;
std::cout << i - u<< std::endl;
std::cout << u - i<<std::endl;

return 0;
}

练习2.5:指出下述字面值的数据类型并说明每一组内几种字面值的区别:

(a) ‘a’, L’a’, “a”, L”a”
(b) 10, 10u, 10L, 10uL, 012, 0xC
(c) 3.14, 3.14f, 3.14L
(d) 10, 10u, 10., 10e-2

(a) ‘a’的类型是char,L‘a’的类型是wchar_t,”a“的类型是以空字符结尾的char数组,L”a”的类型是以空字符结尾的wchar_t数组。
(b) 10的类型是int,10u的类型是unsigned int,10L的类型是long,10uL的类型是unsigend long,012的类型是int,是一个用八进制表示的整数;0xC的类型是int,是一个用十六进制表示的整数。
(c) 3.14的类型是double,3.14f的类型是float,3.14L的类型是long double。
(d) 10的类型是int,10u的类型是unsigned int,10.的类型是double,10e-2的类型是double。

练习2.6:下面两组定义是否有区别,如果有,请叙述之:

1
2
3
4
5
6
7
* int month = 9, day = 7;
* int month = 09, day = 07;
*/

/*
* 第一行定义的是十进制整数。
* 第二行中int mount = 09是非法的,9超出了八进制的表示范围;day = 07定义的是八进制整数。

练习2.7:下述字面值表示何种含义?它们各自的数据类型是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 /** (a) "Who goes with F\145rgus?\012"
* (b) 3.14e1L (c) 1024f (d) 3.14L
*/

/*
* (a) 表示字符串字面量:"Who goes with Fergus?(换行)"
* (b) long double
* (c) float
* (d) long double
*
* ASCII码参考:http://www.asciitable.com/
*/

#include <iostream>

int main()
{
std::cout << "Who goes with F\145rgus?\012";

return 0;
}

练习2.8:请利用转义序列编写一段程序,要求先输出2M,然后转到新一行。修改程序使其先输出2,然后输出制表符,再输出M,最后转到新一行。

1
2
3
4
5
6
7
8
9
10
#include <iostream>

int main()
{
std::cout << "\x32\x4d\n"; //采用八进制的形式表示

std::cout << "\x32\t\x4d\n";

return 0;
}

练习2.9:解释下列定义的含义。对于非法的定义,请说明错在何处并将其改正。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* (a) std::cin >> int input_value;		(b) int i = { 3.14 };
* (c) double salary = wage = 9999.99; (d) int i = 3.14;
*/

/*
* (a) 格式错误。改正如下:
*
* int input_value = 0;
* std::cin >> input_value;
*
* (b) 错误,列表初始化时,如果存在丢失信息的风险,编译器会报错。改为:double i = { 3.14 };
*
* (c) 格式错误。改为:double salary = 9999.99, wage = 9999.99; 或者先定义wage。
*
* (d) 正确。
*/

#include <iostream>

int main()
{
//std::cin >> int input_value;
int input_value = 0;
std::cin >> input_value;

//int i = { 3.14 };
double i = { 3.14 };

//double salary = wage = 9999.99;
double salary = 9999.99, wage = 9999.99;

int i2 = 3.14;

return 0;
}

练习2.10:下列变量的初值分别是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* std::string global_str;
* int global_int;
* int main()
* {
* int local_int;
* std::string local_str;
* }
*/

/*
* global_str是一个空串,global_int是0,local_int的值是0,local_str是一个空串。
*/

#include <iostream>
#include <string>

std::string global_str;
int global_int;
int main()
{
int local_int;
std::string local_str;

std::cout << "global_str: " << global_str << std::endl;
std::cout << "global_int: " << global_int << std::endl;
std::cout << "local_int: " << local_int << std::endl;
std::cout << "local_str: " << local_str << std::endl;

return 0;
}

运行结果

1
2
3
4
global_str: 
global_int: 0
local_int: 0
local_str:

练习2.11:指出下面的语句是声明还是定义:

(a) extern int ix = 1024;
(b) int iy;
(c) extern int iz;

(a) 定义。(b) 定义。(c) 声明。

1
2
3
变量的声明规定了变量的类型和名字; 变量的定义规定了变量的类型和名字,还申请存储空间,也可能会为变量赋一个初始值。
C++ Primer Plus(第六版)原文:
定义声明,简称为定义。这意味着它将导致编译器为变量分配内存空间。在较为复杂的情况下,还可能有引用声明。这些声明命令计算机使用在其他地方定义的变量。通常,声明不一定是定义。

为什么int iy 属于定义,因为系统会自动赋予伪随机初始值。来源网络。

练习2.12:请指出下面的名字中哪些是非法的?

(a) int double = 3.14; (b) int _;
(c) int catch-22; (d) int 1_or_2 = 1;
(e) double Double = 3.14;

非法的有:(a), (c), (d)。

练习2.13:下面程序中j的值是多少?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 /*
* int i = 42;
* int main()
* {
* int i = 100;
* int j = i;
* }
*/

/*
* 100。
*/

#include <iostream>

int i = 42;
int main()
{
int i = 100;
int j = i;

std::cout << j << std::endl;

return 0;
}

练习2.14:下面的程序合法吗?如果合法,它将输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* int i = 100, sum = 0;
* for (int i = 0; i != 10; ++i)
* sum += i;
* std::cout << i << " " << sum << std::endl;
*/

/*
* 合法,将输出:100 45(换行)
*/

#include <iostream>

int main()
{
int i = 100, sum = 0;
for (int i = 0; i != 10; ++i)
sum += i;
std::cout << i << " " << sum << std::endl;

return 0;
}

练习2.15:下面的哪个定义是不合法的?为什么?

(a) int ival = 1.01; (b) int &ival1 = 1.01;
(c) int &rval2 = ival; (d) int &rval3;

(b)不合法,因为引用不能绑定到一个字面值上。
(d)不合法,因为引用必须初始化。

练习2.16:考察下面的所有赋值然后回答:哪些赋值是不合法的?为什么?哪些赋值是合法的?它们执行了什么样的操作?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* int i = 0, &r1 = i;	double d = 0, &r2 = d;
* (a) r2 = 3.14159; (b) r2 = r1;
* (c) i = r2; (d) r1 = d;
*/

/*
* (a)合法,将3.14159赋值给r2绑定到的对象d。
* (b)合法,将r1绑定到的对象i的值赋值给r2绑定到的对象d。
* (c)合法,将r2绑定到的对象d的值赋值给i。
* (d)合法,将d的值赋值给r1绑定到的对象i。
*/

int main()
{
int i = 0, &r1 = i; double d = 0, &r2 = d;

r2 = r1;

return 0;
}

练习2.17:执行下面的代码段将输出什么结果?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 /*
* int i, &ri = i;
* i = 5; ri = 10;
* std::cout << i << " " << ri << std::endl;
*/

/*
* 10 10(换行)
*/

#include <iostream>

int main()
{
int i, &ri = i;
i = 5; ri = 10;
std::cout << i << " " << ri << std::endl;

return 0;
}

练习2.18:编写代码分别更改指针的值以及指针所指对象的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main()
{
int a = 0;
int *p = nullptr; //空指针

p = &a;
*p = 10;

std::cout << *p << std::endl;

return 0;
}

练习2.19:说明指针和引用的主要区别。

指针是一个对象,因此可以通过赋值来改变其值。
引用是一个对象的别名,必须初始化以绑定到对象,且之后无法更改绑定的对象。

练习2.20:请叙述下面这段代码的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/ *
* int i = 42;
* int *p1 = &i;
* *p1 = *p1 * *p1;
*/

/*
* 通过指针p1,求得i的值的平方,将其赋值给i。
*/

#include <iostream>

int main()
{
int i = 42;
int *p1 = &i;
*p1 = *p1 * *p1;

std::cout << "42 * 42 = " << 42 * 42 << std::endl;
std::cout << "i = " << i << std::endl;

return 0;
}

练习2.21:请解释下述定义。在这些定义中有非法的吗?如果有,为什么?

int i = 0;
(a) double* dp = &i; (b) int *ip = i; (c) int *p = &i;

(a)非法,dp所指的对象类型必须是int。
(b)非法,不能把int变量赋值给一个指针。

c++学习笔记(3)注释和while的使用

7、注释的正确使用

练习1.7:编译一个包含不正确的嵌套注释的程序,观察编译器返回的错误信息

1
2
3
4
5
6
7
8
9
#include <iostream>
/*
* /*这是一个错误的嵌套注释*/
*
*/
int main()
{
return 0;
}

error: expected unqualified-id before ‘/’ token

错误的嵌套形式,/**/只和最近的进行匹配。

8、注释的正确使用

练习1.8:指出下列哪些输出语句是合法的(如果有的话)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// std::cout << "/*";
// std::cout << "*/";
// std::cout << /* "*/" */;
// std::cout << /* "*/" /* "/*" */;

// 预测编译这些语句会产生什么样的结果,实际编译这些语句来验证你的答案(编写一个小程序,每次将上述一条语句作为其主体),改正每个编译错误

/*
* 只有第三个不合法,在其最后添加一个"
*/

// 结果: /**/ */ /*

#include <iostream>

int main()
{
std::cout << "/*";
std::cout << "*/";
std::cout << /* "*/" */";
std::cout << /* "*/" /* "/*" */;

return 0;
}

9、while循环的使用

练习1.9:编写程序,使用while循环将50到100的整数相加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int main()
{
int sum = 0, i = 50;

while (i <= 100) {
sum += i;
++i;
}

std::cout << "Sum of 50 to 100 inclusive is " << sum << std::endl;

return 0;
}

leetcode70:爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

1
2
3
4
5
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

示例 2:

1
2
3
4
5
6
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶

解题思路:

假设我们现在站在台阶ii上面。对于我们如何到达的ii,有且仅有两种可能:

  1. 我们之前在台阶i-1上面,然后用一步走到了台阶ii上面;

  2. 我们之前在台阶i-2上面,然后用两步走到了台阶ii上面。

设函数f(i)f(i)为到达ii的所有可能的方法数量。则有
f(i) = f(i-1) + f(i-2)f(i)=f(i−1)+f(i−2),
即到达ii的方法数等于到达i-1i−1的方法数加上到达i-2i−2的方法数。大的问题depends on小的问题,这就是最基本的动态规划的原则。

作者:what-to-do
链接:https://leetcode-cn.com/problems/climbing-stairs/solution/solution-python3-by-bu-zhi-dao-gan-sha/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

|