C++回顾 day3

发布于:2025-05-01 ⋅ 阅读:(13) ⋅ 点赞:(0)

宏定义的数据是在预处理发生了替换

const类型的数据是在编译阶段发生的替换

命名空间

namespace 空间名{
    int a;
    void func_print()
    {
        printf("func_print");
    }
    struct Stu
    {
        int x;
        char *y;
    };
    //或者其他命名空间
}
Space::x = 20;
cout << Space::x;

using Space::x;using Space::y;
cout << x << y;

using namespace Space;
x = 10;y = 20;
cout << x << y;

{
    using namespace Space;
    x = 10;y = 20;
}
{
    using namespace Other;
    x = 30;y = 60;
}
//相同命名空间会自动合并

string

string s = "qwert";
char chr[50];
strcpy(chr,s.c_str());

string s1 = "XXXX";
s.swap(s1);

s1.find('i',0);
s1..find("in",0);
//找到返回起始地址,找不到返回-1

打开文件

C

fopen 函数

fopen 函数用于打开一个文件,并返回一个指向 FILE 结构的指针,该指针可用于后续的文件读写操作。fopen 的函数原型如下:

FILE *fopen(const char *filename, const char *mode);
  • filename:这是一个字符串,指定了要打开的文件名。可以是相对路径或绝对路径。

  • mode

  • :这是一个字符串,指定了文件的打开模式。常见的模式包括:

    • "r":只读模式,文件必须存在。

    • "w":写入模式,如果文件存在则清空文件内容,如果文件不存在则创建新文件。

    • "a":追加模式,如果文件存在则在文件末尾追加内容,如果文件不存在则创建新文件。

    • "r+":读写模式,文件必须存在。

    • "w+":读写模式,如果文件存在则清空文件内容,如果文件不存在则创建新文件。

    • "a+":读写模式,如果文件存在则在文件末尾追加内容,如果文件不存在则创建新文件。

  • rewind 函数

    rewind 函数用于将文件指针的位置重置到文件的开头。rewind 的函数原型如下:

  • void rewind(FILE *stream);

  • stream:这是一个指向 FILE 结构的指针,通常是由 fopen 函数返回的文件指针。

  • 使用 rewind 函数后,文件指针会回到文件的起始位置,这在需要重新读取文件内容而不关闭文件的情况下非常有用。

    e.g.

#include <stdio.h>

int main() {
    FILE *fp;
    char str[] = "这是一个测试。\n再测试一次。\n";

    // 以写入模式打开文件
    fp = fopen("test.txt", "w");
    if (fp == NULL) {
        perror("无法打开文件");//用来输出错误信息
        return 1;
    }

    // 写入字符串到文件
    fputs(str, fp);

    // 关闭文件
    fclose(fp);

    // 以读取模式打开文件
    fp = fopen("test.txt", "r");
    if (fp == NULL) {
        perror("无法打开文件");
        return 1;
    }

    // 读取并打印文件内容
    char c;
    while ((c = fgetc(fp)) != EOF) {
        putchar(c);
    }

    // 重置文件指针到文件开头
    rewind(fp);

    // 再次读取并打印文件内容
    printf("\n再次读取文件内容:\n");
    while ((c = fgetc(fp)) != EOF) {
        putchar(c);
    }

    // 关闭文件
    fclose(fp);

    return 0;
}

封装特性一:对内数据开放,对外提供接口;数据和行为在一起存放;先有类,再创建对象,最后由对象调用函数

多文件编写更能体现封装

class.h

#include <iostream>
using namespace std;

namespace Class
{
	class time
	{
		public:
			void init();
			void print();
			bool isleapyear();
			int getyear();
		private:
			int year;
			int month;
			int day;
	};
	
}

class.cpp  

#include "class.h"
#include <iostream>
using namespace std;

namespace Class{

	void time::init()
	{
		cin >> year;
		cin >> month;
		cin >> day;
		return;
	}
	void time::print()
	{
		cout << year << '.';
		cout << month << '.';
		cout << day << '.';
		return;
	}
	bool time::isleapyear()
	{
		if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
			return true;
		else
			return false;
	}
	int time::getyear()
	{
		return year;
	}

}

main.cpp

#include <iostream>
#include "class.h"

using namespace std;
using namespace Class;

int main()
{
	time tim;
	tim.init();
	tim.print();
	if(tim.isleapyear())
		cout << "Yes," << tim.getyear() << " is a leap year.";
	else
		cout << "No," << tim.getyear() << " is not a leap year.";
	return 0;
}

封装特性二:有权限控制

构造器(构造函数):

与类名相同;在构造类对象时自动调用,用来初始化;可以有参数,构造器的重载,默认参数;

注意:默认参数只能在声明上

不添加构造器,系统会有默认无参构造器;重载和默认参数不要同时使用,会有ambiguous错误 但一定要包含标配(无参)构造器以实现对象的无参创建

析构器(析构函数)

~与类名相同,无参无返回,用于对象销毁时的内存处理工作

销毁和创建要在同级内对应完成

class Str
{
    public:
        Str()
        {
            str = new char[100];
        }
        ~Str()
        {
            delete []str;
        }
    private:
    	char *str;
};
int main()
{
    Str *eg = new Str;
    strcpy(eg.str,"hello,world");
    delete eg;
}

析构注意事项:

先析构里面的再析构外面的

多个同级对象则按照出入栈的顺序,先创建的后析构,后创建的先析构

自实现string:

mystr.h

using namespace std;
class mystr{
	public:
		//mystr();
		mystr(const char * new_str = nullptr);
		char * c_str();
		~mystr();
	private:
		char * str;
};

mystr.cpp

#include "my_string.h"
#include <string.h>
using namespace std;

/*
mystr::mystr()
{
	str = new char[1];
	*str = '\0';
}
*/

mystr::mystr(const char * new_str)
{
	if(new_str == nullptr)
	{
		str = new char[1];
		*str = '\0';
	}
	else
	{
		int len = strlen(new_str) + 1;
		str = new char[len]; 
		strcpy(str,new_str);
	}
}

char * mystr::c_str()
{
	return str;
}

mystr::~mystr()
{
	delete []str;
} 

main.cpp

#include <iostream> 
#include "my_string.h"
using namespace std;

int main()
{
	mystr str1;
	mystr str2("abcdefg");
	
	cout << str1.c_str() << endl;
	cout << str2.c_str() << endl;
	
	string * p = new string("123456");
	cout << (*p).c_str() << endl;
	delete p;
	
	mystr * q = new mystr("654321");
	cout << (*q).c_str() << endl;
	delete q;
	
	return 0;
}

思考:string的本质实现还是char*,所以string *是一个指向char *的指针, *p和 *q是解引用,使其指向char *,即一个字符数组;

自实现list部分功能

mylist.h

using namespace std;

struct node
{
	int num;
	node *next = nullptr;
};

class mylist
{
	public:
		mylist();
		~mylist();
		void insert(const int &data);
		void traverseList();
	private:
		node * head;
};

mylist.cpp

#include "mylist.h"
#include <iostream>
using namespace std;

mylist::mylist()
{
	head = new node;
	head -> next = nullptr;//(*head).next = nullptr;
}
mylist::~mylist()
{
	node * t = head;
	if(t != nullptr)
	{
		head = head -> next;
		delete t;
		t = head;
	}
	
}
void mylist::insert(const int &data)
{
	node *p = new node;
	p -> num = data; 
	p -> next = head -> next;
	head -> next = p;
}

void mylist::traverseList()
{
	node * q = head -> next;
	while(q != nullptr)
	{
		cout << q -> num << endl;
		q = q -> next;
	}
}

main.cpp

#include "mylist.h"
using namespace std;

int main()
{
	mylist mlis;
	mlis.insert(1);
	mlis.insert(2);
	mlis.insert(3);
	mlis.traverseList();
	return 0;
}

q:->和.有什么区别?

a:. 操作符(点操作符)

  • 用于直接访问结构体或类的成员。

  • 当您有一个结构体或类的实例(非指针)时,使用.来访问其成员。

-> 操作符(箭头操作符)

  • 用于通过结构体或类的指针来访问其成员。

  • 当您有一个指向结构体或类的指针时,首先需要使用->来解引用指针,然后访问其成员。

示例:

总结:

  • 使用.操作符时,您已经有一个结构体或类的实例。

  • 使用->操作符时,您有一个指向结构体或类的指针,并且需要通过这个指针来访问其成员。


网站公告

今日签到

点亮在社区的每一天
去签到