目录
1.面向过程编程
1.1数据的输入输出
第一个C++程序
#include <iostream>
using namespace std; //名字空间
int main(void){
cout << "helloworld!" << endl;
return 0;
}
编译
g++ 01helloworld.cpp -o helloworld
或 gcc 01helloworld.cpp -o helloworld -lstdc++
运行
./helloworld
1.1.1 流的概念
C++输入和输出可以看作一连串的数据流,输入即文件或键盘中输入程序的一串数据流,输出即输出一 连串的数据流到显示屏或文件中。
1.1.2 cout和插入运算符<<
当程序执行都cout语句时,遇到<<运算符就会将要是输出的信息插入到输出流中去,最终将输出流中的数据会被输出到标准输出设备(通常为 屏幕)上去。
#include <iostream>
using namespace std;
int main(void){
int x = 10;
float y = 1.1;
char z = 'c';
cout << x <<" "<< y <<" "<< z << endl;
return 0;
}
输出时自动判断基本数据类型的类型。
1.1.3 cin和析取运算符>>
当程序执行到cin语句时,就会停下来等待键盘数据的输入。输入数据被插入到输入流中,数据输完后按Enter键结束。当遇到运算符>>时,就 从输入流中提取一个数据,存入变量x中。
需要说明的几点内容:
在一条cin语句中可以同时为多个变量输入数据。 各输入数据之间用一个或多个空白作为间隔符
#include <iostream>
using namespace std;
#include <cstdio>
int main(void){
int x, y, z;
#if 0
scanf("%d %d %d", &x, &y, &z);
printf("%d %d %d\n", x, y, z);
#endif
cin >> x >> y >> z;
cout << x << " " << y << " " << z << endl;
return 0;
}
cin具有自动识别数据类型的能力,析取运算符>>根据它后面的变量类型从输入流中为他们提取对应的数据。 比如: cin >>x;
假设输入数据2, 析取运算符>>将根据其后x的类型决定输入的2到底是数字还是字符。若x是char类型,则2就是字符;
若x是int,float 之类的类型,则2就是一个数字。 假设输入34,且x是char类型,则只有字符3被存储到x中,4将继续保存在流中。
1.2 名字空间
1.2.1 名字空间的定义
namespace xx_name{
members;
}
eg:
namespace ABC{
int num;
struct stu{
int age;
char *name;
};
double add(int a, int b){
return (double)a+b;
}
int Min(int a, int b){
return a>b? b:a;
}
}
1.2.2 名字空间成员的访问和无名名字空间
名字空间成员的访问有主要有三种方法:
通过作用域限定符(::)
#include <iostream> using namespace std; namespace ns1{ void func(void){ cout << "ns1 func" << endl; } } namespace ns2{ void func(void){ cout << "ns2 func" << endl; } } int main(void){ ns1::func(); ns2::func(); return 0; }
using引用名字空间单个成员
#include <iostream> using namespace std; namespace ns1{ void func(void){ cout << "ns1 func" << endl; } } namespace ns2{ void func(void){ cout << "ns2 func" << endl; } } int main(void){ using ns1::func; func(); ns2::func(); return 0; }
using引用名字空间全部成员
#include <iostream> using namespace std; namespace ns1{ void func(void){ cout << "ns1 func" << endl; } int a = 100; } namespace ns2{ int a = 200; void func(void){ cout << "ns2 func" << endl; } } int main(void){ using namespace ns1; func(); ns2::func(); cout << a << endl; return 0; }
未命名的名字空间称作无名名字空间
#include <iostream>
//using namespace std;
namespace ns1{
void func(void){
std::cout << "ns1 func" << std::endl;
}
int a = 100;
}
namespace ns2{
int a= 200;
void func(void){
std::cout << "ns2 func" << std::endl;
}
}
namespace{
int a = 300;
}
int main(void){
ns1::func();
ns2::func();
std::cout << ns1::a << std::endl;
std::cout << ::a << std::endl;
return 0;
}
1.2.3 名字空间嵌套
#include <iostream>
using namespace std;
namespace ns1{
void func(void){
std::cout << "ns1 func" << std::endl;
}
int a = 100;
namespace ns2{
int b = 111;
}
}
int main(void){
cout << ns1::ns2::b << endl;
return 0;
}
1.3 数据类型的扩展
1.3.1 结构体、联合、枚举、布尔、字符串
结构体:
C++中定义结构型变量,可以省略struct关键字
C++结构体中可以直接定义函数,谓之成员函数(方法)
#include <iostream> #include <cstring> using namespace std; int main(void){ struct stu{ int age; char name[20]; void who(void){ cout <<"我是:" << name << " 我今年:" << age <<endl; } }; stu s1; s1.age = 21; strcpy(s1.name, "张飞"); s1.who(); return 0; }
联合:
C++中定义联合体变量,可以省略union关键字。
union XX{……}; XX x;//定义联合体变量直接省略union
支持匿名联合。
union{ //没有名字
……
};
#include <iostream> using namespace std; int main(void){ union{ //匿名联合 int num; char c[4]; }; num = 0x12345678; //hex 可以将整数以十六进制格式输出。 cout << hex << (int)c[0] <<" " << (int)c[1] << endl; return 0; }
枚举:
C++中定义枚举变量,可以省略enum关键字。
C++中枚举是独立的数据类型,不能当做整型数使用。
#include <iostream> using namespace std; int main(void){ enum COLOR{RED, GREEN, BLUE}; COLOR c = GREEN; //c = 2; //error cout << c << endl; return 0; }
布尔:
C++中布尔(bool)是基本数据类型,专门表示逻辑值。
布尔类型的字面值常量: true 表示逻辑真。
false表示逻辑假。
布尔类型的本质: 单字节的整数,使用1表示真,0表示假 任何基本类型都可以被隐式转换为布尔类型。
#include <iostream> using namespace std; int main(void){ bool b = true; cout << b <<endl; cout <<boolalpha << b <<endl; b = 3 + 2; cout <<boolalpha << b <<endl; return 0; }
字符串:
C++兼容C中的字符串表示方法和操作函数
C++专门设计了string类型表示字符串
string类型字符串定义
string s; //定义空字符串 string s("hello"); string s = "hello"; string s = string("hello");
字符串拷贝
string s1 = “hello”; string s2 = s1;
字符串连接
string s1 = “hello”, s2 = “ world”; string s3 = s1 + s2;//s3:hello world s1 += s2;//s1:hello world
字符串比较
string s1 = “hello”, s2 = “ world”; if(s1 == s2){ cout << “false”<< endl; } if(s1 != s2){ cout << “true”<< endl; }
随机访问
string s = “hello”; s[0] =“H”; //Hello
获取字符串长度
size_t size(); size_t length();
转换为C风格的字符串
const char* c_str();
字符串交换
void swap(string s1,string s2)
实例:
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
/*定义*/
string s1; //定义空字符串
string s2("aaa");
string s3 = string("bbb");
string s4 = "cccc";
/*字符串的拷贝*/
string s5 = s2; // char *p5 = p2;
cout << "s5 = " << s5 << endl;
/*拼接*/
s5 += s3;
cout << "s5 = " << s5 << endl;
/*字符串比较*/
if(s2 == s3){
//strcmp(.....)
cout << "true" << endl;
}else
cout << "false" << endl;
/*取字符串长度*/
cout << "s5 length = "<< s5.length() << endl;
/*转换为C风格字符串*/
const char *p = s5.c_str();
printf("%s\n", p);
/*交换*/
swap(s2, s3);
cout << "s2= "<< s2 << " s3= "<< s3<< endl;
return 0;
}
1.4 类型转换
类型转换分为隐式转换和显示转换。 写C/C++代码的时候,有时候不可避免的会使用类型转换,良好的编码风格中应该避免隐式转换,隐式转换有时候会产生不易察觉的问题。
1.4.1 隐式类型转换
C++定义了一套标准数据类型转换的规则,在必要时C++会用这套转换规则进行数据类型的转换。这种转换是在程序员不参与的情况下自动进 行的,所以成为隐式类型转换。转换原则:
多种数据类型的算术表达式中
int a = 2;
float b = 3.4;
double d = 2.2;
a+b+c;
将一种数据类型赋值给另外一种数据类型变量
int a = 2;
float b = 3.4;
long double d = 2.2;
b = a;
d = a;
函数调用时,若实参表达式与形参的类型不相符
int Min(int a, int b){
return a<b?a:b;
}
int a = 2;
float b = 3.4;
int x = Min(b, a+3.5);
函数返回时,如果返回表达式的值与函数返回类型不同
double add(int a, int b){
return a+b;
}
1.4.2 显示类型转换
显示类型转换也称为强制类型转换,是指把一种数据类型强制转换为指定的另一种数据类型。
int a = 4;
float c = (float) a; //C风格 c++也支持
float d = float(a); //C++风格 C不支持
C++ 提供了更严格的类型转换,可以提供更好的控制转换过程,C++增加了四个强制转换运算符: static_cast, dynamic_cast, const_cast和 reinterpret_cast.
静态类型转换 static_cast
目标类型变量 = static_cast (源类型变量)
用于隐式转换的逆转换,常用于基本数据类型之间的转换、void* 转换为其它类型的指针 不能用于整型和指针之间的互相转换 , 不能用于不同类型的指针、引用之间的转换 (风险高)
#include <iostream> #include <cstdlib> using namespace std; int main(void){ int a = 100; double a1 = (double)a; //c风格 double a2 = double(a);//C++风格 double b = static_cast<double>(a); void *p = malloc(100); int *pi = static_cast<int *>(p); char *pc = static_cast<char *>(p); //int num = static_cast<int>(p); //error //pi = static_cast<int *>(pc); //error return 0; }
重解释类型转换 reinterpret_cast
目标类型变量 = reinterpret_cast (源类型变量);
用于任意类型指针或引用之间的转换
指针和整型数之间的转换/
#include <iostream> #include <cstdlib> using namespace std; int main(void){ int a = 100; double a1 = (double)a; //c风格 double a2 = double(a);//C++风格 double b = static_cast<double>(a); void *p = malloc(100); int *pi = static_cast<int *>(p); char *pc = static_cast<char *>(p); //int num = static_cast<int>(p); //error //pi = static_cast<int *>(pc); //error int num = reinterpret_cast<int>(p); pi = reinterpret_cast<int *>(pc); int n = 0x00414243; char *ps = reinterpret_cast<char *>(&n); cout << ps << endl; cout << hex << n << endl ; return 0; }
常类型转换 const_cast
目标类型变量 = const_cast (源类型变量);
用于去除指针或引用的常属性
#include <iostream> using namespace std; int main(void){ int tmp = 123; const int *p1 = &tmp; //不能通过指针修改tmp对应的值 //(*p1)++; //error int *p2 = const_cast<int *>(p1);//去除常属性 *p2 = 10000; cout << tmp << endl; return 0; }
动态类型转换 dynamic_cast
目标类型变量 = dynamic_cast (源类型变量);
主要用于多态中类指针的向下转型,可以检测是否可以转型成功