以下内容为大学期间学习C++语言总结的知识:
《C++》基础入门_01——数据存储,表示形式,基本运算
《C++》基础入门_02——面向对象的总体概括
《C++》基础入门_03——程序的开发过程
《C++》基础入门_04——四大语句
《C++》基础入门_05——函数详解篇
《C++》基础入门_06——面向对象的详述
《C++》基础入门_07——数据的共享保护:const
《C++》基础入门_08——利用数组实现对批量数据的处理
《C++》基础入门_09——指针和引用的讲解
《C++》基础入门_10——用户自定义数据类型详细篇
《C++》基础入门_11——友元的讲解
《C++》基础入门_12——类模板
《C++》基础入门_13——运算符的重载
《C++》基础入门_14——继承与派生
《C++》基础入门_15——多态性
《C++》基础入门_16——输入输出流详讲
《C++》基础入门_17——对象串行化
《C++》基础入门_18——异常处理
《C++》基础入门_19——命名空间
《C++》基础入门_20——文件操作
《C++》基础入门_21——在函数中返回数组的常用方法
c++提供了一些类,专门用于输出输入。这些类组成一个流类库,简称流库。
流类库是采用继承方式建立的,这些类的两个基类:ios类和streambuf类,所有其他流类都是从他们直接或间接派生出来的。
iostream | 包含了对输入输出流进行操作所需的基本信息 |
fstream | 用于用户管理的文件的I/O操作 |
strstream | 用于字符串流 |
iomanip | 在使用格式化I/O时应包含此头文件 |
stdiostream | 用于混合使用c++和c的I/O时 |
最重要的三个输出流是
ostream类提供了数据流输出的功能,其流对象是流的目的地。在程序里可以将数据不断地插入流中,送至这些ostream流对象。
输出时使用的ostream流对象通常是cout,有3种基本操作方式:
ostream定义的三个输出流对象
插入运算符(<<)
用流对象的成员函数控制输出格式
1. 用于控制输出格式的流成员函数
使用width控制输出宽度
#include
using namespace std;
int main() {
double values[] = { 1.23, 35.36, 653.7, 4358.24 };
for (int i = 0; i < 4; i++) {
cout.width(10);
cout << values[i] << endl;
}
return 0;
}
使用*填充
#include
using namespace std;
int main() {
double values[] = { 1.23, 35.36, 653.7, 4358.24};
for (int i = 0; i < 4; i++) {
cout.width(10);
cout.fill('*');
cout << values[i] << '\n';
}
return 0;
}
使用setw指定宽度和对齐方式和控制输出精度
#include
#include
#include
using namespace std;
int main() {
double values[] = { 1.23, 35.36, 653.7, 4358.24};
string names[] = { "Zoot", "Jimmy", "Al", "Stan"};
for (int i = 0; i < 4; i++)
cout << setw(6) << names[i]<< setw(10) << values[i] << endl;
cout << endl;
cout << endl;
//设置对齐方式
for (int i = 0; i < 4; i++)
cout << setiosflags(ios_base::left)
<< setw(6) << names[i]
<< resetiosflags(ios_base::right)
<< setw(10) << values[i] << endl;
cout << endl;
cout << endl;
//控制输出精度
for (int i = 0; i < 4; i++)
cout << setiosflags(ios_base::left)
<< setw(6) << names[i]
<< resetiosflags(ios_base::left)
<< setw(10) << setprecision(1) << values[i]
<< endl;
return 0;
}
设置格式状态的格式标志
格式标志 | 作用 |
---|---|
ios::left | 输出数据在本域宽范围内向左对齐 |
os::right | 输出数据在本域宽范围内向右对齐 |
os::internal | 数值的符号位在域宽内左对齐,数值右对齐,中间由填充字符填充 |
ios::dec | 设置整数的基数为10 |
os::oct | 设置整数的基数为8 |
os::hex | 设置整数的基数为16 |
ios::showbase | 强制输出整数的基数(八进制数以0打头,十六进制数以0x打头) |
os::showpoint | 强制输出浮点数的小点和尾数0 |
os::uppercase | 在以科学记数法格式E和以十六进制输出字母时以大写表示 |
ios::showpos | 对正数显示“+”号 |
ios::scientific | 浮点数以科学记数法格式输出 |
os::fixed | 浮点数以定点格式(小数形式)输出 |
ios::unitbuf | 每次输出之后刷新所有的流 |
os::stdio | 每次输出之后清除stdout, stderr |
#include
#include
using namespace std;
int main( ){
int a = 21;
cout.setf(ios::showbase); //显示基数符号(0x或)
cout<<"dec:"<<a<<endl; //默认以十进制形式输出a
cout.unsetf(ios::dec); //终止十进制的格式设置
cout.setf(ios::hex); //设置以十六进制输出的状态
cout<<"hex:"<<a<<endl; //以十六进制形式输出a
cout.unsetf(ios::hex); //终止十六进制的格式设置
cout.setf(ios::oct); //设置以八进制输出的状态
cout<<"oct:"<<a<<endl; //以八进制形式输出a
const char *pt="China"; //pt指向字符串"China"
cout.width(10); //指定域宽为
cout<<pt<<endl; //输出字符串
cout.width(10); //指定域宽为
cout.fill('*'); //指定空白处以'*'填充
cout<<pt<<endl; //输出字符串
double pi=22.0/7.0; //输出pi值
cout.setf(ios::scientific); //指定用科学记数法输出
cout<<"pi="; //输出"pi="
cout.width(14); //指定域宽为
cout<<pi<<endl; //输出pi值
cout.unsetf(ios::scientific); //终止科学记数法状态
cout.setf(ios::fixed); //指定用定点形式输出
cout.width(12); //指定域宽为
cout.setf(ios::showpos); //正数输出“+”号
cout.setf(ios::internal); //数符出现在左侧
cout.precision(6); //保留位小数
cout<<pi<<endl; //输出pi,注意数符“+”的位置
return 0;
}
#include
#include
#include
using namespace std;
int main() {
double values[] = { 1.23, 35.36, 653.7, 4358.24 };
string names[] = { "Zoot", "Jimmy", "Al", "Stan" };
for (int i = 0; i < 4; i++)
cout << setiosflags(ios_base::left)
<< setw(6) << names[i]
<< resetiosflags(ios_base::right)
<< setw(10) << values[i] << endl;
return 0;
/*
Zoot 1.23
Jimmy 35.36
Al 653.7
Stan 4358.24
*/
}
```
>
#include
#include
using namespace std;
int main() {
const char *p = "I am a good girl";
for (int i = 0; i < 10; i++)
cout.put(*(p + i));
cout.put('\n');
cout.put(65 + 32);//输出ASCII对应的字符
return 0;
/*
I am a goo
a
*/
}
if(!cin) cout<<“error”;
无参,
调用形式:cin.get();
用于从指定的输入流提取一个字符,包括空白字符,函数返回值为读到的字符。若遇到文件结束符,返回EOF(-1)。
c语言中对应的有getchar();
#include
#include
#include
using namespace std;
int main() {
int c;
cout << "enter a sentence:" << endl;
while ((c = cin.get()) != EOF)
cout.put(c);
return 0;
/*
enter a sentence:
i sds sdsds we
i sds sdsds we
*/
}
一个参
调用形式:cin.get(ch);
用于从指定的输入流提取一个字符,赋给字符变量ch。读取成功,返回非零值,否则返回0。
三个参数
调用形式:
cin.get(字符数组,字符个数,终止字符);
cin.get(字符指针,字符个数,终止字符);
用于从指定的输入流提取n-1个字符,赋给数组或指针。读取到设定的终止字符·处。读取成功,返回非零值,否则返回0。
cin.getline(ch,20,’/’):读入19个字符或者遇到‘/’结束,在最后一位加‘/0’,存入数组或指针ch中
eof函数
表示文件结束。
从输入流中读取数据,如果到达文件末尾(遇到文件结束符),eof函数值为非0值,否则为0(假)。
int c;
cout << "enter a sentence:" << endl;
while (!cin.eof())
if((c=cin.get())!=' ')//检查输入字符是否为空格字符
cout.put(c);
peek函数
putback函数
#include
#include
#include
using namespace std;
int main() {
char c[20];
int ch;
cout << "enter a sentence:" << endl;
cin.getline(c, 15, '/');
cout << "first part:" << c << endl;
ch = cin.peek();
cout << "the next char is:" << ch << endl;
cin.putback(c[0]);
cin.getline(c, 15, '/');
cout << "second part:" << c << endl;
return 0;
ignore函数
#include
#include
#include
using namespace std;
int main() {
char c[20];
cout << "enter a sentence:" << endl;
cin.get(c, 20, '/');
cout << "first part:" << c << endl;
cin.ignore();//若不加此函数,next patr 无法取到值,因为当前指针停在/处
cin.get(c, 20, '/');
cout << "the next part:" << c<< endl;
return 0;
/*
enter a sentence:
i like c++./l study c++./i am unhappy.
first part:i like c++.
the next part:l study c++.
*/
}
文件原理: 文件打开都有一个文件指针,该指针的初始位置由I/O方式指定,每次读写都从文件指针的当前位置开始。每读入一个字节,指针就后移一个字节。当文件指针移到最后,就会遇到文件结束EOF(文件结束符也占一个字节,其值为-1),此时流对象的成员函数eof的值为非0值(一般设为1),表示文件结束 了。
文件是程序的一个重要部分。文件一般是存储在外部介质上数据的集合。
操作系统以文件为单位对数据进行管理。
常见文件分类:
根据文件中数据的组织形式:
1. 对于字符来说,在内存中以ASCII码存放,每一个字节放一个ASCII代码,因此无论用ASCII文件输出还是二进制文件输出,其数据形式一样。
2. 对于数值数据,二者不同。
比如:整数100000,在内存中占有4个字节,若按内部格式直接输出,在磁盘中占有4个字节,但是转换成ACSII形式输出,6个字符占有6个字节。
c++提供了二种I/O:
例如将内存中的数据送到显示器上输出,先把内存中的数据转换成ASCII字符,然后按照整型,浮点型等形式输出。
用于文件操作的文件类:
以上工作通过二种方式实现:
调用文件流的成员函数open。
一般调用方式:
文件流对象.open(磁盘文件名,输入输出方式);
磁盘文件名可以包含路径,若缺省则默认当前目录下的文件。
若打开失败则open函数返回值为0.
例如:
ofstream outfile; //建立一个文件输出类对象
outfile.open(“f1.dat”,ios::out); //使文件流与f1.dat建立联系
outfile.open(“C:\c++\f1.dat”,iso::out);
iso::out:是I/O的一种,表示以输出方式打开文件。
在定义文件流对象时指定参数
声明文件流对象时定义了带参数的构造函数,其中包括打开文件的功能。
调用形式:
文件流类 文件流对象名(“文件路径”,输入输出方式)
若打开失败,流对象返回值为0。
例如:
ostream outfile(“f1.dat”,ios::out);
文件的每个字节都以ACSII形式存放,此文件为ASCII文件。
对ASCII读写操作有两种:
用流插入运算符“<<”和流提取“>>"运算符输入输出标准类型的数据。
由于ofstream和ifstream从ostream和istream类继承了公用的重载函数,所以对磁盘文件的操作,可以通过文件流对象和流插入,流提取运算符对文件进行读写。
写入文件内容:
#include
#include
using namespace std;
int main() {
int a[10];
ofstream outfile("f1.dat", ios::out); //定义文件流对象,打开磁盘文件f1.dat
if (!outfile) { //若打开失败,返回0
cerr << "open error!" << endl;
exit(1);
}
cout << "please enter 10 integer number:" << endl;
for (int i = 0; i < 10; i++) {
cin >> a[i];
outfile << a[i] << " "; //将键盘输入的数据输出到磁盘文件
}
outfile.close(); //关闭文件流
return 0;
文件建立在了当前程序存放空间下的地方。若不存在此文件,会新建一个f1.dat文件,若存在,则直接打开此文件并覆盖其内容。
读取文件内容
#include
#include
using namespace std;
int main() {
int a[10];
ifstream infile("f1.dat",ios::in|ios::_Nocreate); //定义文件流对象,以输入方式打开磁盘文件f1.dat若不存在也不会新建此文件。
if (!infile) {
cerr << "open error!" << endl;
exit(1);
}
for (int i = 0; i < 10; i++) {
infile>> a[i]; //从磁盘读取10个字符,顺序存放在数组中。
cout << a[i]<<" ";
}
cout << endl;
infile.close();
return 0;
}
用文件流的put,get,getline等成员函数进行字符的输入输出。
#include
#include
using namespace std;
//此函数从键盘读取一行字符并把字母存入磁盘文件
void save_to_file() {
ofstream outfile("f2.txt", ios::out);//定义输出流文件对象,以输出方式打开磁盘文件f2
if (!outfile) {
cerr << "open error!"<<endl;
exit(1);
}
char c[100];
cin.getline(c, 100); //从键盘上读取一行字符
for (int i = 0; c[i] != 0; i++) {
if (c[i] >= 65 && c[i] <= 90 || c[i] >= 97 && c[i] <= 122) {//判断是否为字母
outfile.put(c[i]);//若为字母保存在文件f2中
cout << c[i]; //并显示在屏幕上
}
}
cout << endl;
outfile.close();
}
//此函数读取文件中所以字母,并把所以小写字母转化为大写字母,全部存入f3文件中
void get_from_file() {
char ch;
ifstream infile("f2.txt", ios::in | ios::_Nocreate);
if (!infile) {
cerr << "open f2.txt error!" << endl;
exit(1);
}
ofstream outfile("f3.txt", ios::out);
if (!outfile) {
cerr << "open f3.txt error!" << endl;
exit(1);
}
while (infile.get(ch)) {//从磁盘文件读取字符,直到文件结束
if (ch >= 97 && ch <= 122)
ch -= 32;
outfile.put(ch);//读取的单个字符存入f3文件
cout << ch;
}
cout << endl;
infile.close();
outfile.close();
}
//读取磁盘文件内容
void display_file(string s) {
ifstream infile(s,ios::in);
if (!infile) {
cerr << "open error" << endl;
exit(1);
}
char ch;
while (infile.get(ch))
cout.put(ch);
cout << endl;
infile.close();
}
int main() {
save_to_file();
get_from_file();
display_file("f3.txt");
return 0;
}
用成员函数read和write读写二进制文件
对二进制文件的读写主要用istream类的成员函数read和write来实现
istream& read(char *buffer,int len);
ostream& write(const char * buffer,int len);
read函数的功能是从输入流中顺序读取len个字符,并存入到buffer所指向的字
符数组中。它与get函数、getline函数的区别是,不在读取的这些字符的尾部添加一个空字符(’\0’)。
存二进制文件
#include
#include
using namespace std;
struct Student {
char name[20];
int age;
char sex;
};
int main() {
Student stu[3] = { {"Tom",18,'f' },{"Sun",17,'f'},{"Rain",13,'f'} };
ofstream outfile("student.dat", ios::binary);
if (!outfile) {
cerr << "open error " << endl;
abort();
}
//此处if语句可以改写成write.((char*)&stu[0],sizeof(stu));
for (int i = 0; i < 3; i++) {
outfile.write((char *)&stu[i], sizeof(stu[i]));
}
outfile.close();
return 0;
}
读取二进制文件
#include
#include
using namespace std;
struct Student {
char name[20];
int age;
char sex;
};
int main() {
Student stu[3];
ifstream infile("student.dat", ios::binary);
if (!infile) {
cerr << "open error " << endl;
abort();
}
for (int i = 0; i < 3; i++) {
infile.read((char *)&stu[i], sizeof(stu[i]));
}
infile.close();
for (int i=0; i < 3; i++) {
cout << stu[i].name << " " << stu[i].age << " " << stu[i].sex << endl;
}
return 0;
/*
Tom 18 f
Sun 17 f
Rain 13 f
*/
}
以文件指针有关的流成员函数
员函数 | 作用 |
---|---|
gcount() | 得到最后一次输入所读入的字节数 |
ellg() | 得到输入文件位置标记的当前位置 |
ellp() | 得到输出文件位置标记当前的位置 |
eekg(文件中的位置) | 将输入文件位置标记移到指定的位置 |
eekg(位移量,参照位置) | 以参照位置为基础移动若干字节 |
eekp(文件中的位置) | 将输出文件位置标记移到指定的位置 |
eekp(位移量,参照位置)) | 以参照位置为基础移动若干字节 |
参照位置
ios::beg | 文件开头(默认) |
---|---|
ios::cur | 位置标记当前的位置 |
os::end | 文件的末尾 |
infile.seekg(100): 输入文件位置标记向前移到100字节位置
infile.seekg(-50,ios::cur):输入文件位置标记从当前位置后移50字节
infile.seekg(-50,ios::end):输入文件位置标记从文件尾后移50字节
随机访问二进制数据文件
一般文件的读写时顺序进行的,逐个字节读写。但是对于二进制文件来说,可用成员函数移动指针,随机访问任意位置的数据,还可以修改文件中的数据。
#include
#include
using namespace std;
struct Student {
char name[20];
int age;
};
int main() {
Student stu[5] = {"A",12,"df",23,"wq",21,"sds",32,"ed",23};
fstream iofile("student.dat",ios::in|ios::out|ios::binary);
if (!iofile) {
cerr << "open error " << endl;
abort();
}
for (int i = 0; i < 5; i++) {
iofile.write((char*)&stu[i], sizeof(stu[i]));
}
Student stu1[5];
for(int i=0;i<5;i+=2){
iofile.seekg(i*sizeof(stu[i]),ios::beg);//定位于0,2,4学生数据开头
iofile.read((char*)&stu1[i / 2], sizeof(stu1[0]));//先后读入三个学生的数据,存入stu1[0],stu1[1],stu1[2]
cout << stu1[i/2].name << " " << stu1[i/2].age << endl;
}
cout << endl;
strcpy_s(stu[2].name, "yj");
stu[2].age = 18;
iofile.seekp(2 * sizeof(stu[0]), ios::beg);//定位第3个学生数据开始处
iofile.write((char*) &stu[2], sizeof(stu[2]));//更新第3个学生数据
iofile.seekg(0, ios::beg);
for (int i = 0; i < 5; i++) {
iofile.read((char*)&stu[i], sizeof(stu[i]));
cout << stu[i].name << " " << stu[i].age << endl;
}
iofile.close();
return 0;
/*
A 12
wq 21
ed 23
A 12
df 23
yj 18
sds 32
ed 23
*/
}
举例:
#include
#include
using namespace std;
#include
class Teacher
{
public:
Teacher() {}
Teacher(int sno, const char name[]){
this->sno= sno;
strcpy_s(this->name, name);
}
void prinf(){
cout << "Teacher name:" << this->name << " sno:" << this->sno << endl;
}
private:
int sno;
char name[20];
};
int main()
{
Teacher t1( 1001 ,"Tom");
Teacher t2( 1002 , "Rain");
Teacher t3( 1003 , "Sun");
Teacher t4( 1004 , "Jain");
fstream fs("teacher", ios::binary | ios::out);
if (!fs)
{
cout << "文件打开失败" << endl;
}
fs.write((char *)&t1, sizeof(Teacher));
fs.write((char *)&t2, sizeof(Teacher));
fs.write((char *)&t3, sizeof(Teacher));
fs.write((char *)&t4, sizeof(Teacher));
fs.flush();
fs.close();
fstream fs2("teacher", ios::binary | ios::in);
if (!fs)
{
cout << "文件打开失败" << endl;
}
Teacher t;
fs2.read((char *)&t, sizeof(Teacher));
t.prinf();
fs2.read((char *)&t, sizeof(Teacher));
t.prinf();
fs2.read((char *)&t, sizeof(Teacher));
t.prinf();
fs2.read((char *)&t, sizeof(Teacher));
t.prinf();
fs2.close();
system("pause");
return 0;
}
ostrstream类提供的函数构造原型:
ostrstream :: ostrstream (char *buffer, int n,int mode=iso::out);
ostrstream strout (ch1,20);
建立输出字符串流对象strout,并与字符数组ch1关联,流缓冲区大小为20.
istrstream类提供的函数构造原型:
istrstream :: istrstream (char *buffer );
istrstream :: istrstream (char *buffer, int n);
- istrstream strin (ch1);
建立输入字符串流对象strin,并与字符数组ch1关联,将ch1的全部数据作为流全部输入。- istrstream strin (ch1,20);
建立输入字符串流对象strin,并与字符数组ch1关联,将ch1的前20个字符作为流输入。
strstream类提供的函数构造原型:
strstream :: strstream (char *buffer, int n,int mode);
strstream strio(ch ,sizeof(ch),ios::in|ios::out);
建立输入输出字符串流对象strio,并与字符数组ch关联,流缓冲区大小为字符数组ch的大小.
#include
#include
#include
using namespace std;
struct Student {
int sno;
string name;
};
int main() {
Student stu[3] = { 1001,"Tom",1002,"Rain",1003,"Sun" };
char c[50];
ostrstream strout(c, 30);
for (int i = 0; i < 3; i++) {
strout << stu[i].sno << " " << stu[i].name << endl;
}
strout << ends;
cout << "array c:" << endl;
cout << "array c:" << c << endl;
return 0;
/*
array c:
1001 Tom
1002 Rain
1003 Sun
*/
}
例:
string s = “这是一个中文字符串”;
s.size():返回18
s.substr(3,2):得到的结果是“且”
s.find(“且”):返回3
宽字符:对宽字符的支持其实是ANSI C标准的一部分,用以支持多字节表示一个字符。宽字符和Unicode并不完全等同,Unicode只是宽字符的一种编码方式。在ANSI中,一个字符(char)的长度为一个字节(Byte)。使用Unicode时,一个字符占据一个字.
C++在wchar.h头文件中定义了最基本的宽字符类型
wchar_t :typedef unsigned short wchar_t;
例: wchar_t c = L’人’;
与string同源
1. typedef basic_string string;
2. typedef basic_string
>例如:
wstring s = L"这是一个中文字符串";
s.size():返回9
例:L“ABCD”占4个字节,L“甲乙丙丁”占8个字节,这由编码方案体现
示例
locale loc(".936"); //创建本地化配置方案对象
wcout.imbue(loc); //设置wcout对象的编码方案
wcout << L"这是一个中文字符串" << endl; //输出字符串
C/C++程序中,locale(即系统区域设置,即国家或地区设置)将决定程序所使用的当前语言编码、日期格式、数字格式及其它与区域有关的设置,locale设置的正确与否将影响到程序中字符串处理(wchar_t如何输出、strftime()的格式等)。因此,对于每一个程序,都应该慎重处理locale设置。
C locale和C++ locale是独立的。C locale用setlocale(LC_CTYPE, “”)初始化,
C++ locale用std::locale::global(std::locale(“”))初始化。这样就可以根据当前运行环境正确设置locale。
关于locale的详细讲解请点击:https://blog.csdn.net/haiross/article/details/45074355?utm_source=copy