C++输入输出格式文件读写操作

C++ 输入输出格式与文件读写操作(修改版)

这里可能只会讨论到一些基本的文件读写,有兴趣的读者可以自行参考一些资料

环境
这里为了满足比较多小伙伴的需求,我选用的是win10系统
若Mac和Linux下有各别东西不同,我会稍加说明

先来看看于输入输出流相关的类
在这里插入图片描述简单介绍几个类
他们之间的继承派生关系如图所示
1.istream:用于输入的流类,cin就是该类的对象
2.ostream用于输出的流类,cout是它的对象
**fstream中:既能从文件读取数据,又可以向文件写入数据
**
3.iftream用于从文件读取数据
4.oftream用于向文件写入数据
5.iostream 既能输入,又可以输出

其他有兴趣可自行了解sstream可以看我关于
STL:string类的博客
string类
 

标准流对象

  1. 输入流对象: cin 与标准输入设备相连
  2. 输出流对象:cout 与标准输出设备相连
  3. cerr 与标准错误输出设备相连
  4. clog与标准错误输出设备相连

缺省情况下

cerr << "Hello,world" << endl;
clog << "Hello,world" << endl; 

和下面一样

cout << “Hello,world” << endl; 
  1. cin对应于标准输入流,用于从键盘读取数据,也可以被重定向 为从文件中读取数据。
  2. cout对应于标准输出流,用于向屏幕输出数据,也可以被重定 向为向文件写入数据。
  3. cerr对应于标准错误输出流,用于向屏幕输出出错信息。
  4. clog对应于标准错误输出流,用于向屏幕输出出错信息。

cerr和clog的区别在于cerr不使用缓冲区,直接向显示器输出信息;
而输出到clog中的信息先会被存放在缓冲区,缓冲区满或者刷新时才输出到屏幕。

判断输入流结束

int x;
while(cin>>x){
//
}
return 0;

就相当于

istream &operator >>(int & a)
{
//
return *this ;
}

put()函数

cout.put('A').put('\n')// 由此看出,返回对象的引用

1.如果是从文件输入,比如前面有freopen(“some.txt”,”r”,stdin);那么,读到文件尾部,输入流就算结束
后面会介绍freopen函数的

2.如果从键盘输入,则在单独一行输入Ctrl+Z代表输入流结束

iostream类的成员函数

<iostream>

1.getline函数
这里有两种形式
first type

istream & getline(char * buf, int bufSize);

从输入流当中读取bufSize-1个字符进去,或者碰到’\n’为止(哪个先到就算哪个)

second type

istream & getline(char * buf, int bufSize,char delim);

从输入流中读取bufSize-1个字符到缓冲区buf,或读到碰到delim字符为止(哪个先到算哪个)。

需要注意的是:
两个函数都会自动在buf中读入数据的结尾添加\0’。,‘\n’或delim都不会被读入buf,但会被从输入流中取走。

但是,如果输入流中‘\n’或delim之前的字符个数大于等于了bufSize个,就导致读入出错,其结果是:虽然本次读入已经完成,但是之后的读入就都会失败了

这里介绍个小技巧判断输入是否结束

if(!cin.getline(...))

2.其他成员函数
bool eof(); 判断输入流是否结束

while(!(cin>>a>>b).eof())

int peek(); 返回下一个字符,但不从流中去掉.

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string word;
    char c;
    int n;
    cout << "Please enter a word or a number: ";
    c = cin.peek();
    if(isdigit(c))//拿回n
    {
        cin >> n;
        cout << "You have entered a number: " << n << endl;
    }
    else
    {
        cin >> word;
        cout << "You have entered a word: " << word << endl;
    }
    return 0;
}

get()
用法1:读取字符串

    #include <iostream>
    using namespace std;
     main ()
     {
     char ch,t;
     ch=cin.get();  //或者cin.get(ch);
     cin>>t;//get()读取完后会往后移,而peek()不会
     cout<<ch<<endl;
     cout<<t<<endl;
     }

1 2->1 2

用法2:读取字符串

    #include <iostream>
    using namespace std;
    main ()
    {
    char a[20];
    cin.get(a,20);
    cout<<a<<endl;
    }

istream & putback(char c); 将字符ch放回输入流

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cctype>
#include <algorithm>
using namespace std;
int main()
{
    char c;
    int n;
    char  str[256];
    cout << "Enter a number or a word: ";
    c = cin.get();
    if ( (c >= '0') && (c <= '9') )
    {
        cout << c << " ---  the middle output" << endl;
        cin.putback (c);//放回去不用重新从键盘当中读入了
        cin>> n;
        cout<< "You have entered number " << n << endl;
    }
    else
    {
        cout << c << " ---  the middle output" << endl;
        cin.putback (c);
        cin>> str;
        cout<< " You have entered word " << str << endl;
    }
    return 0;
}

Enter a number or a word:
input:
5
output:
5 — the middle output
You have entered number 5

istream & ignore( int nCount = 1, int delim = EOF );
从流中删掉最多nCount个字符,遇到EOF时结束。
ignore()

  if(cin.fail())
        {
        cout << "Invalid" <<  endl;
        cin.clear();//fail后就无法继续读入了,直到看见clear()
        cin.ignore(80,'\n'); //忽略这一行后面的数据后在在下面的语句当中读入,用sync()清空也行
	    }

others:

    int p;//有效位数
    double v;//值
    cin >> p >> v;
    cout.unsetf(ios::fixed);
    cout << setprecision(p) << showpoint << v << endl;//保留有效位数(showpoint还可以完成补零)

在这里插入图片描述

关于函数这一部分,我的建议是不用背,不会或者忘了查就行😂

关于函数这一个部分可以看
C++几个重要的文件读写函数

代码演示

#include<iostream>
using namespace std;

int main()
{
    int x;
    char buf[100];
    cin>>x; 12+空格
    cin.getline(buf,90);//abcd
    cout<<buf<<endl;
    return 0;
}

看完这个程序你可以停一停,想一想它输出的会是什么东西呢

 
下面公布答案
在这里插入图片描述
如果输入的是 12+enter呢

答案是:无输出!!!因为一开始就把\n读了进来

File Processing

输出/入重定向

这里为了节省空间,主要以代码演示为主,解释在代码当中

win10系统下演示

#include <iostream>
using namespace std;
int main() {
	int x,y;
	cin >> x >> y;
	freopen("test.txt","w",stdout); //将标准输出重定向到 test.txt文件
	if( y == 0 ) //除数为0则在终端屏幕上输出错误信息,txt文件里面没有
		cerr << "error." << endl;
	else 
		cout << x /y ; //输出结果到test.txt
	return 0;
}

 

#include <iostream >
using namespace std;
int main() {
    double f;
    int n;
    freopen("test.txt","r",stdin); //cin被改为从test.txt中读取数据
    cin >> f >> n;
    cout << f << "," <<n << endl;
    return 0;
}

读取txt的数据,输出在屏幕上
输出会以,号分隔

 

流操纵运算子

• 整数流的基数:流操纵算子dec,oct,hex,setbase(10进制,8,16,2)
• 浮点数的精度(precision,setprecision)
• 设置域宽(setw,width)
• 用户自定义的流操纵算子
使用流操纵算子需要 #include <iomanip>

这里的话Jalor写了一个很详细的讲解,大家可以去看看C++进制转换

这部分的内容可能都比较熟悉了,这里我就一笔带过吧

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double x = 1234567.89;
cout << setiosflags(ios::fixed) << 
setprecision(6) << x << endl << 
resetiosflags(ios::fixed) << x ;//取消以小数点位置固定的方式输出
}
//output:输出:
//1234567.890000
//1.23457e+006

Practice:
输入

输入共5行
第一行三个整数,表示一个日期的年,月,日(年份在1900到2100之间)
第二行一个整数h,表示需要输出一个菱形的高度(保证是奇数)
高度为5的菱形的样例如下

Copy

(请不要使用二重循环进行打印,注意后面没有空格)
第三行输入一个整数和一个实数,表示需要输出的实数的有效数字位数和实数的值
第四行两个实数,使用科学计数法表示,E使用大写,如1.35E+2
第五行输入一个正整数,判断该整数是否为质数
输出

第一行输出一个日期,格式为XXXX-XX-XX,如2000-01-01
接下来的h行,输出一个指定高度的菱形,注意后面没有空格
接下来的一行,输出一个实数,表示按指定有效数字位数表示的实数(不需要科学记数法)
接下来一行输出一个实数,用科学记数法表示,E大写,表示输入的两个实数的和,保留6位有效数字
接下来的一行输出一个字符串"true"或"false"表示输入的数是否为质数(使用函数来判断质数)
输入样例

2000 1 1
5
5 1.5
1.5E+02 1.5E+03
11

Copy
输出样例

2000-01-01
*

1.5000
1.65000E+03
true

#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cmath>
#include <sstream>
using namespace std;

bool isPrime(int n)
{
	if (n == 1)
		return false;
	if (n == 2)
		return true;
	if (n % 2 == 0 && n != 2)
		return false;
	int limit = sqrt(n);
	for (int i = 3; i <= limit; i += 2)
	{
		if (n % i == 0)
			return false;
	}
	return true;
}
int main()
{
	string inf;
	getline(cin, inf);
	istringstream is(inf);
	int y;
	string mon, date;
	is >> y >> mon >> date;

	if (mon.size() == 1)
		mon = "0" + mon;
	if (date.size() == 1)
		date = "0" + date;
	ostringstream os;
	os << y << "-" << mon << "-" << date << endl;
	cout << os.str() ;
	int h;
	cin >> h;
	for (int i = h / 2; i >= -h / 2; --i)
	{
		if (abs(i) == h / 2)
			cout << setw(h / 2 + 1) << "*" << endl;
		else
		{
			cout << setw(abs(i)+1) << "*" << setw(h-2*abs(i)-1) << "*" << endl;
		}

	}


	int a; double b;
	cin >> a >> b;
	cout.unsetf(ios::fixed);
	cout << setprecision(a) <<showpoint<< b << endl;

	double c, d;
	cin >> uppercase >> scientific >> c >> d;
	cout << resetiosflags(ios::fixed) << scientific << setprecision(5) << uppercase << c + d << endl;
	int t;
	cin >> t;
	if (isPrime(t)) cout << "true" << endl;
	else cout << "false" << endl;
	return 0;
}

Practice:
输入

输入数据包含若干行
每行会输入4个数据,表示两个点(向量)的坐标:x1,y1,x2,y2x_1,y_1,x_2,y_2x1​,y1​,x2​,y2​
如果输入有效,则4个坐标值应当全为整数,而且范围在[-1000,1000]内
请使用cin直接对Point对象输入
输出

输出数据包含若干行,对应每行输入
如果输入对应行出现了无效数据,则输出"Invaild input."(不带引号)
如果输入有效,则输出一个(a,b)的格式,表示两个向量相加后的结果,使用cout直接输出对象
输入样例

1 2 3 4
1 2 a b
0 0 0 1
a b c d

Copy
输出样例

(4,6)
Invaild input.
(0,1)
Invaild input.


#include <iostream>
#include <iomanip>
using namespace std;

class Point
{
	int x, y;
public:
	Point()
	{

	}
	Point(int xx, int yy) :x(xx), y(yy)
	{

	}
	friend istream& operator>>(istream& is, Point& n);
	Point operator+(Point& n);
	friend ostream& operator<<(ostream& os, const Point& n);
};

Point Point::operator+(Point& n)
{
	return Point(n.x + x, n.y + y);
}

istream& operator>>(istream& is, Point& n)
{
	is >> n.x >> n.y;
	if(!cin.fail())
    {
        if (n.x < -1000 || n.x>1000 || n.y < -1000 || n.y>1000)
            is.setstate(ios::failbit);
    }
	return is;
}

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



int main()
{
	Point a, b;

	while (!(cin>>a>>b).eof())
	{

	        if(cin.fail())
        {
            cout << "Invaild input." <<  endl;
        cin.clear();
        cin.ignore(80,'\n');
	    }
        else
	     	cout<<a+b;
	}

	return 0;
}

设置域宽(setw,width)
两者功能相同,一个是成员函数,另一个是流操作算子,调用方式不同:

cin >> setw(4); 或者 cin.width(5);
cout << setw(4); 或者 cout.width(5);

example:

#include <iostream >
using namespace std;
int main() {
  int w = 4;
    char string[10];
    cin.width(5);
    while(cin >> string){
        cout.width(w++);
        cout << string << endl;
        cin.width(5);
    }
    return 0;
}

输入:
1234567890
输出:
1234
5678
90
注意的是:宽度设置有效性是一次性的,在每次读入和输出之前都要设置宽度

那么这一个部分最后就来一个代码示例吧


 #include <iostream>
#include <iomanip>
using namespace std;
int main() {
    int n = 141;
//1) 分别以十六进制、十进制、八进制先后输出 n
    cout << "1) " << hex << n << " " << dec << n << " " << oct << n << endl;
    double x = 1234567.89,y = 12.34567;
//2) 保留5位有效数字
    cout << "2) " << setprecision(5) << x << " " << y << " " << endl;
//3) 保留小数点后面5位
    cout << "3) " << fixed << setprecision(5) << x << " " << y << endl ;
//4) 科学计数法输出,且保留小数点后面5位
    cout << "4) " << scientific << setprecision(5) <<x << " " << y << endl ;
//5) 非负数要显示正号,输出宽度为12字符,宽度不足则用'*'填补
    cout << "5) " << showpos << fixed << setw(12) << setfill('*') << 12.1 << endl;
//6) 非负数不显示正号,输出宽度为12字符,宽度不足则右边用填充字符填充
    cout << "6) " << noshowpos << setw(12) << left << 12.1 << endl;
//7) 输出宽度为12字符,宽度不足则左边用填充字符填充
    cout << "7) " << setw(12) << right << 12.1 << endl;
//8) 宽度不足时,负号和数值分列左右,中间用填充字符填充
    cout << "8) " << setw(12) << internal << -12.1 << endl;
    cout << "9) " << 12.1 << endl;
return 0;
}

在这里插入图片描述

用户自定义的操纵算子

ostream &tab(ostream &output){
return output << '\t';
}
cout << “aa” << tab << “bb” << endl;

输出:aa bb

很明显,我们对<<进行了重载

形如

ostream & operator<<( ostream & ( * p ) ( ostream & ) ) ;

该函数内部会调用p所指向的函数,*且以 this 作为参数

但是我觉得这个可能有点点多余了

创建文件

头文件#include <fstream>

回忆一下开头所讲的

ofstream         //文件写操作 内存写入存储设备 
ifstream         //文件读操作,存储设备读区到内存中
fstream          //读写操作,对打开的文件可进行读写操作 
ofstream outFile(“clients.dat”, ios::out|ios::binary); //创建文件

这里详细说明一下子

  1. – clients.dat 要创建的文件的名字
  2. – ios::out 文件打开方式
    • ios:out 输出到文件, 删除原有内容
    •ios::app 输出到文件, 保留原有内容,总是在尾部添加
  3. – ios::binary 以二进制文件格式打开文件
  4. 具体如下
ios::in为输入(读)而打开文件,文件不存在就报错
ios::out为输入(读)而打开文件,文件不存在就新建
ios::app所有输出附加在文件末尾,文件不存在就新建
ios::binary二进制方式
ios::trunc如果文件已存在则先删除该文件(单独使用时候与out一样)
ios::ate打开存在文件,通过读写指针放在尾部。不存在就报错

ate只适用于ifstream对象
trunc只适用于ofstream对象

5.这些方式是能够进行组合使用的,以“或”运算(“|”)的方式:例如

直接创建打开

ofstream outFile("Gary.dat",ios::out);

Linux系统下代码演示

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

int main()
{
    ofstream outFile("Gary.dat",ios::out);
    if(!outFile)
    {
        cerr<<"File can not be opened!"<<endl;
    }
        char inf[30];
        while(cin>>inf)
            outFile<<inf<<endl;
    return 0;
}

在这里插入图片描述
ctrl+d结束输入(Linux下)
在这里插入图片描述

也可以先创建ofstream对象,再用 open函数打开

ofstream fout;
fout.open("test.out",ios::out|ios::binary);

判断打开是否成功:

if!fout){ 
cout << “File open error!<<endl; }

orfout.is_open()//打开成功返回1,失败0

open函数的原型

public member function
 
void open ( const char * filename,
            ios_base::openmode mode = ios_base::in | ios_base::out );
 
void open(const wchar_t *_Filename,
        ios_base::openmode mode= ios_base::in | ios_base::out,
        int prot = ios_base::_Openprot)

参数: filename 操作文件名 mode 打开文件的方式 prot 打开文件的属性(这个几乎不会用到)

这里讲一下关于路径的问题

绝对路径: “c:\tmp\mydir\some.txt” 由头写到尾

相对路径:
“\tmp\mydir\some.txt”
当前盘符的根目录下的tmp\dir\some.txt
“tmp\mydir\some.txt”
当前文件夹的tmp子文件夹里面的……
“…\tmp\mydir\some.txt”
当前文件夹的父文件夹下面的tmp子文件夹里面的……
“…\…\tmp\mydir\some.txt”
当前文件夹的父文件夹的父文件夹下面的tmp子文件夹里面的……

 

文件的读写指针

这里为了节省空间,主要为代码演示

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
ofstream fout("a1.out",ios::app); //以添加方式打开
long location = fout.tellp(); //取得写指针的位置
location = 10;
fout.seekp(location); // 将写指针移动到第10个字节处
fout.seekp(location,ios::beg); //从头数location
fout.seekp(location,ios::cur); //从当前位置数location
fout.seekp(location,ios::end); //从尾部数location
//location 可以为负值
ifstream fin("a1.in",ios::ate); 
//打开文件,定位文件指针到文件尾
long location = fin.tellg(); //取得读指针的位置
location = 10L;
fin.seekg(location); // 将读指针移动到第10个字节处
fin.seekg(location,ios::beg); //从头数location
fin.seekg(location,ios::cur); //从当前位置数location
fin.seekg(location,ios::end); //从尾部数location
return 0;
}
 inFile.clear(); / / reset eof  for next input
 inFile. seekg(0); / / reposition to beginning of file

**关于这一部分更加详细的内容,可以移步到C++文件读写**看后面部分

关闭文件

成员函数close(),它负责将缓存中的数据排放出来并关闭文件。这个函数一旦被调用,原先的流对象就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程所访问了。为防止流对象被销毁时还联系着打开的文件,析构函数将会自动调用关闭函数close。

显示关闭文件

ifstream fin(“test.dat”,ios::in);
fin.close();
ofstream fout(“test.dat”,ios::out);
fout.close();

字符串文件的读写

example:写一个程序,将文件 in.txt 里面的整数排序后,输出到out.txt

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
int main() { 
    vector<int> v;
    ifstream srcFile("in.txt",ios::in);
    ofstream destFile("out.txt",ios::out);
    int x;
    while( srcFile >> x )
    	v.push_back(x);
    sort(v.begin(),v.end());
    for( int i = 0;i < v.size();i ++ )
        destFile << v[i] << " ";
    destFile.close();
    srcFile.close(); 
    return 0;
}

有兴趣的话可以浏览这一篇小博客和它的续集C++文件读写操作(一)将字母表写入TXT文本文件

二进制文件的读写

二进制写文件:
ofstream 和 fstream的成员函数:

istream& write (const char* s, long n);

将内存地址s处的n个字节内容,写入到文件中写指针指向的位置,然后将文件写指针向后移动n字节(以ios::out方式打开文件时,文件写指针开始指向文件开头, 以ios::app方式打开文件时,文件写指针开始指向文件尾部 )

先来说一下二进制文件和文本文件的区别

Linux,Unix下的换行符号:‘\n’ (ASCII码: 0x0a)
Windows 下的换行符号:‘\r\n’ (ASCII码: 0x0d0a) endl 就是 ‘\n’
Mac 下的换行符号: ‘\r’ (ASCII码:0x0d)
导致 Linux, Mac 文本文件在Windows 记事本中打开时不换行
导致的后果是:
Unix/Linux下打开文件,用不用 ios::binary 没区别
Windows下打开文件,如果不用 ios::binary,则:
读取文件时,所有的 ‘\r\n’会被当做一个字符’\n’处理,即少读了一个字符’\r’。
写入文件时,写入单独的’\n’时,系统自动在前面加一个’\r’,即多写了一个’\r’

在文件中写入和读取一个整数

#include <iostream>
#include <fstream>
using namespace std;
int main() { 
	ofstream fout("some.dat", ios::out | ios::binary);
	int x=120;
	fout.write( (const char *)(&x), sizeof(int) );//write函数,地址写入缓冲区
	fout.close();
	ifstream fin("some.dat",ios::in | ios::binary);
	int y;
	fin.read((char * ) & y,sizeof(int));//read函数,一直读到结尾
	fin.close();//一定要关闭文件
	cout << y <<endl;
	return 0;
}

二进制文件读写
从键盘输入几个学生的姓名的成绩,并以二进制文件形式保存

#include <iostream>
#include <fstream>
using namespace std;
struct Student {
	char name[20];
	int score;
};
int main() {
	Student s;
	ofstream OutFile( "c:\\tmp\\students.dat",ios::out|ios::binary);
	while( cin >> s.name >> s.score ) 
	OutFile.write( (char * ) & s, sizeof( s) );
	OutFile.close();
return 0;
}

输入:
Tom 60
Jack 80
Jane 40
^Z+回车
则形成的 students.dat 为 72字节,用 记事本打开,呈现:
Tom 烫烫烫烫烫烫烫烫< Jack 烫烫烫烫烫烫烫蘌 Jane 烫烫烫烫烫烫烫?

二进制文件读写

将 students.dat 文件的内容读出并显示

#include <iostream>
#include <fstream>
using namespace std;
struct Student {
char name[20];
int score;
};
int main() {
Student s;
ifstream inFile("students.dat",ios::in | ios::binary );
if(!inFile) {
	cout << "error" <<endl;
	return 0;
}
while( inFile.read( (char* ) & s, sizeof(s) ) ) {
	int readedBytes = inFile.gcount(); //看刚才读了多少字节
	cout << s.name << " " << s.score << endl; }
	inFile.close();
return 0; 
}

输出:
Tom 60
Jack 80
Jane 40

二进制文件读写
将 students.dat 文件的Jane的名字改成Mike

#include <iostream>
#include <fstream>
using namespace std;
struct Student {
char name[20];
int score;
};
int main()
{
	Student s;
	fstream iofile( "c:\\tmp\\students.dat",ios::in|ios::out|ios::binary);
if( !iofile) {
	cout << "error" ;
	return 0;
	}
	iofile.seekp( 2 * sizeof(s),ios::beg); //定位写指针到第三个记录
	iofile.write("Mike",strlen("Mike")+1);
	iofile.seekg(0,ios::beg); //定位读指针到开头
while( iofile.read( (char* ) & s, sizeof(s)) ) 
	cout << s.name << " " << s.score << endl;
	iofile.close();
return 0;
}

文件拷贝程序mycopy 示例

**/用法示例:mycopy src.dat dest.dat 即将 src.dat 拷贝到 dest.dat 如果 dest.dat 原来就有,则原来的文件会被覆盖 /

#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char * argv[])
{
	if( argc != 3 ) {
	cout << "File name missing!" << endl;
	return 0;
}
ifstream inFile(argv[1],ios::binary|ios::in); //打开文件用于读
	if( ! inFile ) {
	cout << "Source file open error." << endl;
	return 0;
	}
ofstream outFile(argv[2],ios::binary|ios::out); //打开文件用于写
	if( !outFile) {
	cout << "New file open error." << endl;
	inFile.close(); //打开的文件一定要关闭
return 0;
}
char c;
while( inFile.get(c)) //每次读取一个字符
	outFile.put(c); //每次写入一个字符
outFile.close(); 
inFile.close();
return 0;
}

看完这个之后,有兴趣的小伙伴可以再来看看C++文件读写

学会程序和算法,走遍天下都不怕

在这里插入图片描述
武汉黄鹤楼

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值