C++Primer Plus笔记——第十七章 输入、输出和文件总结及程序清单

目录

本章小结

程序清单

使用cout进行输出

17.1 write.cpp            17.2 defaults.cpp         17.3 manip.cpp        17.4 width.cpp       17.5 fill.cpp

17.6 precise.cpp        17.7 showpt.cpp          17.8 setf.cpp            17.9 setf2.cpp        17.10 iomanip.cpp 

使用cin进行输入

17.11 check_it.cpp     17.12 cinexcp.cpp       17.13 get_fun.cpp   17.14 peeker.cpp    17.15 truncate.cpp

文件的输入和输出

17.16 fileio.cpp           17.17 count.cpp           17.18 append.cpp   17.19 binary.cpp     17.20 random.cpp

内核格式化

17.21 strout.cpp           17.22 strin.cpp


本章小结

       流是进出程序的字节流。缓冲区足内存中的临时存储区域,是程序与文件或其他I/O设备之间的桥梁。 信息在缓冲区和文件之间传输时,将使用设备(如磁盘驱动器)处理效率最高的尺寸以大块数据的方式进行传输。信息在缓冲区和程序之间传输时,是逐字节传输的,这种方式对于程序中的处理操作更为方便。 C++通过将一个被缓冲流同程序及输入源相连来处理输入。同样,C++也通过将一个被缓冲流同程序及其输出目标相连来处理输出。iostream和fstream文件构成了 I/O类库,该类库定义了大量用于管理流的类。 包含了 iostream文件的C++程序将自动打开8个流,并使用8个对象管理它们。cin对象管理标准输入流, 后者默认与标准输入设备(通常为键盘)相连:cout对象管理标准输出流,后名默认与标准输出设备(通常为M示器)相连;cerr和clog对象管理与标准错误设备(通常为显示器)相连的未被缓冲的流和被缓冲的流。这4个对象有都有用于宽字符的副本,它们是wcin、wcout、wcerr和wclog。

       I/O类库提供了大量有用的方法。istream类定义了多个版本的抽取运算符(>>),用于识别所有基本的 C++类型,并将字符输入转换为这些类型。get( )方法族和getline()方法为单字符输入和字符串输入提供了进一步的支持。同样,ostream类定义了多个版木的插入运算符(<<),用于识别所有的C++基本类型,并将它们转换为相应的字符输出。put()方法对单字符输出提供进一步的支持。wistream和wostrcam类对宽字符提供了类似的支持。

       使用ios_base类方法以及文件iostream和iomanip中定义的控制符(可与插入运算符拼接的函数),可以控制程序如何格式化输出。这些方法和控制符使得能够控制计数系统、字段宽度、小数位数、显示浮点变量时采用的计数系统以及其他元素.

       fstream文件提供了将iostream方法扩展到文件I/O的类定义。ifstream类是从istream类派生而来的。 通过将ifstream对象与文件关联起来,可以使用所有的istream方法来读取文件。同样,通过将ofstream对象与文件关联起来,可以使用ostream方法来写文件:通过将fstream对象与文件关联起来,可以将输入和 输出方法用于文件。

       要将文件与流关联起来,可以在初始化文件流对象时提供文件名,也可以先创建一个文件流对象,然后用open()方法将这个流与文件关联起来。close()方法终止流与文件之间的连接。类构造函数和open() 方法接受可选的第一个参数,该参数提供文件模式。文件模式决定文件是否被读和/或写、打开文件以便写 入时是否截短文件、试图打开不存在的文件时是否会导致错误、是使用二进制模式还是文本模式等。

       文本文件以字符格式存储所有的信息,例如,数字值将被转换为字符表示。常规的插入和抽取运算符以及get()和getline()都支持这种模式。二进制文件使用计算机内部使用的二进制表示来存储信息。与文本文件相比,二进制文件存储数据(尤其是浮点值)更为精确、简洁,但可移植性较差。read()和write()方法都支持二进制输入和输出。

       seekg()和seekp()函数提供对文件的随机存取。这些类方法使得能够将文件指针放置到相对于文件开头、文件尾和当前位置的某个位置。tellg()和tellp()法报抟当前的文件位置。

       sstream头文件定义了 istringstream和ostringstream类,这择类使得能够使用istream和ostream方法来抽取字符串中的信息。并对要放入到字符串中的信息进行格式化。

程序清单

使用cout进行输出

17.1 write.cpp

演示write()函数

// write.cpp -- using cout.write!) 
#include <iostream>
#include <cstring> // or else string.h

int main()
{
	using std::cout;
	using std::endl;
	const char * statel = "Florida";
	const char * state2 = "Kansas";
	const char * state3 = "Euphoria";
	int len = std::strlen(state2);
	cout << "Increasing loop index:\n";
	int i;
	for (i = 1; i <= len; i++)
	{
		cout.write(state2, i);
		cout << endl;
	}
	// concatenate output
	cout << "Decreasing loop index:\n";
	for (i = len; i > 0; i--)
		cout.write(state2, i) << endl;
	// exceed string length
	cout << "Exceeding string length:\n";
	cout.write(state2, len + 5) << endl;
	return 0;
}

17.2 defaults.cpp

演示默认输出

// defaults.cpp -- cout default formats 
#include <iostream>
int main()
{
	using std::cout;
	cout << "12345678901234567890\n";
	char ch = 'K';
	int t = 273;
	cout << ch << "An";
	cout << t << " An";
	cout << -t << "An";

	double fl = 1.200;
	cout << fl << ":\n";
	cout << (fl + 1.0 / 9.0) << "An";

	double f2 = 1.67E2;
	cout << f2 << "An";
	f2 += 1.0 / 9.0;
	cout << f2 << "An";
	cout << (f2 * 1.0e4) << "An";

	double f3 = 2.3e-4;
	cout << f3 << "An";
	cout << f3 / 10 << "An";
	return 0;
}

17.3 manip.cpp

使用控制符

// manip.cpp -- using format manipulators 
#include <iostream> 

int main()
{
	using namespace std;
	cout << "Enter an integer: ";
	int n;
	cin >> n;
	cout << "n n*n\n";
	cout << n << "	" << n * n << " (decimal)\n";
	// set to hex mode 
	cout << hex;
	cout << n << "	";
	cout << n * n << " (hexadecimal)\n";
	// set to octal mode
	cout << oct << n << "	" << n * n << " (octal)\n";
	// alternative way to call a manipulator dec < cout);
	cout << n << "	" << n * n << " (decimal)\n";
	return 0;
}

17.4 width.cpp

演示用于调整字段宽度的width()函数

// width.cpp -- using the width method 
#include <iostream>
int main()
{
	using std::cout;
	int w = cout.width(30);
	cout << "default field width = " << w << ":\n";
	cout.width(5);
	cout << "N" << ":";
	cout.width(8);
	cout << "N * N" << ":\n";

	for (long i = 1; i <= 100; i *= 10)
	{
		cout.width(5);
		cout << i << ":";
		cout.width(8);
		cout << i * i << ":\n";
	}
	return 0;
}

17.5 fill.cpp

演示用于填充字符的fill()函数

// fill.cpp -- changing fill character for fields 
#include <iostream>
int main()
{
	using std::cout;
	cout.fill('*');
	const char * staff[2] = { "Waldo Whipsnade", "Wilmarie Wooper" };
	long bonus[2] = { 900, 1350 };
	for (int i = 0; i < 2; i++)
	{
		cout << staff[i] << ": $";
		cout.width(7);
		cout << bonus[i] << "\n";
	}
	return 0;
}

17.6 precise.cpp

演示用于设置浮点数显示精度的precision()函数

//precise.cpp -- setting the precision
#include <iostream>

int main()
{
	using std::cout;
	float pricel = 20.40;
	float price2 = 1.9 + 8.0 / 9.0;
	cout << "V'Furry Friends\" is S" << pricel << "!\n ";
	cout << "\"Fiery Fiends\" is $" << price2 << "!\n";
	cout.precision(2);
	cout << "\"Furry Friends\" is $" << pricel << "!\n ";
	cout << "\"Fiery Fiends\" is $" << price2 << "!\n";
	return 0;
}

17.7 showpt.cpp

设置小数点的方法

// showpt.cpp -- setting the precision, showing trailing point 
#include <iostream>

int main()
{
	using std::cout;
	using std::ios_base;
	float pricel = 20.40;
	float price2 = 1.9 + 8.0 / 9.0;
	cout.setf(ios_base::showpoint);
	cout << "\"Furry Friends\" is $" << pricel << "!\n";
	cout << "\"Fiery Fiends\" is $" << price2 << "!\n";
	cout.precision(2);
	cout << "\MFurry Friends\" is $" << pricel << "!\n";
	cout << "\"Fiery Fiends\" is $" << price2 << "!\n";

	return 0;
}

17.8 setf.cpp

设置小数点的格式常量

//setf.cpp -- using setf() to control formatting
#include <iostream>

int main()
{
	using namespace std;
	int temperature = 63;
	cout << "Today's water temperature:";
		cout.setf(ios_base::showpos);	// show plus sign
	cout << temperature << endl;
	cout << "For our programming friends, that's\n";
	cout << std::hex << temperature << endl; // use hex
	cout.setf(ios_base::uppercase);	// use uppercase in hex
	cout.setf(ios_base::showbase);	// use OX prefix for hex
	cout << "or\n";
	cout << temperature << endl;
	cout << "How " << true << "! oops -- How ";
	cout.setf(ios_base::boolalpha);
	cout << true << "!\n";
	return 0;
}

17.9 setf2.cpp

使用两个参数设置小数点

// setf2.cpp -- using setf() with 2 arguments to control formatting 
#include <iostream>
#include <cmath>
	int main()
{
	using namespace std;
	// use left justification, show the plus sign, show trailing
	// zeros, with a precision of 3 
	cout.setf(ios_base::left, ios_base::adjustfield);
	cout.setf(ios_base::showpos); 
cout.setf(ios_base::showpoint); 
cout.precision(3);
	// use e-notation and save old format setting
ios_base::fmtflags old = cout.setf(ios_base::scientific, ios_base::floatfield);
cout << "Left Justification:\n";
long n;
for (n = 1; n <= 41; n += 10)
{
	cout.width(4);
	cout << n << "|";
	cout.width(12);
	cout << sqrt(double(n)) << "|\n";
	// change to internal justification
	cout.setf(ios_base::internal, ios_base::adjustfield);
	// restore default floating-point display style 
	cout.setf(old, ios_base::floatfield);
	cout << "Internal Justification:\n"; for (n = 1; n <= 41; n += 10)
	{
		cout.width(4); cout << n << cout.width(12);
		cout << sqrt(double(n)) << "|\n";
	}
	// use right justification, fixed notation
	cout.setf(ios_base::right, ios_base::adjustfield);
	cout.setf(ios_base::fixed, ios_base::floatfield);
	cout << "Right Justification:\n";
	for (n = 1; n <= 41; n += 10)
	{
		cout.width(4);
		cout << n << " |";
		cout.width(12);
		cout << sqrt(double(n)) << "|\n";
	}
	return 0;
}

17.10 iomanip.cpp 

使用头文件iomanip

// iomanip.cpp -- using manipulators from iomanip
// some systems require explicitly linking the math library
#include <iostream>
#include <iomanip>
#include <cmath>
int main()
{
	using namespace std;
	// use new standard manipulators
	cout << fixed << right;
	// use iomanip manipulators
	cout << setw(6) << "N" << setw(14) << "square root" << setw(15) << "fourth root\n";
	double root;
	for (int n = 10; n <= 100; n += 10)
	{
		root * sqrt(double(n));
		cout << setw(6) << setfill('.') << n << setfill(' ')
			<< setw(12) << setprecision(3) << root
			<< setw(14) << setprecision(4) << sqrt(root) << endl;
	}
	return 0;
}

使用cin进行输入

17.11 check_it.cpp

如何检查输入

// check_it.cpp -- checking for valid input 
#include <iostream>
int main()
{
	using namespace std;
	cout << "Enter numbers: ";
	int sum = 0;
	int input;
	while (cin >> input)
	{
		sum += input;
	}
	cout << "Last value entered = " << input << endl;
	cout << "Sum = " << sum << endl;
	return 0;
}

17.12 cinexcp.cpp

捕获异常

// cinexcp.cpp -- having cin throw an exception 
#include <iostream>
#include <exception>
int main()
{
	using namespace std;
	// have failbit cause an exception to be thrown
	cin.exceptions(ios_base::failbit);
	cout << "Enter numbers: ";
	int sum = 0;
	int input;
	try {
		while (cin >> input)
		{
			sum += input;
		}
	}
	catch (ios_base::failure & bf)
	{
		cout << bf.what() << endl;
		cout << "0! the horror!\n";
	}
	cout << "Last value entered = " << input << endl;
	cout << "Sum = " << sum << endl;
	return 0;
}

17.13 get_fun.cpp

使用字符串输入函数

// get_fun.cpp -- using get() and getline()
#include <iostream> 
const int Limit = 255;

int main()
{
	using std::cout;
	using std::cin;
	using std::endl;
	char input[Limit];
	cout << "Enter a string for getlineO processing:\n";
	cin.getline(input, Limit, '#');
	cout << "Here is your input:\n";
	cout << input << "\nDone with phase 1\n";

	char ch;
	cin.get(ch);
	cout << "The next input character is " << ch << endl;
	if (ch != '\n')
		cin.ignore(Limit, '\n');	// discard rest of line

	cout << "Enter a string for get() processing:\n";
	cin.get(input, Limit, '#');
	cout << "Here is your input:\n";
	cout << input << "\nDone with phase 2\n";
	cin.get(ch);
	cout << "The next input character is " << ch << endl;
	return 0;
}

17.14 peeker.cpp

使用其他输入函数

// peeker.cpp -- some istream methods
#include <iostream>

int main()
{
	using std::cout;
	using std::cin;
	using std::endl;
	// read and echo input up to a  # character
	char ch;
	while (cin.get(ch))// terminates on EOF
	{
		if (ch != '#')
			cout << ch;
		else
		{
			cin.putback(ch);	// reinsert character
			break;
		}
	}

	if (!cin.eof())
	{
		cin.get(ch);
		cout << endl << ch << " is next input character.\n";
	}
	else
	{
		cout << "End of file reached.\n";
		std::exit(0);
	}
	while (cin.peek() != '#')	// look ahead
	{
		cin.get(ch);
		cout << ch;
	}
	if (!cin.eof())
	{
		cin.get(ch);
		cout << endl << ch << " is next input character.\n";
	}
	else
		cout << "End of file reached.\n";
	return 0;
}

17.15 truncate.cpp

使用其他输入函数

// truncate.cpp -- using get() co truncate input line, if necessary 
#include <iostream> 
const int SLEN = 10;
inline void eatline() { while (std::cin.get() != '\n') continue; } 
int main()
{
	using std::cin;
	using std::cout;
	using std::endl;
	char name[SLEN];
	char title[SLEN];
	cout << "Enter your name: ";
	cin.get(name, SLEN);
	if (cin.peek() != '\n')
		cout << "Sorry, we only have enough room for " << name << endl;
	eatline();
	cout << "Dear " << name << ", enter your title: \n";
	cin.get(title, SLEN); if (cin.peek() != '\n')
		cout << "We were forced to truncate your title.\n";
	eatline();
	cout << " Name: " << name << "\nTitle: " << title << endl;
	return 0;
}

文件的输入和输出

17.16 fileio.cpp

简单的文件输入输出

//fileio.cpp -- saving to a file
#include <iostream> // not needed for many systems 
#include <fstream>
#include <string>
int main()
{
	using namespace std;
	string filename;
	cout << "Enter name for new file: ";
	cin >> filename;
	// create output stream object for new file and call it fout 
	ofstream fout(filename.c_str());
	fout << "For your eyes only!\n";	// write to file
	cout << "Enter your secret number: ";// write to screen
	float secret; cin >> secret;
	fout << "Your secret number is " << secret << endl;
	fout.close();	// close file
	// create input stream object for new file and call it fin 
	ifstream fin(filename.c_str());
	cout << "Here are the contents of " << filename << ":\n"; char ch;
	while (fin.get(ch))	// read character from file and
		cout << ch;	// write it to screen
	cout << "Done\n";
	fin.close();
	return 0;
}

17.17 count.cpp

命令行处理技术

//count.cpp -- counting characters in alist of files
#include <iostream>
#include <fstream>
#include <cstdlib> // for exit()
int main(int argc, char * argv[])
{
	using namespace std;
	if (argc == 1)	// quit if no arguments
	{
		cerr << "Usage: " << argv[0] << " filenameIsl\n";
		exit(EXIT_FAILURE);
	}
	ifstream fin; // open stream
	long count;
	long total = 0;
	char ch;

	for (int file = 1; file < argc; file++)
	{
		fin.open(argv[file]);	// connect stream to argv[file]
		if (!fin.is_open())
		{
			cerr << "Could not open " << argv[file] << endl;
			fin.clear();
			continue;
		}
		count = 0;
		while (fin.get(ch))
			count++;
		cout << count << " characters in " << argv[file] << endl;
		total += count;
		fin.clear();// needed for some implementations
		fin.close();// disconnect file
	}

	cout << total << " characters in all files\n";
	return 0;
}

17.18 append.cpp

追加文件

//append.cpp -- appending information to a file
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
// (for exit()

const char * file = "guests.txt";

int main()
{
	using namespace std;
	char ch;
	// show initial contents
	ifstream fin;
	fin.open(file);
	if (fin.is_open())
	{
		cout << "Here are the current contents of the " << file << " file : \n";
		while (fin.get(ch))
			cout << ch;
		fin.close();
	}
	// add new names
	ofstream fout(file, ios::out | ios::app);
	if (!fout.is_open())
	{
		cerr << "Can't open " << file << " file for output.\n";
		exit(EXIT_FAILURE);
	}
	
	cout << "Enter guest names (enter a blank line to quit):\n ";
	string name;
	while (getline(cin, name) && name.size() > 0)
	{
		fout << name << endl;
	}
	fout.close();
	// show revised file
	fin.clear(); // not necessary for some compilers
	fin.open(file);
	if (fin.is_open())
	{
		cout << "Here are the new contents of the " << file << " file:\n";
		while (fin.get(ch))
			cout << ch;
		fin.close();
	}
	cout << "Done.\n";
	return 0;
}

17.19 binary.cpp

二进制文件

// binary.cpp -- binary file I/O
#include <iostream> // not required by most systems 
#include <fstream>
#include <iomanip>
#include <cstdlib> // for exit()
inline void eatline()
{
	while (std::cin.get() != '\n') 
		continue;
} 
struct planet
{
	char name[20];	// name of planet
	double population; // its population
	double g;	// its acceleration of gravity
};

const char * file = "planets.dat";
int main()
{
	using namespace std;
	planet pl;
	cout << fixed << right;
	// show initial contents
	ifstream fin;
	fin.open(file, ios_base::in | ios_base::binary);	// binary file
	//NOTE: some systems don't accept the ios_base::binary mode 
	if (fin.is_open())
	{
		cout << "Here are the current contents of the " << file << " file:\n";
		while (fin.read((char *)&pl, sizeof pl))
		{
			cout << setw(20) << pl.name << ": "
				<< setprecision(0) << setw(12) << pl.population
				<< setprecision(2) << setw(6) << pl.g << endl;
		}
		fin.close();
	}
	// add new data
	ofstream fout(file, ios_base::out | ios_base::app | ios_base::binary); //NOTE: some systems don't accept the ios::binary mode 
	if (!fout.is_open())
	{
		cerr << "Can't open " << file << " file for output:\n";
		exit(EXIT_FAILURE);
	}
	cout << "Enter planet name (enter a blank line to quit):\n";
	cin.get(pl.name, 20);
	while (pl.name[0] != '\0')
	{
		eatline();
		cout << "Enter planetary population: ";
		cin >> pl.population;
		cout << "Enter planet's acceleration of gravity: ";
		cin >> pl.g;
		eatline();
		cout.write((char *)&pl, sizeof pl);
		cout << "Enter planet name (enter a blank line to quit):\n";
		cin.get(pl.name, 20);
	}
	fout.close();
	// show revised file
	fin.clear(); // not required for some implementations, but won't hurt 
	fin.open(file, ios_base::in | ios_base::binary);
	if (fin.is_open())
	{
		cout << "Here are the new contents of the " << file << " file:\n";
		while (fin.read((char *)&pl, sizeof pl))
		{
			cout << setw(20) << pl.name << ": "
				<< setprecision(0) << setw(12) << pl.population
				<< setprecision(2) << setw(6) << pl.g << endl;
		}
		fin.close();
	}
	cout << "Done.\n";
	return 0;
}

17.20 random.cpp

随机存取

// random.cpp -- random access to a binary file
#include <iostream> // not required by most systems 
#include <fstream>
#include <iomanip>
#include <cstdlib>	// for exit()
const int LIM = 20;
struct planet
{
	char name[LIM];// name of planet 
	double population;// its population
	double g;// its acceleration of gravity
};
 
const char * file = "planets.dat";	// ASSUMED TO EXIST (binary.cpp example)
inline void eatline() { while (std::cin.get() != '\n') continue; }
int main()
{
	using namespace std;
	planet pl;
	cout << fixed;
	// show initial contents
	fstream finout;	// read and write streams
	finout.open(file, ios_base::in | ios_base::out | ios_base::binary);
	//NOTE: Some Unix systems require omitting - ios::binary 
	int ct = 0;
	if (finout.is_open())
	{
		finout.seekg(0);// go to beginning
		cout << "Here are tRe current contents of the  " << file << " file: \n";
		while (finout.read((char *)&pl, sizeof pl))
		{
			cout << ct++ << ": " << setw(LIM) << pl.name << ": "
				<< setprecision(0) << setw(-12) << pl.population
				<< setprecision(2) << setw(6) << pl.g << endl;
		}
		if (finout.eof())
			finout.clear(); // clear eof flag
		else
		{
			cerr << "Error in reading " << file << ".\n";
			exit(EXIT_FAILURE);
		}
	}
	else
	{
		cerr << file << " could not be opened -- bye.\n";
		exit(EXIT_FAILURE);
	}
	// change a record
	cout << "Enter the record number you wish to change: ";
	long rec;
	cin >> rec;
	eatline();	// get rid of newline
	if (rec < 0 || rec >= ct)
	{
		cerr << "Invalid record number -- bye\n";
		exit(EXIT_FAILURE);
	}
	streampos place = rec * sizeof pl; // convert to streampos type
	finout.seekg(place);	// random access
	if (finout.fail())
	{
		cerr << "Error on attempted seek\n";
		exit(EXIT_FAILURE);
	}

	finout.read((char *)&pl, sizeof pl);
	cout << "Your selection:\n";
	cout << rec << ": " << setw(LIM) << pl.name << ": "
		<< setprecision(0) << setw(12) << pl.population
		<< setprecision(2) << setw(6) << pl.g << endl;
	// clear eof flag
	if (finout.eof())
		finout.clear();
	cout << "Enter planet name: ";
	cin.get(pl.name, LIM);
	eatline();
	cout << "Enter planetary population: ";
	cin >> pl.population;
	cout << "Enter planet's acceleration of gravity: ";
	cin >> pl.g;
	finout.seekp(place);	// go back
	finout.write((char *)&pl, sizeof pl) << flush;
	if (finout.fail())
	{
		cerr << "Error on attempted write\n";
		exit(EXIT_FAILURE);
	}
	// show revised file ct = 0;
	finout.seekg(0);	// go to beginning of file
	cout << "Here are the new contents of the " << file << "file:\n";
	while (finout.read((char *)&pl, sizeof pl))
	{
		cout << ct++ << ": " << setw(LIM) << pl.name << ": "
			<< setprecision(0) << setw(12) << pl.population
			<< setprecision(2) << setw(6) << pl.g << endl;
	}
	finout.close();
	cout << "Done.\n";
	return 0;
}

内核格式化

17.21 strout.cpp

// strout.cpp -- incore formatting (output) 
#include <iostream>
#include <sstream>
#include <string> 
int main()
{
	using namespace std;
	ostringstream outstr; // manages a string
	string hdisk;
	cout << "What's the name of your hard disk? ";
	getline(cin, hdisk);
	int cap;
	cout << "What's its capacity in GB? ";
	cin >> cap;
	// write formatted information to string stream 
	outstr << "The hard disk " << hdisk << " has a capacity of " << cap << " gigabytes.\n";
	string result = outstr.str();	// save result
	cout << result;	// show contents
	return 0;
}

17.22 strin.cpp

// strin.cpp -- formatted reading from a char array 
#include <iostream> 
#include <sstream>
#include <string> 
int main()
{
	using namespace std;
	string lit = "t was a dark and stormy day, and the full moon glowed brilliantly. ";
	istringstream instr(lit); // use buf for input 
	string word;
	while (instr >> word)// read a word a time
		cout << word << endl;
	return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值