浮点数的比较

class FloatCmp 
{
    private:
        const double eps = 1e—8;
    public:
        static bool equ(const double a, const double b){
            return fabs(a - b) < eps;
        }
        static bool more(const double a, const double b){
            return a - b > eps;
        }
        static bool less(const double a, const double b){
            return a - b < -eps;
        }
        static bool more_equ(const double a, const double b){
            return a - b > -eps;
        }
        static bool less_equ(const double a, const double b){
            return a - b < eps;
        }
};

 

[语法]文件的创建fopen-fwrite-fclose

(1) fopen: 打开文件
FILE* fopen(const char *filename, const char *mode);
mode: 使用”wb” (w表示write, b表示binary)

c:\abc.txt : 全路径
c:\0\abc.txt

返回值: 文件指针 FILE*
其中,不用关心FILE*的具体类型,只需要知道它是一个指针就行了。

(2) fclose: 关闭文件
int fclose(FILE* stream);

参数: stream就是前面fopen的返回值

示例:
fclose(fp);

 

(3) fwrite: 写入数据
size_t fwrite(const void *buf,
size_t size, size_t count,
FILE *stream);

参数: stream就是前面fopen的返回值
buf, 要写入的数据
size,总是传1
count, 字节数

返回值 :字节数

示例:
char buf[] = “hello”;
fwrite(buf, 1, 5, fp);

[语法]写入数据-数字-字符串-结构体

  • 写入数字

有一个int数组,在存储到文件时,一般有两种方式:
int buf[4] = { 0xA001098, 0xB002 ,0xC003, 0xD004 };

方式1 : 直接按字节写入
fwrite(buf, 1, sizeof(buf), fp);
(对照VC的内存窗口来理解)

方式2 :格式化为字符串写入
for(int i=0; i<4; i++)
{
char text[16];
sprintf(text, “%d,” , buf[i]);
fwrite(text,1,strlen(text), fp);
}

对于浮点数(float,double),也可以使用这两种写法

double a = 3 / 4.0;
fwrite(&a, 1, sizeof(a), fp);


char text[16];
sprintf(text, “%.2lf”, a);
fwrite(text, 1, strlen(text), fp);

比较:后者在保存数据时,丢失了精度,无法还原

  • 写入字符串

字符串的两种存储方式
char buf[16] = “hello”;

方式1:按实际有效长度写入
fwrite(buf, 1, strlen(buf), fp);

方式2:按固定长度写入
fwrite(buf, 1, 16, fp);
(占用了较多的空间)

  • 结构体写入

结构体数据的写入:
struct Student
{
int id; // id
char gender; // 性别
char name[16]; // 年龄
};
Student someone = { 20150101, ‘M’ , “Noname” };

方式一:整体写入
fwrite(&someone, 1, sizeof(someone), fp);
(对照VC的内存窗口来理解)

方式二:将各字段分开写入
fwrite(&someone.id, 1, 4, fp);
fwrite(&someone.gender, 1, 1, fp);
fwrite(&someone.name, 1, 16, fp);

[OOP]STL-string

#include <stdio.h>
#include <string.h>

#include <string>
using namespace std;

// 1号方式
void test(const string& t)
{
}
// 2号方式
void test(string& t)
{
}
// 这种方式避免使用,请参考1号方式
void test(string t)
{
}

int main()
{
// 	string str1 ("LiMing");    // 以一个C风格字符串构造
// 	string str2 = "WangHua";  // 同上一种方式
// 	string str3 ("abcde", 3);    // 参数1是C字符串,参数2参数是长度
// 	string str4;  // 空字符串
// 	string str5 = "";  // 同上,空字符串

    // string str6 = NULL; // 不能初始化为NULL

    // 取得字符串内部的char*
    string text("hello,world!\n");
    const char* p = text.c_str();
    printf("str: %s \n", text.c_str());

    // 
    string t1;
    t1.append("something else");	// 附加一个字符串
    t1.append("abcde", 5);    // 附加一个字符串:拷贝前5个字符
    t1.append("abcde", 1, 3);  // 附加一个字符串:
    // 起点offset=1, 长度3,即拷贝"bcd"
    t1.append(4, 'h'); // 附加2个’h’字符

    // 考虑效率问题
    string t2;
    t2.resize(1024);
    t2.clear();
    t2.append("ab");
    t2.append("cd");

    // 
    string t3 = "hello";
    t3[1] = 'i'; // 推荐使用
    t3.at(1) = 'c'; // 不推荐

    // 字符串的比较
    string t4 = "yes";
    if( t4 == "yes")
    {
        printf("相等\n");
    }

    // 字符串的查找
    string t5 = "LiMing is doing homework";
    int p1 = t5.find('i');   // 返回1
    int p2 = t5.rfind('e');   // 
    // 存在,则返回其位置;否则,返回-1

    // 返回子串
    string t6 ("abcdefg");
    string r1 = t6.substr(4); // 返回"efg"
    string r2 = t6.substr(4,2); // 返回"ef"

    return 0;
}

 

[OOP]STL-list

list: 封装链表相关的功能

http://joshliu357.8910.io/wordpress/wp-content/uploads/2018/08/%E6%8D%95%E8%8E%B7.png

链表不能随机访问,只能按顺序链式访问,所以,只能使用迭代器iterator

list<T>::iterator, list内的迭代器

list比vector用适合插入删除操作

list链表中插入/删除一个节点
遍历list,找到目标位置
调用insert/erase,插入/删除一个节点

vector可有可无,但list不可或缺

vector不常用到,使用普通的数组完全没有问题。
list经常用到,如果没有list,那么每个链表都需要从头写起,非常麻烦。

#include <stdio.h>
#include <string.h>

#include <list>
using namespace std;

int main()
{
    list<int> lst;

    lst.push_back(1);
    lst.push_front(3);
    lst.push_front(2);
    //lst.pop_back();

    for(list<int>::iterator iter = lst.begin();
        iter != lst.end(); iter ++)
    {
        int& value = *iter;
        printf("%d, ", value);
    }

    // 删除值为3的节点
    for(list<int>::iterator iter = lst.begin();
        iter != lst.end(); iter ++)
    {
        int& value = *iter;
        if(value == 3)
        {
            lst.erase(iter);
            break;
        }
    }

    return 0;
}
#include <stdio.h>
#include <string.h>

#include <list>
using namespace std;


class Object
{
public:
    Object()
    {		
    }
    Object(int id, const char* name)
    {
        this->id = id;
        strcpy(this->name, name);
    }
public:
    int id;
    char name[32];
};

int main()
{
    list<Object> lst;
    lst.push_back(Object(1, "shaofa"));
    lst.push_back(Object(2, "xxxx"));
    lst.push_back(Object(3, "yyyy"));


    for(list<Object>::iterator iter = lst.begin();
        iter != lst.end(); iter ++)
    {
        Object& value = *iter;

        printf("%d, %s \n", value.id, value.name);
    }


    return 0;
}

 

[OOP]STL-vector

#include <stdio.h>
#include <string.h>

#include <vector>
using namespace std;

int main()
{
    vector  <int >   arr(16);   // capacity:16
    arr.clear(); // size = 0

    arr.push_back (1) ;   //  capacity:16 , size : 1
    arr.push_back (2) ;   //  capacity:16 , size : 2
    int capacity = arr.capacity();
    int size = arr.size();

    // 迭代器遍历
    vector<int>::iterator iter;
    for(iter = arr.begin();  iter != arr.end(); iter ++)
    {
        int& value = *iter;
        printf("%d, ", value);
    }

    // 
// 	for(int i=0; i<arr.size(); i++)
// 	{
// 		int& value = arr[i];
// 		printf("%d, ", value);
// 	}

    return 0;
}

 

[OOP]类模板

main.c

#include <stdio.h>
#include <string.h>

#include "Array.h"

int main()
{
    Array<int> a; // 长度可变的数组
    a.PushBack(1);
    a.PushBack(2);
    a.PushBack(3);
    a.PushBack(4);
    a.PushBack(5);

    int size = a.Size();

    Array<float> b;
    b.PushBack(2.3f);

    return 0;
}

Aarry.h

#ifndef _ARRAY_H
#define _ARRAY_H

// 用于存放double类型的对象
template <typename _TT>
class Array
{
public:
    Array(int capacity=4)
    {
        m_buffer = new _TT[capacity];
        m_capacity = capacity;
        m_size = 0;
    }

    void PushBack(_TT val)
    {
        if(m_size >= m_capacity)
        {
            Resize();
        }
        m_buffer[m_size] = val;
        m_size ++;
    }
    int Capacity()
    {
        return m_capacity;
    }
    int Size()
    {
        return m_size;
    }

private:
    void Resize()
    {
        // 创建一个更大的缓冲区
        int n = m_capacity + 4;
        _TT* buf = new _TT[n];

        // 拷贝原有的内容
        memcpy(buf, m_buffer, m_capacity * sizeof(_TT) );

        // 删除旧的内容,释放其内存
        delete [] m_buffer;

        // 更新一下成员变量
        m_capacity = n;
        m_buffer = buf;
    }

private:
    _TT* m_buffer;
    int m_capacity; // 容量
    int m_size; // 已经存放的对象的个数
};


#endif

 

[OOP]函数模板

#include <stdio.h>
#include <string.h>

// 定义一个函数模板
template <typename T>
T findmax (T arr[],  int len)
{
    T  val = arr[0];
    for(int i=1; i<len ; i++)
    {
        if(arr[i] > val) val = arr[i];
    }
    return  val;        
}

template <typename _A, typename _B>
void Test(_A obja, _B objb)
{
}

int main()
{
    int  arr[ 4] = { 1, 42,  87, 100 };
    int  result = findmax <int> (arr,  4);

    double abc[3] = {1.0, 2.0, 3.0};
    double r = findmax<double>(abc, 3);

    // Test<int, double> (10, 12.0);
    return 0;
}

 

[OOP]内部类

#include <stdio.h>
#include <string.h>



class AAA
{
private:
    // 定义一个内部类
    class Inner
    {
    public:
        int id;
        char  name[64];

    };

public:
    AAA()
    {
        Inner i;
        i.id = 123;
    }
};

int main()
{
    // 使用该内部类时,类名使用全称 AAA::Inner
// 	AAA::Inner  a;  
// 	a.id = 123;
// 	strcpy(a.name, "AnXin"); 
// 	printf("Name: %s \n", a.name);
    return 0;
}

 

[OOP]重载输入输出操作符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Point
{
public:
    int x, y;
};

// 日志类
class Logger
{
public:
    Logger()
    {
    }

    Logger& operator << (int value)
    {
        printf("%d", value);
        return *this;
    }
    Logger& operator << (double value)
    {
        printf("%f", value);
        return *this;
    }
    Logger& operator << (const char* value)
    {
        printf("%s", value);
        return *this;
    }
    Logger& operator << (const Point& point)
    {
        printf("(%d,%d)", point.x, point.y);
        return *this;
    }

    Logger& Print(const char* value)
    {
        printf("%s", value);
        return *this;
    }
    Logger& Print(const Point& point)
    {
        printf("(%d,%d)", point.x, point.y);
        return *this;
    }
};

int main()
{
    Logger lg;


    Point pt;
    pt.x = 12;
    pt.y = 13;
    //lg << 1 << "," << 11.01 << "hello" << pt << "\n";


    lg.Print("hello").Print("world");
    return 0;
}