宏定义的数据是在预处理发生了替换
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;elsereturn 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.";elsecout << "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:.
操作符(点操作符):
-
用于直接访问结构体或类的成员。
-
当您有一个结构体或类的实例(非指针)时,使用
.
来访问其成员。
->
操作符(箭头操作符):
-
用于通过结构体或类的指针来访问其成员。
-
当您有一个指向结构体或类的指针时,首先需要使用
->
来解引用指针,然后访问其成员。
示例:
总结:
-
使用
.
操作符时,您已经有一个结构体或类的实例。 -
使用
->
操作符时,您有一个指向结构体或类的指针,并且需要通过这个指针来访问其成员。