Mr. Kin's Blog

计算机知识分享/软件应用讲解

第三章:字符串、向量和数组

练习3.1

使用恰当的using声明重做1.4.1节(第11页)和2.6.2节(第67页)的练习。

因为较为简单,每个小节就只写一个练习了。

using声明易造成名字冲突:

  • 使用using声明,一般建议为每个名字做独立的using声明,例如using std::cin,不太建议使用整个命名空间,例如using namespace std,易造成名字冲突。
  • 头文件不应包含using声明:易造成名字冲突。

练习3.2

编写一段程序从标准输入中一次读入一行,然后修改该程序使其一次读入一个词。

练习3.3

请说明string类的输入运算符和getline函数分别是如何处理空白字符的。

  • 类似 cin >> str 的读取,string对象会忽略开头的空白(空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白为止。
  • 类似 getline(cin, str) 的读取,string对象会从给定的输入流中读取内容,直到遇到换行符为止(换行符被读进来,但不会存放进对象)。

练习3.4

编写一段程序读取两个字符串,比较其是否相等并输出结果。如果不相等,输出较大的那个字符串。改写上述程序,比较输入的两个字符串是否等长,如果不等长,输出长度较大的那个字符串。

练习3.5

编写一段程序从标准输入中读入多个字符串并将它们连接在一起,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符串分隔开来。

string对象操作的一些总结:

  • 定义、初始化和基本操作看下面代码(书本见P76和P77)。
  • 关系运算符<、<=、>、>=比较规则:依次比较每个位置上的字符大小,若都一样时,则长度更长的字符串就更大。
  • string和字符字面值和字符串字面值混在一条语句中,必须确保加法运算符「+」两侧至少有一个string对象(因为标准库可以将字面值转换为string对象,但不允许两个字面值直接相加)
  • size()函数返回的是string::size_type类型的值,是无符号数。表达式中如果有size(),切记不要再使用int。如果需要定义变量存储size()函数,使用autodecltype,例如auto len = str.size()
  • 注意字符串字面值不是string对象,和string是不同的类型(因为需要兼容C)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 定义和初始化(等号是拷贝初始化,圆括号是直接初始化)
string s1; //默认初始化为空串
string s2(s1); // s2是s1的副本
string s2 = s1; // 同上,不过是拷贝初始化
string s3 = ("hello"); // s3是字面值"hello"的副本(不包括字面值中的空字符)
string s3 = "hello"; // 同上
string s4(n, 'c'); // s4初始化为由n个字符c组成的串

// 基本操作
os << s; // 将s写到输出流os,返回os
is >> s; // 将输入流is读取字符串赋值给s,字符串以空白分割,返回is
getline(is, s); // 从输入流is读取一行赋值给s,返回is
s.empty(); // s为空返回true,否则返回false
s.size(); // 返回s中字符的个数
s[n]; // 返回s中第n个字符的引用,下标从0计起。
s1 + s2; // 返回s1和s2连接后的结果
s1 = s2; // 用s2的副本代替s1中原来的字符
s1 == s2; // 判断两个string对象是否相等,对字母大小写敏感
s1 != s2;
<, <=, >, >= ; // 利用字符在字典中的顺序进行比较,对字母大小写敏感
阅读全文 »

第二章:变量和基本类型

练习2.1

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

C++ 规定 shortint 至少16位,long 至少32位,long long 至少64位。
带符号类型能够表示正数、负数和 0 ,而无符号类型只能够表示 0 和正整数。
通常,单精度float用1个字表示(4个字节,32bit),双精度double用2个字表示(8个字节,64bit)。

用法(类型的选择):

  • 如果确认数据是非负的,那么就使用 unsigned 无符号类型。
  • 一般使用 int 做整数运算,short 因为太小在实际中用的少,long 通常和 int 有着相同的大小。如果数据非常大,可以使用 long long
  • 算术表达式不用 charbool ,这二者只建议用于存放字符或布尔值。因为char在某些机器上是有符号的,在另一些机器上是无符号型的,则使用 char 进行运算容易出问题。如果需要较小的整数,就明确指定 signed char 或者 unsigned char
  • 执行浮点运算时用 double ,因为 float 通常精度不够而且双精度浮点数和单精度浮点数的计算代价相差无几。

参考:

float有效位理解

IEEE规定float为32bit,尾数用23位存储,加上隐含的小数点前的1位1,2^(23+1) = 16777216。因为 10^7 < 16777216 < 10^8,所以说单精度浮点数的有效位数是7位(能保证7位有效数字,当然,并非说第8位一定是非有效数字,它也有可能是准确的)。

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
float i = 12345678.76348;
float j = 46857.9874;
printf("%f\n%f\n%.3f\n%.8f", i, j, j, j);
return 0;
}

输出:

1
2
3
4
12345679.000000
46857.988281
46857.988
46857.98828125

从以上数据可以看出,第八个数字之后就不精确了。另外,要注意,有效数字的位数与指定输出的小数位数(%.7f,保留7位有效数字)是两码事,如第三第四个输出,这个是程序指定的输出格式,和类型本身能够存储的精度不是一回事。

C++算术类型

类型含义最小尺寸
bool布尔类型未定义
char字符8位
wchar_t宽字符16位
char16_tUnicode字符16位
char32_tUnicode字符32位
short短整型16位
int整型16位
long长整型32位
long long长整型64位
float单精度浮点数6位有效数字
double双精度浮点数10位有效数字
long double扩展精度浮点数10位有效数字

练习2.2

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

使用 doublefloat

练习2.3

读程序写结果。

1
2
3
4
5
6
7
8
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;

输出:

1
2
3
4
5
6
32
4294967264 // -32=(-1)×2^32+4294967264
32
-32
0
0

类型转换的总结

  • 非布尔类型转换布尔类型时,0转换成false,非0则true(包括负数)。
  • 布尔值转换非布尔类型时,false转换为0,true则1。
  • 浮点数转换整数时,仅保留小数点之前的部分(即整数部分,小数部分直接截断),这是精度损失;当浮点数表示的值大过整型值,会发生溢出。
  • 整数转浮点数时,小数部分记为0。不会发生溢出,但当整数值数据较大时,转换浮点数可能会发生精度丢失。例如,int 有31bit用来拓展精度,float 只有24bit,即当int值大于2^24或者小于-2^24时,转换float就会精度丢失。
  • 给无符号类型赋值超过其表示范围时,实际值是初始值对无符号类型表示数值总数取模后的余数。8bit的unsigned char表示0-255,赋值超出范围时,实际值为该值对256取模后的余数。因此将-1赋给8bit的unsigned char时,结果值为255。
  • 赋给带符号类型一个超出范围的值时,结果是未定义的。此时,程序可能工作、可能崩溃、也可能生成垃圾数据。

无符号类型和有符号类型计算,结果为负数时,结果值的计算方法

给定一个正整数p,任意一个整数n,一定存在等式n=kp+r

其中k、r是整数,且0<=r<p,称k为n除以p的商,r为n除以p的余数。

定义取模运算:a % p(或a mod p),表示a除以p的余数。

实际运用场景:将-1赋给8bit的unsigned char时,结果值为255。
计算过程:-1=(-1)×256+255

二进制表示的本质:用补码表示,先看原码(符号位为1,数值位只有一个1)对原码取反加1(符号位不变),转换成补码后,所有位都是1。

类型转换的使用场景总结

  • 不要混用带符号类型和无符号类型:表达式中含有这两种类型时,带符号数会自动转换成无符号数(此时,一个负数转换成无符号数后,真值将很大)。
  • 循环中的判断条件慎用无符号数:无符号数表示范围为正整数,不会小于0,尤其是当循环的临界条件是0时。如以下代码,就是死循环,当u=0时,循环条件依然满足,继续执行,--u就是-1,但无符号数只能表示整数,-1被自动地转换成一个合法的无符号数,即正整数。
1
2
for (unsigned u = 10; u >= 0; --u)
std::cout << u << std::endl;

解决方式:

  1. 用有符号类型
  2. 用while语句,代码如下。
  3. 类似while语句,将for语句的--u置于cout语句中。
  4. 2和3本质上就是保证u不会变为-1。
1
2
3
4
5
6
unsigned u = 11;
while (u > 0)
{
--u;
std::cout << u << std::endl;
}

练习2.4

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

阅读全文 »

第一章:开始

练习1.1

查阅你使用的编译器文档,确定它所使用的文件命名约定。编译并运行第2页的main程序。

1
2
3
4
int main()
{
return 0;
}

练习1.2

改写程序,让它返回-1。返回值-1通常被当作程序错误的标识。重新编译并运行你的程序,观察你的系统如何处理main返回的错误标识。

1
2
3
4
int main()
{
return -1;
}

编译后在命令行运行程序,之后通过echo查看。

cmd: echo %ERRORLEVEL%,输出-1

bash: echo $?,输出127

练习1.3

编写程序,在标准输出上打印 Hello, World。

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

int main()
{
std::cout << "Hello, World" << std::endl;
return 0;
}

练习1.4

我们的程序使用加法运算符+来将两个数相加。编写程序使用乘法运算符*,来打印两个数的积。

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

int main()
{
std::cout << "Enter two numbers:" << std::endl;
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout << "The product of " << v1 << " and " << v2
<< " is " << v1 * v2 << std::endl;
return 0;
}

练习1.5

我们将所有输出操作放在一条很长的语句中。重写程序,将每个运算对象的打印操作放在一条独立的语句中。

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

int main()
{
std::cout << "Enter two numbers:" << std::endl;
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout << "The product of ";
std::cout << v1;
std::cout << " and ";
std::cout << v2;
std::cout << " is ";
std::cout << v1 * v2;
std::cout << std::endl;
return 0;
}
阅读全文 »

1   计划重启缘由

2018年末之际,我发布了一篇博文「翻译规划(作废)」,计划着翻译一些视频教程和文档等,但因诸多原因,一直未能有效按计划进行,后来也就不了了之,将此篇博文就此作废。现在看来,这个计划完成的进度可能都不及5%,真的是个巨难填补的巨坑啊,哈哈哈……

翻译本身就是无偿行为,毕竟原作品不是自己创作的,平台投稿时又无法投原创自制。一想到这个,就没啥了驱动力,毕竟没法总是为爱发电。

由于编写批处理工具时需要进行测试,因此又接触到了视频压制和字幕处理。在测试的过程中,又有想法要重新开启翻译计划。

不过本次的计划重启,与上次那样庞大的目标的不同,这次的翻译目标仅限于自己的看过并感兴趣的视频。

2   翻译计划表

注:点击列表中的英文视频名即可访问相应的视频链接。

2.1   Blender开放动画电影

视频名中译名完成进度字幕下载
Sprite Fright惊悚小精灵已翻译点击跳转
The Daily Dweebs每日蠢事已翻译点击跳转

2.2   Blender fundamental 教程

视频名中译名完成进度字幕下载

1   翻译的感想

抽空翻译了blender的开放动画电影《Sprite Fright》,该动画电影是一部恐怖喜剧,台词有部分俚语,总体的翻译难度比一般的教学类视频要高一点。

2   观看动画电影

3   下载字幕

字幕采用aegisub软件制作,已同步分享至Github仓库「OpenDocs」,有需要的朋友可下载学习或者观看。

4   本期翻译的英语词汇总结

  • tree hugger 抱树者(意指给环保主义者贴上过于情绪化和不理性的标签)
  • sugar buns/sweet cakes/love muffin 这三个都是用作爱称,意思同sweetheart
  • get wasted 喝醉,形容大醉
  • way ahead of you 形容比别人更早地完成或者解决某事
  • dilly-dally v. 犹豫,磨蹭
  • fungis n. 真菌(这个用法有问题,fungi本身就是复数,加s应该只是为了配合台词fun guys)
  • dorkwad n. 傻瓜,呆子(俚语,意思同dork)
  • be supposed to do/be sth. 应当……
  • piss break 指上厕所的休息过程(例如在听一个无聊的讲座时,可以说piss break,然后离场去休息)
  • make yourself useful 让对方别闲着,干点事情(差不多就是get off your ass and do something)
  • innit 表示强调,用于陈述句后代替附加疑问句(tag question)
    • She's a real weenie that one, innit? 她是一个真正的窝囊废,不是吗?(innit相当于isn’t she)
  • gnome n. 守护精灵(童话故事中的地下宝藏守护神,外形像戴着尖顶帽的小人)
  • shag v. 和……性交(该词我根据上下文来翻译了)
    • It's like a gnome shagged a mushroom. 这就像一个守护精灵头顶一只蘑菇
  • peppermint n. (常用于糖果的)薄荷
  • sprite n. 小精灵(该词本身只是名词,但动画中原创了动词用法,因此我根据上下文来翻译动词意思了)
    • We sprite balance to the forest. 我们让森林保持平衡
    • Sprite them! 净化他们
  • son of a spriteberry 狗娘养的(意思同son of a bitch,不过动画中小精灵用的是spriteberry)
  • treat sth. as sth. 把……视为……,把……看作……

5   参考文献

[1] BRIDGERS B. What it Means to be Called a Tree Hugger[EB/OL]. https://www.newamerica.org/millennials/dm/what-it-means-be-called-tree-hugger/.
[2] What does Way ahead of you. mean?[EB/OL]. https://hinative.com/en-US/questions/166902.
[3] What is the difference between get lit and get wasted and get hammered?[EB/OL]. https://hinative.com/en-US/questions/17881208.
[4] What does Make yourself useful. mean?[EB/OL]. https://hinative.com/en-US/questions/15910440.

R.I.P