温故知识点
第一第二章
1. 代码规范问题 P18 缩进和空格
2. 声明的定义 P26 P30
3. 标识符 驼峰式命名法例子 numberOfStudent,驼峰指的就是小写大写字母嵌套形式,从第二个单词开始,首字母都用大写。这样能清晰的表示出这个短语的各个单词。
4.命名常量 #define 用法(参考前面的博客第四篇)
5.数值类型转换 ASCII P45 目录B 额外:P118 代码12
ASCII表 就是一个整数映射成一个字符或者命令 课上提过,文字写起来太麻烦。
6.常见错误:1,2,3,4,
第三章:
1. 关系运算符、条件表达式 P39运算符优先级,P61 bool数据类型,P88 优先级、结合律
这里特别注意数据类型扩展的问题,同一个级别的表达式当中,所有的类型的数据会扩展成为这个表达式中出现过的级别最高的那种数据类型。
如int ,short同时出现,所有变量都会扩展为int, 如果出现double,所有参与运算的都扩展成double类型。
同一级别表达式举例如下:
1.0 + 2 * true + 1.0*2;
乘法先算:那么2*true先进行运算true被扩展为int, 1.0*2中2被扩展为double(float)
加法:前两个乘法计算完后得到1.0+2+2.0, 2被扩展为2.0进行计算
2.switch 用法 P84
3.if语句 P62
4.常见错误 P53
5.随机数 P76 伪随机(下文补充)
额外:
sizeof 用法 (讲完指针部分再提)
getchar用法 下文补充
getline用法
其他问题:
1. 有关数组越界的解决方法
数组越界的原因主要有
1.开辟的内存空间不够
那么对应的就是增加内存空间,把数组开大一点
尽可能用全局的数组变量,如下value,避免使用局部定义方法如 name
int value[1000000];
int main(){
int cost[10000];
int n;
cin>>n;
int name[n];
}
全局的变量使用的是堆,能够开辟更大的内存空间,如value,
函数内部的变量使用的是栈,所以开辟的内存空间小,如cost。
2.逻辑错误
例1:
for(int i = 0;i < n; i++)
cost[i] = cost[i-1] + cost[i];
当i = 0 , i-1 = -1 发生越界
例2:
for(int i = 0;j < n; j++)
cin>>cost[i];
此处由于判断条件是j < n ,应该为i < n, 因此程序进入死循环,同时发生越界
例3:
string x;
cin>>x;
int cost[x.length()];
cost[1] = 0;
当x的长度为0时,对cost[1]的访问显然越界
.......
逻辑错误的可能性很多,主要考虑边界问题,特殊情形。解决的方法只能是自己思考。
再介绍一下数组越界可能产生的问题。如下
1. 问题1,发生位置死循环
int x[100],i;
//注意这里定义全局变量,如果局部变量根据编译器、操作系统的内存分配策略,
//结果可能不一样,导致这里分析得到任意一种错误
int main(){
for(i = 0;i < 100; i++){
x[100] = 0;
}
}
在内存空间中以下整数存储的位置是连续的,
x[0],x[1],x[2],......,x[99],i
那么x[100] = 0 操作的结果便是 i = 0
因此程序进入死循环。
此处的结果是发送死循环。但是更复杂的情况是,会导致内存中某个位置的值发生变化
对最后结果产生位置干扰。
2. 无明显错误
int x[100],y[100];
//注意这里定义全局变量,如果局部变量根据编译器、操作系统的内存分配策略,
//结果可能不一样,导致这里分析得到任意一种错误
int main(){
for(int i = 0;i < 200 ;i++)
x[i] = i;
cout<<x[150]<<endl;
}
同1,由于x,y数组存储所在的内存空间是连续的,如下
x[0],x[1],.....,x[99],y[0],y[1],......,y[99]
因此并不会发生有影响的错误。
3. 单纯越界
int main(){
int x[100];
x[1000] = 1;
}
此处直接发生越界,程序崩溃。
4. 访问非法函数。
这个部分涉及操作系统,由于计算机指令存储在
内存中,那么访问一个位置的内存空间,可能就是访问了一个函数或者指令的入口。
举例:
内存地址 10000 的位置对应的是 system("pause");指令的入口
x[10],操作系统给x分配的起始内存地址是9900,
那么x[100]对应的就是system("pause");指令的入口,那么访问x[100]导致程序暂停。
此处system("pause")可以替换为任何函数。
当然!!!!这里只是一个例子,帮助大家理解,实际情况会更复杂,甚至不一样。
2.能不能讲一下中文的那三个练习题:easy problems
这三道题都很简单。
第一题:输入进行判断,然后统计即可。
第二题:对于每次询问,对于区间内的每个数字进行判断是否为素数,然后统计即可,每个数字x的判断是否为素数代价是sqrt(x)
优化:1.用上面的素数判断方法, 预处理1-1000,知道每个数字是否为素数,用isPri[ x]记录这个x是否为素数,然后询问时统计这个区间的结果即可。
2.在1的基础上预处理sum[i] 表示前i个数字有几个素数,然后输出 sum[r] - sum[l-1]即可。
3.素数筛法自行百度,有nlog(n)和线性筛法。
第三题:判断大小写,然后注意z->c的情况(对应于取模问题)
getchar 和 getline
getline函数(参考百度百科)
getline不是C库函数,而是C++库函数。它会生成一个包含一串从输入流读入的字符的字符串,
直到以下情况发生会导致生成的此字符串结束。1)到文件结束,2)遇到函数的定界符,
3)输入达到最大限度。
在函数遇到和结束定界符相等的字符时函数结束,同时函数抽出定界符,
此种情况下该定界符既不被放回输入流,也不被放入要生成的字符串。
getchar(参考百度百科)
从stdio流中读字符,相当于getc(stdin),它从标准输入里读取下一个字符。返回类型为int型,
返回值为用户输入的ASCⅡ码,出错返回-1。
cin
cin读取到EOF、换行、空格时便结束字符输入,并且会把这个结束符返回到输入流中
因此cin和getchar、getline共同使用的时候要尤其注意
如下例子:
int main()
{
int n;
cin>>n;
char x;
x = getchar();
char y;
y = getchar();
cout<<n<<x<<y<<endl;
//输入123 y
//输出123 y
}
通过cin读入123,当时空格还留在输入流中,因此下一个读取得字符x还是空格,
所以在做第一次练习第四题 1153 Word Reversal时,
用cin读入case数后应该立刻使用getchar()读入'\n'这个换行符,
或者可以立刻用getline读入一行,因为'\n'是一行的结束标志。
int main(){
int n;
cin>>n;
string x;
getchar(); //或者 getline(cin,x);
for(int i = 0;i < n; i++){
getline(cin,x);
....
}
}
随机数生成代码:
实现一个与库中效果一样的随机数生成函数
/** 这里采用的是windows系统中随机数生成的方法
* 参考资料:https://www.zhihu.com/question/23705240
* 安装visual studio 可查看头文件的源代码 Microsoft Visual Studio 10.0\VC\crt\src 这事路径,10.0是版本号
* 实现srand和rand函数的文件为rand.c 自行搜索便可查到
**/
#include<iostream>
#include<cstdio>
#include<stdlib.h>
using namespace std;
unsigned long long seed = 0;
//设置种子
void test_srand(unsigned long long value){
seed = value;
}
//随机数生成公式
int test_rand()
{
seed = seed * 214013L + 2531011L;
unsigned int result = ((seed >> 16) & 0x7fff );
return result;
}
int main()
{
//输出rand函数取值范围
cout<<RAND_MAX<<endl;
//确定生成随机数的种子
seed = 2;
//设定生成种子,并输出前十个数字
srand(seed);
for(int i = 0;i < 10 ;i++){
cout<<rand() <<" ";
}
cout<<endl;
//采用相同的公式生成随机数,并输出十个数字
test_srand(seed);
for(int i = 0;i < 10; i++){
cout<<test_rand()<<" ";
}
cout<<endl;
}
rand.c文件中代码
/***
*rand.c - random number generator
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines rand(), srand() - random number generator
*
*******************************************************************************/
#include <cruntime.h>
#include <mtdll.h>
#include <stddef.h>
#include <stdlib.h>
/***
*void srand(seed) - seed the random number generator
*
*Purpose:
* Seeds the random number generator with the int given. Adapted from the
* BASIC random number generator.
*
*Entry:
* unsigned seed - seed to seed rand # generator with
*
*Exit:
* None.
*
*Exceptions:
*
*******************************************************************************/
void __cdecl srand (
unsigned int seed
)
{
_getptd()->_holdrand = (unsigned long)seed;
}
/***
*int rand() - returns a random number
*
*Purpose:
* returns a pseudo-random number 0 through 32767.
*
*Entry:
* None.
*
*Exit:
* Returns a pseudo-random number 0 through 32767.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl rand (
void
)
{
_ptiddata ptd = _getptd();
return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ 2531011L) >> 16) & 0x7fff );
}