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