记录C/C++语言相关的问题。

算法可视化:https://visualgo.net/en

<data structure and algorithm in c++> By Adam 有免费电子版

1. while( ) 与 Ctrl+D

Ctrl+D后,默认还是要执行完后面的程序。

  1. void multi_input(void)
  2. {
  3. int sum = 0;
  4. int value;
  5. while(std::cin >> value)
  6. {
  7. cout << "-" << endl;
  8. sum += value;
  9. }
  10. cout << sum << endl;
  11. }
  12.  
  13. multi_input()
  14.  
  15. multi_input()

第一个multi_input()执行中,执行Ctrl+D后:

一旦测试失败,while 终止并退出循环体,执行 while 之后的语句。

该语句在输出 sum 后输出 endl,endl 输出换行并刷新与 cout 相关联的缓冲区。

最后,执行 return,通常返回零表示程序成功运行完毕。

2. c++英语学习

  1. 声明 Declarations
    定义 Definitions
  2.  
  3. 小括号 parenthesis [pə'renθɪsɪs]
  4. 中括号 square brackets
  5. 花括号 curly brace
  6.  
  7. 实参 argument
    形参 parameter
  8.  
  9. 操纵符 manipulator
    ...

3. 赋值越界

字符

C++ 中,把负值赋给 unsigned 对象是完全合法的,其结果是该负数对该类型的取值个数求模后的值。

所以,如果把 -1 赋给 8 位的 unsigned char, 那么结果是 255, 因为 255 是 -1 对256 求模后的值。

数字的最大值

float 型只能保证 6位有效数字,可能不够用;

double 型至少可以保证 10位有效数字 满足大部分计算的需要。

size of types

  1. #include<limits>
    cout << numeric_limits<double>::max() << endl;

字符串的不同类型

如果连接普通字符串字面值和宽字符串字面值,将会出现什么结果呢?例如:

  1. // Concatenating plain and wide character strings is undefined
  2. std::cout << "multi-line " L"literal " << std::endl;

其结果是未定义的,也就是说,连接不同类型的行为标准没有定义。

这个程序可能会执行,也可能会崩溃或者产生没有用的值,而且在不同的编译器下程序的动作可能不同。

wchar_t 

L'a' stored in wchar_t.

4. 数据间的转化

  1. unsigned int a = ;
  2. signed int b = -;  // “局部”大范围 --> 小范围
  3. cout << a*b << endl;

4294967295
-1 is promoted to unsigned int, but the binary representation stays
the same: 111111111111111111111111111 (32 bits)
The unsigned value is: 4294967295, therefore
4294967295 * 1 = 4294967295

auto 类型

自动去匹配可能的类型,有解的话就不会报错。

5. 运算符的优先级(precedence)

  1. int i = ;
  2. int j = (i = ) * i;
  3. cout << "j = " << j << endl;
  4.  
  5. j = 9;   // 因为括号优先级高

const

  The primary role of const is to specify immutability.

  1. const int a = ;
  2. const long &r = a;
    // Can refer to an object of a different (but related) type. 但还是不要这么做了吧,容易误会。

Jeff: const int val; int const val 目前编译器解释是一样的。

  1. int i = ;
  2. int *const p1 = &i; // we can't change the value of p1; const is top-level
  3. const int ci = ; // we cannot change ci; const is top-level

  4. const int *p2 = &ci; // we can change p2; const is low-level 指向的只是一个特定的类型
  5. const int *const p3 = p2; // right-most const is top-level, left-most is not
  6. const int &r = ci; // const in reference type is always low-level 引用的只是一个特定的类型

6. Function

Lvalue vs Rvalue

  • rvalue: the content in the vector   -- 内容/值 只会出现在RHS
  • lvalue: address of the vector      -- RHS, LHS都可能出现。

"传值"的英文叫法是:Call by value or Call by reference.

Return value

Make sure that do not return local object.

注意:Low-level是可以区分函数的定义的哦:)

7. Namespace

reference: http://www.jizhuomi.com/software/289.html

命名空间: 本质上讲namespace是对全局作用域的细分。

      将多个变量和函数等包含在内,使其不会与命名空间外的任何变量和函数等发生重命名的冲突。

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. // 命名空间JiZhuoMi
  5. namespace JiZhuoMi
  6. {
  7. char *szUrl = "www.jizhuomi.com";
  8. }
  9.  
  10. // 命名空间Software
  11. namespace Software
  12. {
  13. char *szUrl = "www.jizhuomi.com/software/";
  14. }
  15.  
  16. // 释放命名空间JiZhuoMi和Software
  17. using namespace JiZhuoMi;
  18. using namespace Software;
  19.  
  20. int _tmain(int argc, _TCHAR* argv[])
  21. {
  22. char *szUrl = "url";
  23. cout << szUrl << endl;
  24. return ;
  25. }

8. How to print

Reference: http://www.cplusplus.com/reference/ios/ios_base/fmtflags/

具有默认输出格式

cout 输出的数字的有效数字位数有默认的限制:6个有效数字。

  1. cout << "[" << << "]" << endl;
  2. std::cout << << std::endl;
  3. cout << "[" << << "]" << endl;
  4. std::cout << "In hex " << std::hex << << std::endl;
  5. cout << "[" << << "]" << endl;
  6. std::cout << 1331.123456 << std::endl;   // 只保留了俩位小数,看来默认是6个有效数字
  7. cout << "[" << << "]" << endl;
  8. std::cout.setf(std::ios::scientific, std::ios::floatfield);  // 设置了cout的属性为科学计数法
  9. cout << "[" << << "]" << endl;
  10. std::cout << 1331.123456 << std::endl;
  11. cout << "[" << << "]" << endl;
  12. std::cout << std::setprecision() << 1331.123456 << std::endl; // 进一步设置,科学技术法的小数点
  13. cout << "[" << << "]" << endl;
  14. std::cout << std::dec << << std::endl;   // 设置回了十进制
  15. cout << "[" << << "]" << endl;
  16. std::cout.width();  // 下一次 ONLY 写[八]个words.
  17. cout << "[" << << "]" << endl;
  18. std::cout << << std::endl;
  19. cout << "[" << << "]" << endl;
  20. std::cout.setf(std::ios::left, std::ios::adjustfield);
  21. cout << "[" << << "]" << endl;
  22. std::cout.width();  // 自动对齐的一种技巧
  23. cout << "[" << << "]" << endl;
  24. std::cout << << std::endl;
  25. cout << "[" << << "]" << endl;

16, 设置下次输出的一个下限。

自动对齐输出

15-22, 自动对齐的技巧。

  1. []
  2.  
  3. []
  4. In hex
  5. []
  6. 1331.12
  7. []
  8. []
  9. 1.331123e+03
  10. []
  11. 1.331e+03
  12. []
  13.  
  14. []
  15. []
  16.  
  17. []
  18. []
  19. [ ]
  20.  
  21. []

Result

9. cin的陷阱

【1】cin.getline(str, len):缓冲区有残留

当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. char str[];
  6. cin.getline(str, ); // input多少,这里都只从缓冲区 读取5个。剩下的就自动成为了下一次输入。
  7. cout<<str<<endl;
  8. cin.getline(str, );
  9. cout<<str<<endl;
  10. return ;
  11. }

【2】cin >>, 空格会成为终止

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. char str1[], str2[];
  6. cin>>str1;  // 输入:abcd efg. 第一次读取字符串时遇到空格则停止.
  7. cin>>str2;  // 缓冲区有残留数据,读入操作直接从缓冲区中取数据。
  8. cout<<str1<<endl;
  9. cout<<str2<<endl;
  10. return ;
  11. }

看来,比较稳妥的方式是:使用cin.getline(255)这种即可。

【3】cin.get(<char>)

空格不会成为终止(空格可能就是要输入的字符*_*),Enter可以。

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.   char c1, c2;
  6.   cin.get(c1);
  7.   cin.get(c2);
  8. cout<<c1<<" "<<c2<<endl; // 打印两个字符
  9. cout<<(int)c1<<" "<<(int)c2<<endl; // 打印这两个字符的ASCII值
  10. return ;
  11. }

自定义 终止符如何?

  1. #include <iostream>
  2. using namespace std;
  3. int main ()
  4. {
  5.   char ch, a[];
  6.   cin.get(a, , 'd'); //设置d为终止符
  7.   cin>>ch;
  8.   cout<<a<<endl;
  9.   cout<<(int)ch<<endl;
  10.   return ;
  11. }

注意:识别结束符,但不丢弃。

【4】灵活清空缓冲区

为什么ch的输出错了呢?

  1. #include <iostream>
  2. using namespace std;
  3. int main ()
  4. {
  5.   char ch, a[];
  6.   cin.getline(a, );  // 输入123456, a: 1234
  7.   cin>>ch;        // ch: 0, but not the ascii of '5'
  8.   cout<<a<<endl;
  9.   cout<<(int)ch<<endl;
  10.   return ;
  11. } 

所以,输入一次数据后,最好记得清空“input buffer"。灵活的清空方法如下:

  1. cin.ignore(numeric_limits<std::streamsize>::max(),’\n’);//清除输入缓冲区的当前行 
  2. cin.ignore(numeric_limits<std::streamsize>::max()); //清除输入缓冲区里所有内容 
  3. cin.ignore()//清除一个字符

10. 智能指针 - 类型转换

reference: http://www.jellythink.com/archives/205

C++中的类型转换分为两种:

    1. 隐式类型转换;
    2. 显式类型转换。(这里的重点)

在标准C++中有四个类型转换符:static_cast、dynamic_cast、const_cast和reinterpret_cast;

static_cast & dynamic_cast

执行非多态类型的转换,用于代替C中通常的转换操作。

  1. double myDouble = 3.14;
  2. int cast1 = (int)myDouble; // c-style
  3. int cast2 = int(myDouble);
  4. int cast3 = static_cast<int>(myDouble); // recommended
  1. 用于类层次结构中,基类和子类之间指针和引用的转换;
    当进行上行转换,也就是把子类的指针或引用转换成父类表示,这种转换是安全的;【类比:结构体 --> 子结构体】
    当进行下行转换,也就是把父类的指针或引用转换成子类表示,这种转换是不安全的,也需要程序员来保证;【类比:子结构体 --> 外层结构体】

    • dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。【多继承的情况】
    • 在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
    • 在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。(详见:暂未定关于类的篇章)
  2. 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum等等,这种转换的安全性需要程序员来保证;(上述例子)
  3. 把void指针转换成目标类型的指针,是极其不安全的;

More details: C++多继承动态交叉转换dynamic_cast

reinterpret_cast

C++里的强制类型转换符。让指针value改变时更安全一些。

  1. // Returns a hash code based on an address
  2. unsigned short hash(void *p) {
  3.   unsigned long val = reinterpret_cast<unsigned long>(p);
  4.   return ( unsigned short )(val ˆ (val >> ));
  5. }

当开辟了系统全局的内存空间,需要在多个应用程序之间使用时,需要彼此共享,传递这个内存空间的指针时,就可以将指针转换成整数值,得到以后,再将整数值转换成指针,进行对应的操作。

const_cast

用于修改类型的const或volatile属性。

  1. #include <iostream>
  2. using namespace std;
  3. class CA
  4. {
  5. public:
  6. CA():m_iA(){}
  7. int m_iA;
  8. };
  9. int main()
  10. {
  11. const CA *pA = new CA;
  12. // pA->m_iA = 100; // Error
  13. CA *pB = const_cast<CA *>(pA);
  14. pB->m_iA = ;  // 临时性可以修改了
  15. // Now the pA and the pB points to the same object
  16. cout<<pA->m_iA<<endl;
  17. cout<<pB->m_iA<<endl;
  18. const CA &a = *pA;
  19. // a.m_iA = 200; // Error
  20. CA &b = const_cast<CA &>(a);
  21. b.m_iA = ;
  22. // Now the a and the b reference to the same object
  23. cout<<b.m_iA<<endl;
  24. cout<<a.m_iA<<endl;
  25. }

一般不要用! 以上例子,原本的const指针没法修改对象的变量,但const_cast之后的新指针,便可以了。但,这样的操作要慎重!

11. 数组

多维数组

打开多维array的正确方式:

    • 体会auto的魅力。
    • begin与end的技巧。
  1. int ia[][] = {
  2. , , , ,
  3. , , , ,
  4. , , ,
  5. };
  6.  
  7. for (auto p = std::begin(ia); p != std::end(ia); ++p) {
  8. for (auto q = std::begin(*p); q != std::end(*p); ++q) {
  9. std::cout << *q << " ";
  10. }
  11. std::cout << std::endl;
  12. }

string的遍历:避免了结束符问题,提倡!

  1. string str = "lolop";
  2. for (auto &c : str)
  3. {
  4. c = toupper(c);
  5. }
  6. cout << str << endl;

矩阵:数值计算的数组

c++11面向数值计算的数组:valarray

数值计算专列:使用正确的类型,处理的正确问题,也方便代码阅读。

  1. int days[] = {, , , , , , , , , };
  2. valarray<int> vi;
  3. valarray<double> di();
  4. valarray<float> fi(3.14, );
  5. valarray<int> vid(days, );
  6. vid *= ;
  7. cout << vid[] << endl;

动态数组

记得delete就好。

  1. int n = ;
  2. int *dyn_arr = new int [n];
  3. for ( int i = ; i < n; i++)
  4. {
  5. dyn_arr[i] = i;
  6. }
  7.  
  8. delete [] dyn_arr;

12. Operator Overload

1. 在重载下标运算符时(数组符号):不可重载为友元函数,必须是非static类的成员函数。 why?
 
/* implement */
 
 
2. overload ++ 时,如果是: int a; ++a; ++在前面时,怎么办?
答:counter counter::operator ++(int)
  

3. 关于虚析构函数,问:基类中的析构函数一般都设置为virtual,是么?不设置的话,会出现什么问题?

用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。

总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。
也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的。
 
 

 
 “消息传递需要消耗时间“,原因是?
 

 
 
 
 
 
 
暂时放在这里? 本篇需要大总结和整理.
 

Macros should never be required in C++.
Variables should be defined close to their use.
Don’t use malloc/realloc, use new (or smart pointers)
Minimise use of void*, pointer arithmetic, union and c-style casts
Minimise the use of C-style arrays and strings, use vector/array (from C++11) and string instead.

总之,忘掉C语言。

 

[c++] 面试题之犄角旮旯 第壹章的更多相关文章

  1. [Algorithm] 面试题之犄角旮旯 第贰章

    闲下来后,需要讲最近涉及到的算法全部整理一下,有个indice,方便记忆宫殿的查找 MIT的算法课,地球上最好: Design and Analysis of Algorithms 本篇需要重新整理, ...

  2. [LeetCode] 面试题之犄角旮旯 第叁章

    题库:LeetCode题库 - 中等难度 习题:网友收集 - zhizhiyu 此处应为一个简单的核心总结,以及练习笔记. 查找一个数“在不在”?桶排序理论上貌似不错. 回文问题 ----> [ ...

  3. [Code] 烧脑之算法模型

    把博客的算法过一遍,我的天呐多得很,爱咋咋地! 未来可考虑下博弈算法. 基本的编程陷阱:[c++] 面试题之犄角旮旯 第壹章[有必要添加Python] 基本的算法思想:[Algorithm] 面试题之 ...

  4. 程序员编程艺术:第三章续、Top K算法问题的实现

    程序员编程艺术:第三章续.Top K算法问题的实现 作者:July,zhouzhenren,yansha.     致谢:微软100题实现组,狂想曲创作组.     时间:2011年05月08日    ...

  5. 从零开始山寨Caffe·玖:BlobFlow

    听说Google出了TensorFlow,那么Caffe应该叫什么? ——BlobFlow 神经网络时代的传播数据结构 我的代码 我最早手写神经网络的时候,Flow结构是这样的: struct Dat ...

  6. 从零开始山寨Caffe·陆:IO系统(一)

    你说你学过操作系统这门课?写个无Bug的生产者和消费者模型试试! ——你真的学好了操作系统这门课嘛? 在第壹章,展示过这样图: 其中,左半部分构成了新版Caffe最恼人.最庞大的IO系统. 也是历来最 ...

  7. 从零开始山寨Caffe·伍:Protocol Buffer简易指南

    你为Class外访问private对象而苦恼嘛?你为设计序列化格式而头疼嘛? ——欢迎体验Google Protocol Buffer 面向对象之封装性 历史遗留问题 面向对象中最矛盾的一个特性,就是 ...

  8. 从零开始山寨Caffe·叁:全局线程管理器

    你需要一个管家,随手召唤的那种,想吃啥就吃啥. ——设计一个全局线程管理器 一个机器学习系统,需要管理一些公共的配置信息,如何存储这些配置信息,是一个难题. 设计模式 MVC框架 在传统的MVC编程框 ...

  9. 《软件性能测试与LoadRunner实战教程》新书上市

    作者前三本书<软件性能测试与LoadRunner实战>.<精通软件性能测试与LoadRunner实战>和<精通软件性能测试与LoadRunner最佳实战>面市后,受 ...

随机推荐

  1. 谈谈JVM垃圾回收

    概述 Java运行时区域中,程序计数器,虚拟机栈,本地方法栈三个区域随着线程的而生,随线程而死,这几个区域的内存分配和回收都具备确定性,不需要过多考虑回收问题.而Java堆和方法区则不一样,一个接口的 ...

  2. idea打包失败时,强行打包

    set target_jar="E:\handSight\fras\Jars" cd Jars del fras-.jar rem 拉取最新代码 call git pull ech ...

  3. java中Long类型和long类型的大小比较

    在开发过程中老犯一些低级错误,基础还得好好加强啊...... 今天遇到这样一个问题,我用 "=="来比较两个Long类型的数据,明明数值都相等,可是结果就是false,后来仔细想想 ...

  4. 牛客多校第六场 C Generation I 组合数学 阶乘逆元模板

    链接:https://www.nowcoder.com/acm/contest/144/C来源:牛客网 Oak is given N empty and non-repeatable sets whi ...

  5. poj3666 Making the Grade(基础dp + 离散化)

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  6. codeforces 701 E. Connecting Universities(树+ 边的贡献)

    题目链接:http://codeforces.com/contest/701/problem/E 题意:有n个城市构成一棵树,一个城市最多有一个学校,这n个城市一共2*k个学校,要对这2*k个学校进行 ...

  7. codeforces 284 C. Cows and Sequence(线段树)

    题目链接:http://codeforces.com/contest/284/problem/C 题意:就是给出3个操作 1)是将前i 个数加x 2)在数组最后添加一个数x 3)删除数组最后的那个数 ...

  8. Keras之注意力模型实现

    学习的一个github上的代码,分析了一下实现过程.代码下载链接:https://github.com/Choco31415/Attention_Network_With_Keras 代码的主要目标是 ...

  9. spring组件注册

    基于注解和类的组件注册 @Conditional 作用:按照一定的条件进行判断,如果满足条件的话就给spring容器中注册bean ​ 该注解既可以标注到方法上面,也可以标注到类上面(只有满足条件时, ...

  10. Python 为了提升性能,竟运用了共享经济

    大家或许知道,Python 为了提高内存的利用效率,采用了一套共用对象内存的分配策略. 例如,对于那些数值较小的数字对象([-5, 256]).布尔值对象.None 对象.较短的字符串对象(通常 是 ...