《C++程序设计:原理与实践》Chapter10练习

本文为《C++程序设计:原理与实践》第10章的练习题答案,代码是自己写的,可能会存在不少缺陷,但是基本的功能是可以实现的,仅供参考。


题目描述:

1. 编写一个程序来处理平面中的点。首先定义包含两个表示坐标成员x,y的数据类型Point;

2.提示用户输入7个(x,y)值对。当用户输入数据是,将其保存在一个名为original_points的向量中;

3.打印original_points中的数据查看结果;

4.打开一个ofstream,将每个点输出到名为mydata.txt的文件中;

5.关闭ofstream,然后打开一个ifstream,使其与mydata.txt关联。从mydata.txt中读取数据,保存在一个名为processed_points的新的向量中;

6.比较两个向量,如果发现元素数目或值不一致,打印“Something's wrong!"。

 

代码如下:

1. 定义一个Point数据类型

struct Point{
    int x;
    int y;
};

2.  自定义输入流

istream& operator>>(istream& is, Point& p){
    char ch1;
    cin>> ch1;
    if((ch1!='(') && (ch1!='\n'))    // 允许输入换行
        perror("Error:'('");
    
    char ch2;
    int x, y;
    cin>> x>> ch2>> y;
    if(ch2!=',')
        perror("Error:','");
    char ch3;
    cin>> ch3;
    if(ch3!=')')
        perror("Error:')'");
    p.x = x;
    p.y = y;
    return is;
}

3. 自定义输出流

ostream& operator<<(ostream& os, Point& p){
    return os<< "("<< p.x<< ","<< p.y<< ")"<< endl;
}

4. 写文件

void Write_to_file(vector<Point>& points, string& name){
    ofstream ost{name};
    if(!ost) perror("Can't open file.\n");
    for(int i=0;i<points.size();i++){
        ost<< points[i];
    }
}

这里没有显式地打开或关闭文件,因为这里将其包含在了Write_to_file的ofstream的作用域中,当文件流离开了其作用域,与之关联的文件会被关闭。当文件被关闭时,与之关联的缓冲区会被刷新,即缓冲区中的字符会被写入文件中。

一般来说,最好在程序的一开始位置,在任何计算都尚未开始之前就打开文件。因为如果在完成计算后才发现无法保存结果,将会是对计算资源的巨大浪费。

理想的方式:在创建ostream或istream对象时,隐式打开文件,并依靠流对象的作用域关闭文件。

// 如果使用文件的范围不能简单地包含域任何流对象的作用域中,需要显示使用open()、close()操作
ost.open(filename, iOS_base::out);
// ......
ost.close();

5. 读文件

void Read_from_file(vector<Point>& points, string& name){
    ifstream ist{name};
    if(!ist) perror("Can't open file\n");
    while(!ist.ios_base::eof()){
        Point p;
        char ch1, ch2, ch3;
        int x, y;
        ist>> ch1>> x>> ch2>> y>> ch3;
        // 增加对eof的判断,防止文件最后一行被读2次
        if(ist.ios_base::eof())   
            return;
        if((ch1!='(') && (ch2!=',') && (ch3!=')'))
            return;
        p.x = x;
        p.y = y;
        points.push_back(p);
    }
}

读文件这里遇到了一个问题:使用EOF判断读取文件是否结束时,会造成文件最后一行被读了两遍。

这是因为:当文件刚刚读到文件尾时,eof()不会返回true。只有在文件尾部再次进行一次读操作,eof()才会返回真。

所以在程序中,对eof()判断了两次。

The extraction will only set the EOF bit on the stream if you attempt to extract the end-of-file, not if your extraction just stops at the end-of-file. file.eof() will only tell you if the previous read hit the end-of-file and not if the next one will. After the last line has been extracted, the EOF bit is still not set and the iteration occurs one more time. However, on this last iteration, the extraction fails and line still has the same content as before, i.e. the last line is duplicated.

file.eof()只会告诉我们上一次读取是否命中文件末尾,而不会告诉我们下一次读取是否命中,提取最后一行后,eof()仍未置true,再迭代一次,才会置true。但在最后一次迭代中,提取到文件结束标志符,但行内容不变,因此最后一行被复制。

cite from : https://stackoverflow.com/questions/14615671/whats-the-real-reason-to-not-use-the-eof-bit-as-our-stream-extraction-condition

6. 比较两个向量

bool is_equal(vector<Point>& original, vector<Point>& processed){
    if(original.size() != processed.size()){
        perror("Something's wrong. Size is not equal!");
        return false;
    }
        
    long v_size = original.size();
    for(int i=0;i<v_size;i++){
        if((original[i].x != processed[i].x)
           &&(original[i].y != processed[i].y)){
            perror("Something's wrong");
            return false;
        }
    }
    return true;
}

7. 完整代码

#include <iostream>
#include <vector>
#include <string>
#include <fstream>   // !否则ifstream/ofstream会报错

using namespace std;

struct Point{
    int x;
    int y;
};

istream& operator>>(istream& is, Point& p);
ostream& operator<<(ostream& os, Point& p);
void Write_to_file(vector<Point>& points, string& name);
void Read_from_file(vector<Point>& points, string& name);
bool operator!=(Point& p1, Point& p2);
bool is_equal(vector<Point>& original, vector<Point>& processed);

int main(int argc, const char * argv[]) {  
    // 提示用户输入
    vector<Point> original_points;
    cout<< "Please input 7 set of Point(x,y):\n";
    int num = 0;
    while(num<7){
        Point p;
        cin>> p;
        original_points.push_back(p);
        num++;
    }

    // 打印验证
    cout<< "Print the original_points:\n";
    for(int i=0;i<original_points.size();i++)
        cout<< original_points[i];

    // 写文件
    string filename = "my_data.txt";
    Write_to_file(original_points, filename);
    
    // 读文件
    vector<Point> processed_points;
    Read_from_file(processed_points, filename);
    
    // 验证读入是否正确
    cout<< "Verify reading\n";
    for(int i=0;i<processed_points.size();i++){
        cout<< processed_points[i];
    }
    
    // 比较两个向量是否相等
    if(is_equal(original_points, processed_points))
        cout<< "It's right!\n";
    return 0;
}

istream& operator>>(istream& is, Point& p){
    char ch1;
    cin>> ch1;
    if((ch1!='(') && (ch1!='\n'))
        perror("Error:'('");
    
    char ch2;
    int x, y;
    cin>> x>> ch2>> y;
    if(ch2!=',')
        perror("Error:','");
    char ch3;
    cin>> ch3;
    if(ch3!=')')
        perror("Error:')'");
    p.x = x;
    p.y = y;
    return is;
}

ostream& operator<<(ostream& os, Point& p){
    return os<< "("<< p.x<< ","<< p.y<< ")"<< endl;
}


void Write_to_file(vector<Point>& points, string& name){
    ofstream ost{name};
    if(!ost) perror("Can't open file.\n");
    for(int i=0;i<points.size();i++){
        ost<< points[i];
    }
}

void Read_from_file(vector<Point>& points, string& name){
    ifstream ist{name};
    if(!ist) perror("Can't open file\n");
    while(!ist.ios_base::eof()){
        Point p;
        char ch1, ch2, ch3;
        int x, y;
        ist>> ch1>> x>> ch2>> y>> ch3;
        if(ist.ios_base::eof())
            return;
        if((ch1!='(') && (ch2!=',') && (ch3!=')'))
            return;
        p.x = x;
        p.y = y;
        points.push_back(p);
    }
}

bool is_equal(vector<Point>& original, vector<Point>& processed){
    if(original.size() != processed.size()){
        perror("Something's wrong. Size is not equal!");
        return false;
    }
        
    long v_size = original.size();
    for(int i=0;i<v_size;i++){
        if((original[i].x != processed[i].x)
           &&(original[i].y != processed[i].y)){
            perror("Something's wrong");
            return false;
        }
    }
    return true;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为编写实际的应用程序做好准备:无论你是为了进行软件开发还是进行其他领域的工作。《C++程序设计原理实践(英文版)》假定你的最终目标是学会编写实际有用的程序。以基本概念和基本技术为重点:与传统的C++教材相比,《C++程序设计原理实践(英文版)》对基本概念和基本技术的介绍更为深入。这会为你编写有用、正确.易维护和有效的代码打下坚实的基础。, 用现代C++语言编程:, 《C++程序设计原理实践(英文版)》一方面介绍了通用的程序设计方法(包括面向对象程序设计和泛型程序设计)。另一方面还对软件开发实践使用最广泛的程序设计语言——C++进行了很好的介绍。《C++程序设计原理实践(英文版)》从开篇就开始介绍现代C++程序设计技术,并介绍了大量关于如何使用C++标准库来简化程序设计的内容。, 适用于初学者以及任何希望学习新知识的人:, 《C++程序设计原理实践(英文版)》主要是为那些从未编写过程序的人编写的。而且已经由超过1000名大学一年级新生试用过。不过,对于专业人员和高年级学生来说,通过观察公认的程序设计大师如何处理编程的各种问题。同样也会获得新的领悟和指引。, 提供广阔的视野:, 《C++程序设计原理实践(英文版)》第一部分非常广泛地介绍了基本程序设计技术,包括基本概念、设计和编程技术、语言特性以及标准库。这些内容教你如何编写具有输入、输出、计算以及简单图形显示等功能的程序。《C++程序设计原理实践(英文版)》第二部分则介绍了一些更专门性的内容(如文本处理和测试),并提供了大量的参考资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值