编程基础知识总结

基本知识

程序  = 算法 + 数据结构,算法是对操作的描述,数据结构是对数据的描述。

伪代码:pseudo code

程序一般包括:

(1)预处理命令:#include等

(2)全局声明部分

(3)函数:函数首部(声明)、函数体(局部声明+执行部分)

程序执行过程

源程序-->编译成目标程序obj-->连接目标程序成可执行文件

类:数据成员+成员函数

命名空间

实际上就是一个由程序设计者命名的内存区域。程序员可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其它全局实体分隔开,解决名字冲突,防止全局命名空间污染。

C++库的所有标识符(标准头文件中函数、类、对象、类模版)都是在std命名空间定义的

A 的ASCII码值65   a 的97

1.数据类型

  • 基本类型:整型、浮点型、字符型、布尔型
  • 构造类型:枚举、数组、结构体类型(struct)、公用体(union)、类类型
  • 指针类型
  • 引用类型
  • 空类型:null

int 4             unsigned int 4                 short int 2        unsigned short int 2         long int 4  unsigned long int 4

char 1         uchar 1

float 4          double 8                           long double 8

无符号:不用保存符号位,故比有符号多了一位

有符号:数值用补码存放(无论正负),最高位为符号位

VC中,long double与double字节数相同,故long double是无用的

GCC中,long double则有12个字节

无负值的量可以定义为unsigned int,如年龄、学号等,以增大存储范围。

short int,long int,unsigned int这些类型后面的int可以省略

整型表示:

十进制,后面加L 或 l

八进制,前面加0

十六进制,前面加0x

浮点数表示:

默认为双精度型double

后面加 f 或 F 则为单精度float

后面加 l 或 L 则为长精度型long double

指数形式

数符  数字部分  指数部分

a = 3.14e2         a=0.314e4        a=31.4e1          a=3140e-1

浮点数,不管是用小数形式还是指数形式表示,在内存中都是以指数形式表示的,且数字部分必须小于1

如3.14159 在内存中表示为   +  .314159   3 ,数字部分为.314159,是小于1的

字符型

字符型在内存中存储的是ASCII码,也是整型,故而可以把字符型赋给整型

字符串后面,编译系统会加个'\0'作为结束符

符号常量

用符号代表一个常量,如#define   PI  3.14159

在编译时,系统会把符号常量替换成具体的值


2.变量

变量:程序运行期间,值可变的量

变量名:代表内存中的一个存储单元,在编译连接时由系统给每一个变量分配一个地址

标识符:标识实体名字的有效字符序列,字母、数字、下划线

常变量:定义变量时加上const,运行期间值不可变,也即只读变量

区别#define 定义的符号常量与const定义的常变量

符号常量只是用一个符号代表一个常量,在编译时把所有符号常量替换为指定的值,它没有类型,在内存中不存在以符号常量命名的存储单元

常变量具有变量的特征,具有类型,在内存中有以它命名的存储单元,与一般变量不同的是,常变量代表的存储单元值不可变。

强定义的好处

1.保证变量名使用的正确,不正确会在编译时报错

2.每个变量指定为一确定类型,在编译时就能为其分配存储单元

3.编译时即可检查变量进行的运算是否合法。


3. 运算符

二进制位运算

& 二进制 按位与

|   二进制按位或

^  按位异或

<< 左移位

>> 右移位


 ++ -- 自加自减运算符

++i  使用i之前,i先自加

i++  使用i之后,i再自加

++ -- 结合方向为自右向左

例:

!x++   先取非,再++

(i++)+6  先i+6,后i++,不管有无括号,都是先运算,再自加

(++i)+6 先自加,再加6

-i++ :i左面是符号运算符,右面是自加运算符,设i等于3,运算过程相当于 -(i++),即 -i=-3  -3+1=-2

a = -i++:a结果为-3,先赋值,再自加;

5-i++ =?  答案2    ?待测试

i=1,j=2,则a = i+++j ?    答案:3 因为相当于a=(i++)+j;

i=1,j=2,则a=i+(++j)?    答案:4

赋值运算符=的优先级小于++ -- 运算符

示例:
int arr[] = {6,7,8,9,10};
sint *ptr = arr;
*(ptr++) += 123;
printf("%d,%d",*ptr,*(++ptr));
解:
*(ptr++) += 123; 相当于 *ptr +=123;  *ptr++; 故arr[0] = 129; ptr指向arr[1]
printf函数从右向左压栈,运算顺序:++ptr; 输出结果: 8 8

cout也是自右向左压栈。


逗号运算符

又称顺序求值运算符

a = 3*4,a*5  则  a=? 答案 12  ?  注意逗号运算符优先级最低。注:整个逗号表达式的值为60(a=3*4=12,12*5 =60)

x=(a=3,6*3)   则 x=18

x=a=3,6*a     则 x=3


3.内存存储

浮点数在内存里和整数存储方式不同

float a =1.0f;

cout<<(int)a==(int&a);
(int&a) 相当于把该浮点数地址开始的sizeof(int)个字节当成int型数据输出,其值并不为1

(int)a显示转换等于1


4.类型转换

转换本质:按存储单元中的存储形式直接传送

(1)浮点型赋给整型,舍弃小数部分

(2)double型赋给float,防止溢出错误

(3)int, short, long赋给char,原封不动取低八位

(4)signed赋给unsigned,符号位照搬。负数以补码形式存放,-1赋给unsigned int,结果为65536.整数不会变,除非两个长度不同(int,long)发生截断


5.C++输入输出

C++输入输出包含三个方面的内容

(1)对系统指定的标准设备的输入输出。即从键盘输入、输出到显示器屏幕,称标准输入输出,简称标准I/O

(2)以外出磁盘文件为对象进行输入输出,称文件I/O

(3)对内存中指定空间进行输入输出,通常指定一个字符数组作为存储空间,称字符串输入输出,简称串I/O

在C++中,输入输出流被定义为类。C++的I/O库中的类称为流类,用流类定义的对象称流对象。

C++中输入输出是调用输入输出流库中的流对象cin、cout实现的,即I/O不是C++本身定义的,而是编译系统的I/O库中定义的。

I/O控制符#include <iomanip>

setprecision(n) 设置精度为n,

十进制输出时,n代表有效数字位数包括整数和小数;

fixed(固定小数位数)和scientific(指数)形式输出时,n指小数位数(不包括整数部分)

double a = 123.4567890123456

cout << a;      //十进制输出,输出123.456   默认精度为6

cout<<setprecision(9)<<a;    //十进制,输出123.456789   精度为9

cout<<setprecision(6);      //恢复默认精度

cout<<setioflags(ios::fixed)<<a;    //固定位数,123.456789 ,此时精度表示小数位数,精度为默认的6


6.getchar() 和 putchar()

cout<<getchar();     //读入的实际是ASCII码,故输出为字符ASCII码,97,而非读入的字符

cout<<(c=getchar());  //输出为字符

while((c=getchar())!='\n'){}    //循环读入字符的控制


7.函数与模版

函数原型:不同具体形参的函数声明

如:float add(float,float)

主要作用:根据函数原型,在程序编译阶段对调用函数的合法性进行全面检查。

函数重载:同一函数名定义的多个函数,这些函数的参数个数,参数类型,参数顺序至少有一项不同,一个函数不能既是重载函数,又是带默认参数的函数。

函数模版:适用于函数个数相同,函数体相同,而只有类型不同的情况

#include <iostream>
using namespace std;
template <typename T> // template <class T>
T max(T a, T b, T c)
{
     if(b>a)  a = b;
     if(c>a)   a = c;
     return a;
}
int main()
{
    int a=1,b=2,c=3;
    cout<<T(a,b,c);
    float d=1.1,e=2.2,f=3.3;
    cout<< T(d,e,f);
}

变量作用域:变量有效范围,有四种:

文件作用域 file scope    函数作用域    function scope

块作用域 block scope   函数原型作用域 function prototype scope

递归函数:函数体中,直接或间接调用函数本身的函数。

变量的存储类别:外部、局部(相对于函数而言)

全局变量(也即外部变量)

静态局部变量(static)

自动变量(不加static的局部变量)

寄存器变量(register) 存放在CPU中,而非内存中,这样在使用时就省去了从内存中载入寄存器的过程。但只是建议性的,优化编译系统自动识别使用频繁的变量,从而自动将变量放入寄存器中。

extern声明的外部变量

即提前引用申明,表示该变量是将在下面定义的全局变量或在其它文件中定义(本文件中不用extern,引用该变量的外部文件用extern进行声明)

static声明的静态外部变量

只能被本文件使用,而不能被外部文件使用的全局变量,这样不同文件中的全局变量不会相互干扰,为程序模块化、通用化提供方便。

注:全局变量也是静态存储的。

内部函数与外部函数

内部函数:static 声明,文件内使用

外部函数:另一个文件里extern声明,表示是其它文件的函数,extern可以省略

宏定义

#define PI 3.14       定义符号常量

#define Area(a,b)    a*b                 //定义函数功能,下面当作函数来用。

#include <iostream>  'iostream' 区别

<> 在系统目录寻找,找不到报错

' '   在当前目录寻找,找不到报错  


字符数组

(1) char str[] = "i am happy";

数组长度为11,而非10,因为后面有一个'\0'

(2) char str[] = {'i','a','m','h','y'}

数组长度为5,系统不会自动为其在后面加'\0'

因此,(1),(2)是不同的

输出字符数组:cout<<str;  

string类

字符数组是C中的处理方式,C++中用string类,#include <string>

字符串变量中不会存放'\0',只存放字符串本身,故string str ="hello"; 的长度为5,要注意。

字符串变量存储的实际是字符串的指针,4个字节,

sizeof(string) = 4;

string name[]={"i","am","happy"};   sizeof(name) = 3*4 = 12;


变量与指针:

int *p = &i;     //int型指针变量,定义时的*只是表示指针类型

p是指针变量,其值是变量i的地址,*p则是存储单元,*&a与*p同,都表示变量a

指向数组的指针

int a[10] = {};

int *p;

p = &a[0];  //与下面等价,都指向数组第一个元素,因为数组名本身就是表示数组的地址

p = a;

*************************

*p++ 相当于*(p++),先得到*p的值,p再++移到下一个元素

(*p)++则是使*p的值+1

二维数组的指针表示: *(*(p+i)+j)   表示 a[i,j]

*************************

int (*p)[n]   p为指向含n个元素的数组的指针

int *p[n]     定义指针数组P

函数指针 指向函数的指针,主要用作形参

int max(int,int);

int (*p)(int,int);

p = max; 赋值(地址)

p(1,2)  //调用


引用

int a = 10;

int &b = a;  b是对a的引用

引用传递,引用型变量作为函数形参

//值会改变
main{
  int i=5,j=6;
  swap(i,j)
}
void swap(int &a, int &b)  //这里的&不是“a的地址”,而是指“a是一个引用型变量”,&是个声明符
{
     int temp;
     temp = a;
     a= b;
     b=temp;
}
传递变量地址:形参是指针变量,实参是变量地址,这种虚实结合的方法仍然是“值传递”方式,只是实参的值是变量地址而已。

//值会改变
main()
{
    int i=5,j=6;
    swap(&i,&j)
}
void swap(int *p1, int *p2)  //这里的*号也只表示是指针类型
{
     int temp;
     temp = *p1;
     *p1 = *p2;
     *p2 = temp;
}

结构体变量 struct

作函数参数时有三种形式

(1)用结构体变量名作形参

这时形参要开辟内存单元,实参中全部内容通过值传递方式一一传递给形参,时空开销大,效率低

(2)用指向结构体变量的指针作形参,只有四个字节

void printed(student *p)

{

   cout<<p->num;

}

(3)用结构体变量的引用变量作形参

Student stu;

print(stu);

void print(Student &stu)

{

    cout<stu.num;

}


new delete 动态内存分配

new 类型(初值),返回地址,分配失败返回NULL

float *f = new float(3.14);

int *i = new int(6);

int *k = new int[5][4];  //数组

delete 变量  delete f;  delete i;

            数组   delete [] k;


Enum 枚举类型

声明枚举类型  enum weekday{sun,mon,tue,wed,thu,fri,sat};

定义枚举变量  weekday  workday,week_end;

变量赋值: workday = mon;    或   workday = weekday(2);

枚举常量对应值从0开始,0,1,2,3..


typedef 声明新类型

typedef int  INTEGER  ,相当于为int起了个别名,下面程序中就可以直接用INTEGER作int用了

主要为了方便系统移植,如long int在VC中4个字节,在GCC中占8个字节,直接用int的话可能会溢出,用INTEGER就不用担心了,只要把ypedef int  INTEGER 声明语句一改就行


运算符重载

方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现响应运算。即运算符重载是通过定义函数实现的,运算符重载实际上是函数重载。

格式: 

函数类型 operator 运算符名称 (形参表列)

{对运算符的重载处理}

例如:将 + 用于Complex类(复数)的加法运算,函数原型如下:

Complex operator + (Complex& c1, Complex& c2);

注:operator 是关键字, operator + 就是函数名,可以描述为: 函数operator +重载了运算符+

整数加可以想象为调用如下函数

int operator + (int a,int b)

{ return a+b; }

#include <iostream>
using namespace std;
class Complex
{
  public:
    Complex(){real=0;imag=0;}
    Complex(double r, double r){real=r;imag=i;}
    Complex operator + (Complex &c2);  //声明重载运算符的函数
    void display();
  private:
    double rea;
    double imag;
};
Complex Complex::operator + (Complex &c2) //定义重载运算符的函数
{
  Complex c;
  c.real = real + c2.real;
  c.imag = imag + c2.imag;
  return c;
}
void Complex::display()
{
  cout<<real<<imag;
}
int main()
{
  Complex c1(3,4), c2(5,-10),c3;
  c3 = c1 +c2;       //运算符+ 用于复数运算
  cout<<"c1=";c1.display; 
  cout<<"c2=";c2.display;
  cout<<"c1+c2=";c3.display;
  return 0;
}
运行结果:
c1 = (3,4i)
c2 = (5,-10i)
c1+c2 = (8,-6i)
重载运算符的规则
(1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
(2)C++允许重载绝大部分的运算符
(3)重载不能改变运算符运算对象的个数
(4)重载不能改变运算符的优先级别
(5)重载不能改变运算符的结合性
(6)重载运算符的函数不能有默认的参数
(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少一个是类对象(或类对象的引用)。也就是说参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。

(8)用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载

(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能,否则不易使人理解程序

(10)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还是计费成员函数也非友元函数的普通函数。

发布了143 篇原创文章 · 获赞 11 · 访问量 77万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章