[c++] 面试题之犄角旮旯 第壹章
记录C/C++语言相关的问题。
算法可视化:https://visualgo.net/en
<data structure and algorithm in c++> By Adam 有免费电子版
1. while( ) 与 Ctrl+D
Ctrl+D后,默认还是要执行完后面的程序。
void multi_input(void)
{
int sum = 0;
int value;
while(std::cin >> value)
{
cout << "-" << endl;
sum += value;
}
cout << sum << endl;
} multi_input() multi_input()
第一个multi_input()执行中,执行Ctrl+D后:
一旦测试失败,while 终止并退出循环体,执行 while 之后的语句。
该语句在输出 sum 后输出 endl,endl 输出换行并刷新与 cout 相关联的缓冲区。
最后,执行 return,通常返回零表示程序成功运行完毕。
2. c++英语学习
声明 Declarations
定义 Definitions 小括号 parenthesis [pə'renθɪsɪs]
中括号 square brackets
花括号 curly brace 实参 argument
形参 parameter 操纵符 manipulator
...
3. 赋值越界
字符
C++ 中,把负值赋给 unsigned 对象是完全合法的,其结果是该负数对该类型的取值个数求模后的值。
所以,如果把 -1 赋给 8 位的 unsigned char, 那么结果是 255, 因为 255 是 -1 对256 求模后的值。
数字的最大值
float 型只能保证 6位有效数字,可能不够用;
double 型至少可以保证 10位有效数字 满足大部分计算的需要。
size of types
#include<limits>
cout << numeric_limits<double>::max() << endl;
字符串的不同类型
如果连接普通字符串字面值和宽字符串字面值,将会出现什么结果呢?例如:
// Concatenating plain and wide character strings is undefined
std::cout << "multi-line " L"literal " << std::endl;
其结果是未定义的,也就是说,连接不同类型的行为标准没有定义。
这个程序可能会执行,也可能会崩溃或者产生没有用的值,而且在不同的编译器下程序的动作可能不同。
wchar_t
L'a' stored in wchar_t.
4. 数据间的转化
unsigned int a = ;
signed int b = -; // “局部”大范围 --> 小范围
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)
int i = ;
int j = (i = ) * i;
cout << "j = " << j << endl; j = 9; // 因为括号优先级高
const
The primary role of const is to specify immutability.
const int a = ;
const long &r = a;
// Can refer to an object of a different (but related) type. 但还是不要这么做了吧,容易误会。
Jeff: const int val; int const val 目前编译器解释是一样的。
int i = ;
int *const p1 = &i; // we can't change the value of p1; const is top-level
const int ci = ; // we cannot change ci; const is top-level
const int *p2 = &ci; // we can change p2; const is low-level 指向的只是一个特定的类型
const int *const p3 = p2; // right-most const is top-level, left-most is not
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是对全局作用域的细分。
将多个变量和函数等包含在内,使其不会与命名空间外的任何变量和函数等发生重命名的冲突。
#include <iostream>
using namespace std; // 命名空间JiZhuoMi
namespace JiZhuoMi
{
char *szUrl = "www.jizhuomi.com";
} // 命名空间Software
namespace Software
{
char *szUrl = "www.jizhuomi.com/software/";
} // 释放命名空间JiZhuoMi和Software
using namespace JiZhuoMi;
using namespace Software; int _tmain(int argc, _TCHAR* argv[])
{
char *szUrl = "url";
cout << szUrl << endl;
return ;
}
8. How to print
Reference: http://www.cplusplus.com/reference/ios/ios_base/fmtflags/
具有默认输出格式
cout 输出的数字的有效数字位数有默认的限制:6个有效数字。
cout << "[" << << "]" << endl;
std::cout << << std::endl;
cout << "[" << << "]" << endl;
std::cout << "In hex " << std::hex << << std::endl;
cout << "[" << << "]" << endl;
std::cout << 1331.123456 << std::endl; // 只保留了俩位小数,看来默认是6个有效数字
cout << "[" << << "]" << endl;
std::cout.setf(std::ios::scientific, std::ios::floatfield); // 设置了cout的属性为科学计数法
cout << "[" << << "]" << endl;
std::cout << 1331.123456 << std::endl;
cout << "[" << << "]" << endl;
std::cout << std::setprecision() << 1331.123456 << std::endl; // 进一步设置,科学技术法的小数点
cout << "[" << << "]" << endl;
std::cout << std::dec << << std::endl; // 设置回了十进制
cout << "[" << << "]" << endl;
std::cout.width(); // 下一次 ONLY 写[八]个words.
cout << "[" << << "]" << endl;
std::cout << << std::endl;
cout << "[" << << "]" << endl;
std::cout.setf(std::ios::left, std::ios::adjustfield);
cout << "[" << << "]" << endl;
std::cout.width(); // 自动对齐的一种技巧
cout << "[" << << "]" << endl;
std::cout << << std::endl;
cout << "[" << << "]" << endl;
16, 设置下次输出的一个下限。
自动对齐输出
15-22, 自动对齐的技巧。
[] []
In hex
[]
1331.12
[]
[]
1.331123e+03
[]
1.331e+03
[] []
[] []
[]
[ ] []
Result
9. cin的陷阱
【1】cin.getline(str, len):缓冲区有残留
当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。
#include <iostream>
using namespace std;
int main()
{
char str[];
cin.getline(str, ); // input多少,这里都只从缓冲区 读取5个。剩下的就自动成为了下一次输入。
cout<<str<<endl;
cin.getline(str, );
cout<<str<<endl;
return ;
}
【2】cin >>, 空格会成为终止
#include <iostream>
using namespace std;
int main()
{
char str1[], str2[];
cin>>str1; // 输入:abcd efg. 第一次读取字符串时遇到空格则停止.
cin>>str2; // 缓冲区有残留数据,读入操作直接从缓冲区中取数据。
cout<<str1<<endl;
cout<<str2<<endl;
return ;
}
看来,比较稳妥的方式是:使用cin.getline(255)这种即可。
【3】cin.get(<char>)
空格不会成为终止(空格可能就是要输入的字符*_*),Enter可以。
#include <iostream>
using namespace std;
int main()
{
char c1, c2;
cin.get(c1);
cin.get(c2);
cout<<c1<<" "<<c2<<endl; // 打印两个字符
cout<<(int)c1<<" "<<(int)c2<<endl; // 打印这两个字符的ASCII值
return ;
}
自定义 终止符如何?
#include <iostream>
using namespace std;
int main ()
{
char ch, a[];
cin.get(a, , 'd'); //设置d为终止符
cin>>ch;
cout<<a<<endl;
cout<<(int)ch<<endl;
return ;
}
注意:识别结束符,但不丢弃。
【4】灵活清空缓冲区
为什么ch的输出错了呢?
#include <iostream>
using namespace std;
int main ()
{
char ch, a[];
cin.getline(a, ); // 输入123456, a: 1234
cin>>ch; // ch: 0, but not the ascii of '5'
cout<<a<<endl;
cout<<(int)ch<<endl;
return ;
}
所以,输入一次数据后,最好记得清空“input buffer"。灵活的清空方法如下:
cin.ignore(numeric_limits<std::streamsize>::max(),’\n’);//清除输入缓冲区的当前行
cin.ignore(numeric_limits<std::streamsize>::max()); //清除输入缓冲区里所有内容
cin.ignore()//清除一个字符
10. 智能指针 - 类型转换
reference: http://www.jellythink.com/archives/205
C++中的类型转换分为两种:
- 隐式类型转换;
- 显式类型转换。(这里的重点)
在标准C++中有四个类型转换符:static_cast、dynamic_cast、const_cast和reinterpret_cast;
static_cast & dynamic_cast
执行非多态类型的转换,用于代替C中通常的转换操作。
double myDouble = 3.14;
int cast1 = (int)myDouble; // c-style
int cast2 = int(myDouble);
int cast3 = static_cast<int>(myDouble); // recommended
- 用于类层次结构中,基类和子类之间指针和引用的转换;
当进行上行转换,也就是把子类的指针或引用转换成父类表示,这种转换是安全的;【类比:结构体 --> 子结构体】
当进行下行转换,也就是把父类的指针或引用转换成子类表示,这种转换是不安全的,也需要程序员来保证;【类比:子结构体 --> 外层结构体】- dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。【多继承的情况】
- 在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
- 在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。(详见:暂未定关于类的篇章)
- 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum等等,这种转换的安全性需要程序员来保证;(上述例子)
- 把void指针转换成目标类型的指针,是极其不安全的;
More details: C++多继承动态交叉转换dynamic_cast
reinterpret_cast
C++里的强制类型转换符。让指针value改变时更安全一些。
// Returns a hash code based on an address
unsigned short hash(void *p) {
unsigned long val = reinterpret_cast<unsigned long>(p);
return ( unsigned short )(val ˆ (val >> ));
}
当开辟了系统全局的内存空间,需要在多个应用程序之间使用时,需要彼此共享,传递这个内存空间的指针时,就可以将指针转换成整数值,得到以后,再将整数值转换成指针,进行对应的操作。
const_cast
用于修改类型的const或volatile属性。
#include <iostream>
using namespace std;
class CA
{
public:
CA():m_iA(){}
int m_iA;
};
int main()
{
const CA *pA = new CA;
// pA->m_iA = 100; // Error
CA *pB = const_cast<CA *>(pA);
pB->m_iA = ; // 临时性可以修改了
// Now the pA and the pB points to the same object
cout<<pA->m_iA<<endl;
cout<<pB->m_iA<<endl;
const CA &a = *pA;
// a.m_iA = 200; // Error
CA &b = const_cast<CA &>(a);
b.m_iA = ;
// Now the a and the b reference to the same object
cout<<b.m_iA<<endl;
cout<<a.m_iA<<endl;
}
一般不要用! 以上例子,原本的const指针没法修改对象的变量,但const_cast之后的新指针,便可以了。但,这样的操作要慎重!
11. 数组
多维数组
打开多维array的正确方式:
- 体会auto的魅力。
- begin与end的技巧。
int ia[][] = {
, , , ,
, , , ,
, , ,
};
for (auto p = std::begin(ia); p != std::end(ia); ++p) {
for (auto q = std::begin(*p); q != std::end(*p); ++q) {
std::cout << *q << " ";
}
std::cout << std::endl;
}
string的遍历:避免了结束符问题,提倡!
string str = "lolop";
for (auto &c : str)
{
c = toupper(c);
}
cout << str << endl;
矩阵:数值计算的数组
c++11面向数值计算的数组:valarray
数值计算专列:使用正确的类型,处理的正确问题,也方便代码阅读。
int days[] = {, , , , , , , , , };
valarray<int> vi;
valarray<double> di();
valarray<float> fi(3.14, );
valarray<int> vid(days, );
vid *= ;
cout << vid[] << endl;
动态数组
记得delete就好。
int n = ;
int *dyn_arr = new int [n];
for ( int i = ; i < n; i++)
{
dyn_arr[i] = i;
} delete [] dyn_arr;
12. Operator Overload
3. 关于虚析构函数,问:基类中的析构函数一般都设置为virtual,是么?不设置的话,会出现什么问题?
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++] 面试题之犄角旮旯 第壹章的更多相关文章
- [Algorithm] 面试题之犄角旮旯 第贰章
闲下来后,需要讲最近涉及到的算法全部整理一下,有个indice,方便记忆宫殿的查找 MIT的算法课,地球上最好: Design and Analysis of Algorithms 本篇需要重新整理, ...
- [LeetCode] 面试题之犄角旮旯 第叁章
题库:LeetCode题库 - 中等难度 习题:网友收集 - zhizhiyu 此处应为一个简单的核心总结,以及练习笔记. 查找一个数“在不在”?桶排序理论上貌似不错. 回文问题 ----> [ ...
- [Code] 烧脑之算法模型
把博客的算法过一遍,我的天呐多得很,爱咋咋地! 未来可考虑下博弈算法. 基本的编程陷阱:[c++] 面试题之犄角旮旯 第壹章[有必要添加Python] 基本的算法思想:[Algorithm] 面试题之 ...
- 程序员编程艺术:第三章续、Top K算法问题的实现
程序员编程艺术:第三章续.Top K算法问题的实现 作者:July,zhouzhenren,yansha. 致谢:微软100题实现组,狂想曲创作组. 时间:2011年05月08日 ...
- 从零开始山寨Caffe·玖:BlobFlow
听说Google出了TensorFlow,那么Caffe应该叫什么? ——BlobFlow 神经网络时代的传播数据结构 我的代码 我最早手写神经网络的时候,Flow结构是这样的: struct Dat ...
- 从零开始山寨Caffe·陆:IO系统(一)
你说你学过操作系统这门课?写个无Bug的生产者和消费者模型试试! ——你真的学好了操作系统这门课嘛? 在第壹章,展示过这样图: 其中,左半部分构成了新版Caffe最恼人.最庞大的IO系统. 也是历来最 ...
- 从零开始山寨Caffe·伍:Protocol Buffer简易指南
你为Class外访问private对象而苦恼嘛?你为设计序列化格式而头疼嘛? ——欢迎体验Google Protocol Buffer 面向对象之封装性 历史遗留问题 面向对象中最矛盾的一个特性,就是 ...
- 从零开始山寨Caffe·叁:全局线程管理器
你需要一个管家,随手召唤的那种,想吃啥就吃啥. ——设计一个全局线程管理器 一个机器学习系统,需要管理一些公共的配置信息,如何存储这些配置信息,是一个难题. 设计模式 MVC框架 在传统的MVC编程框 ...
- 《软件性能测试与LoadRunner实战教程》新书上市
作者前三本书<软件性能测试与LoadRunner实战>.<精通软件性能测试与LoadRunner实战>和<精通软件性能测试与LoadRunner最佳实战>面市后,受 ...
随机推荐
- js全选与取消全选
实现全选与取消全选的效果 要求1(将军影响士兵):点击全选按钮,下面的复选框全部选中,取消全选按钮,下面的复选框全部取消 思路:复选框是否被选中,取决于check属性,将全选按钮的check属性值赋值 ...
- Spark的安装及配置
title: Spark的安装及配置 summary: 关键词:Hadoop集群环境 Spark scala python ubuntu 安装和配置 date: 2019-5-19 13:56 aut ...
- lua_lua与.Net互相调用
配置环境:创建C#项目,引入luainterface-1.5.3\Built下面的LuaInterface.dll文件和luanet.dll文件.引入命名空间using LuaInterface 代码 ...
- Java集合框架之Vector浅析
Java集合框架之Vector浅析 一.Vector概述: 位于java.util包下的Vector是Java集合框架的重要一员,虽然没有ArrayList那么的常用,但是我们还要对其做相关学习: 1 ...
- UVA-10004-Bicoloring二分图染色
题意:给一张图,判断是不是二分图: 自己一开始不知道是二分图染色,理解的是任意三点不能互相连接 可能以后遇到这样的模型,可以往二分图想: 首先怎么判定一个图是否为二分图 从其中一个定点开始,将跟它邻接 ...
- POJ 3694 Network 无向图双联通+LCA
一开始题目没看清楚,以为是增加那条边后还有多少桥,所以就当做是无向图tarjan缩点后建树,然后求u,v的最近公共祖先,一直wa. 后来再看题目后才发现边放上去后不会拿下来了,即增加i条边后桥的数量. ...
- CodeForces Round 521 div3
A:Frog Jumping 代码: #include<bits/stdc++.h> using namespace std; #define Fopen freopen("_i ...
- codeforces 808 E. Selling Souvenirs (dp+二分+思维)
题目链接:http://codeforces.com/contest/808/problem/E 题意:最多有100000个物品最大能放下300000的背包,每个物品都有权值和重量,为能够带的最大权值 ...
- 洛谷p2015二叉苹果树&yzoj1856多叉苹果树题解
二叉 多叉 有一棵苹果树,如果树枝有分叉,可以是分多叉,分叉数k>=0(就是说儿子的结点数大于等于0)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1~N,树根编号一定是1.我们用一根树枝两 ...
- uwsgi基本介绍安装和测试--使用Django建立你的第一个网站
一 基本介绍 对像我这样不是专业做网络的人来说,uuwsgi是一个陌生的东西.它是谁?它可以做什么?谁会用到它?其实,在不知道一个东西是什么的情况下,能够快速的了解并使用它,是一门很有艺术性的事情.最 ...