首页 > 编程语言 >C++高级编程(8)

C++高级编程(8)

时间:2024-11-09 20:16:24浏览次数:3  
标签:文件 string int 编程 高级 C++ include 异常 cout

八、标准IO库

1.输入输出流类

1)非格式化输入输出

2)put

#include <iostream>
#include <string>
​
using namespace std;
int main()
{
    string str = "123456789";
    for (int i = str.length() - 1; i >= 0; i--) 
    {
        cout.put(str[i]); //从最后一个字符开始输出
    }
    
    cout.put('\n');
    return 0;
}

3)write

#include <iostream>
using namespace std;
​
int main() 
{
    const char * str = "www.cplusplus.com";
    cout.write(str, 4);
    
    return 0;
}

4)格式化输入/输出

  • C++提供了大量的用于执行格式化输入/输出的流操纵符和成员函数。

  • 功能:

    • 打印地址: cout << (void*)a;

    • 整数流的基数:dec、oct、hex和setbase

    • 设置浮点数精度:precision、setprecision

    • 设置域宽:setw、width

  • 注:如果用到了含参数的流操纵算子,则必须包含头文件< iomanip >。

5)<<运算符重载

class Complex
{
    double real,imag;
public:
    Complex( double r=0, double i=0):real(r),imag(i){ };
    friend ostream & operator<<( ostream & os,const Complex & c);
};
​
ostream & operator<<( ostream & os,const Complex & c)
{
    os << c.real << "+" << c.imag << "i";
    return os;
}
​
int main()
{
    Complex c(3, 5);
    int n = 220;
    cout << c << "," << n;
    
    return 0;
}

6)hex、oct、dec和setbase

#include <iostream>
#include <iomanip>
using namespace std;
​
int main()
{
    int number;
    cout << "Enter a decimal number: ";
    cin >> number;
    cout << number << " in hexadecimal is: " << hex<< number << endl;
    cout << dec << number << " in octal is: " << oct << number << endl;
    cout << setbase(10) << number << " in decimal is: " << number << endl;
    
    return 0;
}
​
/*
输出结果:
Enter a decimal
number: 20
20 in hexadecimal is:14
20 in octal is: 24
20 in decimal is: 20
*/

7)浮点精度(precision,setprecision)

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
​
int main()
{
    double root2 = sqrt( 2.0 );
    int places;
    
    // use fixed point format
    cout << fixed;
    for ( places = 0; places <= 9;places++ )
    {
        cout.precision( places );
        cout << root2 << endl;
    }
    for ( places = 0; places <= 9; places++ )
    {
        cout << setprecision( places ) <<
        root2 << endl;
    }
    return 0;
}

8)域宽(width,setw)

#include <iostream>
#include <iomanip>
using namespace std;
​
int main()
{
    int widthValue = 4;
    char sentence[ 10 ];
    cout << "Enter a sentence:" << endl;
    cin.width( 5 );
    while ( cin >> sentence )
    {
        cout.width( widthValue++ );
        cout << sentence << endl;
        //cout<<setw(widthValue++) << sentence << endl;
        cin.width( 5 );
    }
    
    return 0;
}

9)用户自定义的流操纵算子

#include <iostream>
using namespace std;
​
ostream& bell( ostream& output )
{
    return output << '\a'; // issue system beep
}
​
ostream& carriageReturn( ostream& output )
{
    return output << '\r'; // issue carriage return
}
​
ostream& tab( ostream& output )
{
    return output << '\t'; // issue tab
}
​
ostream& endLine( ostream& output )
{
    return output << '\n' << flush; // issue endl-like end of line
}
​
int main()
{
    cout << "Testing the tab manipulator:" << endLine<< 'a' << tab << 'b' << tab << 'c' << endLine;
    cout << "Testing the carriageReturn and bell manipulators:"<< endLine << "..........";
    cout << bell; // use bell manipulator
    cout << carriageReturn << "-----" << endLine;
​
    return 0;
}

2.文件操作

  • 临时数据

    • 存储在变量和数组中的数据是临时的,这些数据在程序运行结束后都会消失。

  • 文件

    • 目的:文件用来永久地保存大量的数据。

    • 存储:计算机把文件存储在二级存储设备中(特别是磁盘存储设备)。

1)文件中的数据层次

  • 位(bit): 最小数据项:0和1

  • 字符(character)/字节(byte)

    字符:数字、字母和专门的符号

    字节:0、1序列 (常见的是8位/字节)

    字符用字节表示

  • 域(field):一组有意义的字符

  • 记录(record)

    • 一组相关的域

    • 记录关键字(record key):用于检索

  • 文件(file):一组相关的记录

  • 数据库:一组相关的文件

2)文件和流

  • C++语言把每一个文件都看成一个有序的字节流(把文件看成n个字节)

  • 每一个文件或者以文件结束符(end-of-file marker)结束,或者在特定的字节号处结束

  • 当打开一个文件时,该文件就和某个流关联起来

  • 与这些对象相关联的流提供程序与特定文件或设备之间的通信通道

3)文件输出例子

#include <iostream>
#include <fstream> // file stream
#include <cstdlib>
using namespace std;
​
int main()
{
    ofstream outClientFile( "clients.dat", ios::out );//打开文件
    
    // exit program if unable to create file
    if ( !outClientFile ) // overloaded ! operator
    {
        cerr << "File could not be opened" << endl;
        exit( 1 );
    }
    
    cout << "Enter the account, name, and balance." << endl
    << "Enter end-of-file to end input.\n? ";
    
    int account;
    char name[ 30 ];
    double balance;
​
    // read account, name and balance from cin, then place in file
    while ( cin >> account >> name >> balance )
    {
        outClientFile << account << ' ' << name << ' ' << balance << endl;//写文件
        cout << "? ";
    }
    
    return 0; // ofstream destructor closes file
}
​
/*
输出结果:
Enter the account, name, and balance. Enter end-of-file to end input. ? 100 Jones 24.98
? 200 Doe 345.67
? 300 White 0
? 400 Stone -42.16
? 500 Rich 224.62
? ^z
*/

4)文件访问

  • 定义一个流对象

  • 打开文件

  • 访问文件

  • 关闭文件

(1)测试文件打开是否成功
  • 用重载的ios运算符成员函数operator!确定打开操作是否成功。如果open操作的流将failbit或badbit设置,则这个条件返回非0值(true)。

  • 可能的错误是:

    • 试图打开读取不存在的文件

    • 试图打开读取没有权限的文件

    • 试图打开文件以便写入而磁盘空间不足。

(2)测试文件结束符与不合法输入
  • 另一个重载的ios运算符成员函数operator void将流变成指针,使其测试为0(空指针)或非0(任何其他指针值)。如果failbit或badbit对流进行设置,则返回0(false)。

  • 下列while首部的条件自动调用operator void*成员函数:

    Line 26: while (cin >> account >> name >>balance )只要cin的failbit和badbit都没有设置,则条件保持true。输入文件结束符设置cin的failbit。operator void*函数可以测试输入对象的文件结束符,而不必对输入对象显式调用eof成员函数。

(3)打开输入文件
  • ifstream inClientFile( “clients.dat” , ios::in );

  • 生成ifstream对象inClientFile,并将其与打开以便输入的文件clients.dat相关联。括号中的参数传入ifstream构造函数,打开文件并建立与文件的通信线路。

  • 打开ifstream类对象默认为进行输入,因此下列语句等价:

    ifstream inClientFile( “Clients.dat” );

  • 和ofstream对象一样,ifstream对象也可以生成而不打开特定文件,然后再将用open对象与文件相连接。

//文件输出例子
#include <iostream>
#include <fstream> // file stream
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;
​
void outputLine( int, const string, double ); // prototype
​
int main()
{
    // ifstream constructor opens the file
    ifstream inClientFile( "clients.dat", ios::in );
    
    // exit program if ifstream could not open file
    if ( !inClientFile )
    {
        cerr << "File could not be opened" << endl;
        exit( 1 );
    } // end if
    
    int account;
    char name[ 30 ];
    double balance;
    cout << left << setw( 10 ) << "Account" << setw( 13 )<< "Name" << "Balance" << endl << fixed << showpoint;
​
    // display each record in file
    while ( inClientFile >> account >> name >> balance )
    {
        outputLine( account, name, balance );
    }
    return 0; // ifstream destructor closes the file
}
​
    // display single record from file
    void outputLine( int account, const string name, double balance )
    {
    cout << left << setw( 10 ) << account << setw( 13 ) << name<< setw( 7 ) << setprecision( 2 ) << right << balance << endl;
    }

5)文件位置指针

  • 为了按顺序检索文件中的数据,程序通常要从文件的起始位置开始读取数据,然后连续地读取所有的数据,直到找到所需要的数据为止。可能需要反复多次。

  • 文件位置指针( file position pointer):用于指示读写操作所在的下一个字节号;是个整数值,指定文件中离文件开头的相对位置(也称为离文件开头的偏移量)

6)文件指针重新定位

  • istream类和ostream类都提供成员函数,使文件位置指针重新定位

    • istream类的seekg (即“seekget”) :每个istream对象有个get指针,表示文件中下一个输入相距的字节数

    • ostream类的seekp (即“seekput”):每个ostream对象有一个put指针,表示文件中下一个输出相距的字节数

  • seekg和seekp的第一个参数通常为long类型的整数,表示偏移量。第二个参数可以指定寻找方向:

    ios::beg(默认)相对于流的开头定位

    ios::cur相对于流当前位置定位

    ios::end相对于流结尾定位

7)获取文件指针值

  • 成员函数tellg和tellp分别返回get和put指针的当前位置。

下列语句将get文件位置指针值赋给long类型的变量

location。

location = filObject.tellg();

8)更新顺序访问文件

  • 格式化和写入顺序访问文件的数据修改时会有破坏文件中其他数据的危险

  • 例如,如果要把名字“White”改为“Worthington” ,则不是简单地重定义旧的名字。White的记录是以如下形式写入文件中的:

    300 White 0.00

    如果用新的名字从文件中相同的起始位置重写该记录,记录的格式就成为:

    300 Worthington 0.00

  • 因为新的记录长度大于原始记录的长度,所以从“Worthington”的第二个“o”之后的字符将重定义文件中的下一条顺序记录。

  • 出现该问题的原因在于:在使用流插入运算符<<和流读取运算符>>的格式化输入,输出模型中,域的大小是不定的,因而记录的大小也是不定的。例如,7、14、-117、2047和27383都是int类型的值,虽然它们的内部存储占用相同的字节数,因此,格式化输入输出模型通常不用来更新已有的记录。

  • 一种解决方法:将在3000 White 0.00之前的记录复制到一个新的文件中,然后写入新的记录并把300 White 0.00之后的记录复制到新文件中。这种方法要求在更新一条记录时处理文件中的每一条记录。如果文件中一次要更新许多记录,则可以用这种方法。

3.STRING类

  • C++、java等编程语言中的字符串。

  • 在java、C#中,String类是不可变的,对String类的任何改变,都是返回一个新的String类对象。

  • String 对象是 System.Char 对象的有序集合,用于表示字符串。String 对象的值是该有序集合的内容,并且该值是不可变的

为什么需要string?

  • 在内部进行内存分配,从而保证应用程序的健壮性

  • 提供了拷贝构造函数和复制运算符,确保字符串的正确复制

  • 减少程序员创建和操作字符串需要做的工作

  • 提供了增删改查的操作,让程序员可以把精力放在应用程序的主要需求上,而不是字符串的操作细节。

1)string对象的定义和初始化

string s1;
string s2(s1);
string s3("value");
string s4(n,'c');

2)string对象的读写

  • 读入未知数目的string对象

    while(cin>>world)

    cout <<world <<endl;

  • 用getline读取整行

    getline(cin, s);

3)string对象的操作

s.empty();
s.size();
s[n]; //下标操作 范围0~?
s1+s2;
s1=s2;
v1==v2;
!= < <=
> >=

4)string对象中字符的处理

4.异常处理

1)C错误处理机制

  1. 函数返回错误编码

  2. 使用全局变量保存错误编码

  3. 出错时终止程序运行

  • 缺点:

    • 难以统一标准

    • 复杂

    • 构造和析构函数没有返回值

    • 出错就返回,用户接受度低

2)异常处理机制

  • C++异常处理的基本思想是简化程序的错误代码,为程序的健壮性提供了一个标准检测机制:若底层发生问题,则逐级上报,直到有能力处理此异常为止。

  • 异常处理的优势:

  1. 增强程序的健壮性。

  2. 使代码变得更简洁优美,更易维护。

  3. 错误信息更灵活丰富。

  • 缺点:

  1. 性能下降5%~14%。

2. 破坏了程序的结构性。

  1. 完成正确的异常安全的代码,需要付出更大的代价。

3)抛出异常

任何时候,程序在执行中遇到了非正常状况都可以抛出异常异常用throw语句抛出

A *p = new A;

if (p == NULL)

{

throw string(“Out of Memory.”);

}

一旦抛出异常,则程序将在throw语句处跳出

4)捕获异常

异常也由程序员负责捕获

用try{…}catch( ){…}语句来捕获异常

没有捕获的异常将被忽略

try{

// 可能抛出异常的语句

}catch(exceptionType variable){

// 处理异常的语句

}

//捕获异常的例子
#include <iostream>
#include <string>
#include <exception>
using namespace std;
​
int main()
{
    string str = "http://www.cplusplus.com";
    try{
        char ch1 = str[100];
        cout<<ch1<<endl;
        }catch(exception e){
            cout<<"[1]out of bound!"<<endl;
        }
    
    try{
    char ch2 = str.at(100);
    cout<<ch2<<endl;
        }catch(exception &e){ //exception类位于<exception>头文件中
            cout<<"[2]out of bound!"<<endl;
        }
    
    return 0;
}
//捕获任意异常例子
#include <iostream>
using namespace std;
int main( )
{
    int a, b;
    a = 8;
    b = 0;
    try
    {
        if (b == 0)
        {
        throw "Divided by Zero!";
        }else
        {
        double c = a/b;
        cout << c << endl;
        }
    }catch(...)
    {
    cout << "Exception caught!" << endl;
    }
}

5)异常处理的流程

抛出(Throw)--> 检测(Try) --> 捕获(Catch)

6)异常的传递

  • 产生异常之后,程序会立刻跳转

    • 跳出到最近的一层捕获异常的语句

    • 如果当前没有捕获语句或者捕获语句中没有匹配的异常,则程序会跳出当前的函数

  • 在函数的调用处,如果没有捕获住异常,则直接跳转到更高一层的调用者

  • 如果一直没有捕获该异常,C++将会使用默认的异常处理函数

    • p 该处理函数可能会让程序最终跳出main函数并导致程序异常终止

7)C++标准的异常

8)异常的说明

标签:文件,string,int,编程,高级,C++,include,异常,cout
From: https://blog.csdn.net/m0_71616132/article/details/143604395

相关文章

  • 实验3 类和对象——基础编程2
    一、实验目的 加深对类的组合机制的理解,会正确使用C++正确定义,使用组合类理解深复制,浅复制练习标准库string,vector的用法,能基于问题场景灵活使用针对具体问题场景,练习运用面向对象思维进行设计,合理设计,组合类(自定义/标准库),编程解决实际问题。二、实验准备 系统复习浏览......
  • C++基础学习1
    //写代码//1.写出主函数(main函数)//可能写出1-500行代码//如何执行呢?-C语言的代码是从主函数的第一行开始执行的!//主函数=main函数//所以C语言代码中需要有main函数,main函数属于是入口,没有入口就无法执行。//int=函数的返回类型,int是整型的意思(是整数的意思)//main=函数名......
  • 天天学编程Day11
    每日一道编程题104.二叉树的最大深度classSolution{public:intans=0;intmaxDepth(TreeNode*root){dfs(root,1);returnans;}//使用深度优先遍历遍历二叉树记录路径长度不断更新全局变量最长长度//遍历完成后ans即为......
  • 面对对象编程:OOP类与对象详细笔记
    文章目录类类的概念:类的定义:类的属性(成员变量):**类的方法(成员方法):**对象对象的创建与使用:this关键字:构造方法:类与对象的关系:封装:无参方法有参方法类类的概念:类是一种用户定义的数据类型,它描述了一组具有相同特性和行为的对象。类定义了对象的状态(属性)和行为(方法)。......
  • 在 C++ 中,实现线程同步主要有以下几种常见方法
    互斥锁(Mutex)原理:互斥锁用于保护共享资源,确保在同一时刻只有一个线程能够访问被保护的资源。当一个线程想要访问共享资源时,它首先尝试获取互斥锁。如果锁已经被其他线程持有,那么该线程会被阻塞,直到锁被释放。一旦获取到锁,线程就可以安全地访问共享资源,访问结束后再释放锁,以便其......
  • 在C++中,条件变量的等待操作是如何实现的?
    在C++中,条件变量的等待操作主要通过std::condition_variable类来实现,其等待操作涉及到与互斥锁的配合使用,以下是详细的实现过程:包含必要的头文件首先需要包含<condition_variable>和头文件,因为条件变量std::condition_variable的使用需要与互斥锁(如std::mutex)协同工作,同时还......
  • 退休后编程?
    也算半退休状态,学习新的编程语言基本上不可能了,没精力也没用武之地。但是,我觉得有些代码,还会一直写下去。①VBA,我估计写了10年以上VB代码,用VB干过各种事情,应用软件,Web终端,通信的,办公的,共享软件……没想到,老了以后,发现可能会一直用下去,还是vb代码。如果我评价哪个语言最有价值,我认......
  • PHP、Java、Python、C、C++ 这几种编程语言都各有什么特点或优点?
    相信每一个计算机科班出身的同学或许都有这样的经历:在大三的某一天,仿佛打通了全身筋脉一般把三年的所学:“数电里的与非门——[计算机体系结构]——汇编语言——C语言——C++语言——Java语言”。所有知识全部串联了起来。所有这些语言的出现都仿佛都有了必然性和追根溯源的历史......
  • devc++配置opengl库
    由于VisualStudio太占内存,所以用老古董devc++配图形学的环境。用到的文件下载链接Step1:建项目首先打开dev点文件--新建--项目--Multimedia--OpenGLc++/c都行(我这里用的c++)名称最好用英文,然后确定,保存的地方也最好没有中文路径Step2:添加库文件找到DEV-C++的安装目录(右键......
  • Rust-AOP编程实战
    文章本天成,妙手偶得之。粹然无疵瑕,岂复须人为?君看古彝器,巧拙两无施。汉最近先秦,固已殊淳漓。胡部何为者,豪竹杂哀丝。后夔不复作,千载谁与期?——《文章》宋·陆游【哲理】文章本是不加人工,天然而成的,是技艺高超的人在偶然间所得到的。其实作者所说的“天成”,并不就是大自然的......