C++ Primer Plus(第六版)第12章 类和动态内存分配

严重性代码说明项目文件行禁止显示状态
错误    C4996    'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.   

 

error解决:

在strngbad.cpp头文件处加上:

#pragma warning(disable:4996)

 strngbad.h

// strngbad.h -- flawed string class definition
#include <iostream>
#ifndef STRNGBAD_H_
#define STRNGBAD_H_
class StringBad
{
private:
	char * str;                // pointer to string
	int len;                   // length of string
	static int num_strings;    // number of objects
public:
	StringBad(const char * s); // constructor
	StringBad();               // default constructor
	~StringBad();              // destructor
// friend function
	friend std::ostream & operator<<(std::ostream & os,
		const StringBad & st);
};
#endif

strngbad.cpp 

// strngbad.cpp -- StringBad class methods
#include <cstring>                    // string.h for some
#include "strngbad.h"
#pragma warning(disable:4996)
using std::cout;

// initializing static class member
int StringBad::num_strings = 0;

// class methods

// construct StringBad from C string
StringBad::StringBad(const char * s)
{
	len = std::strlen(s);             // set size
	str = new char[len + 1];          // allot storage
	std::strcpy(str, s);              // initialize pointer
	num_strings++;                    // set object count
	cout << num_strings << ": \"" << str
		<< "\" object created\n";    // For Your Information
}

StringBad::StringBad()                // default constructor
{
	len = 4;
	str = new char[4];
	std::strcpy(str, "C++");          // default string
	num_strings++;
	cout << num_strings << ": \"" << str
		<< "\" default object created\n";  // FYI
}

StringBad::~StringBad()               // necessary destructor
{
	cout << "\"" << str << "\" object deleted, ";    // FYI
	--num_strings;                    // required
	cout << num_strings << " left\n"; // FYI
	delete[] str;                    // required
}

std::ostream & operator<<(std::ostream & os, const StringBad & st)
{
	os << st.str;
	return os;
}

vegnews.cpp 

// vegnews.cpp -- using new and delete with classes
// compile with strngbad.cpp
#include <iostream>
using std::cout;
#include "strngbad.h"

void callme1(StringBad &);  // pass by reference
void callme2(StringBad);    // pass by value

int main()
{
	using std::endl;
	{
		cout << "Starting an inner block.\n";
		StringBad headline1("Celery Stalks at Midnight");
		StringBad headline2("Lettuce Prey");
		StringBad sports("Spinach Leaves Bowl for Dollars");
		cout << "headline1: " << headline1 << endl;
		cout << "headline2: " << headline2 << endl;
		cout << "sports: " << sports << endl;
		callme1(headline1);
		cout << "headline1: " << headline1 << endl;
		callme2(headline2);
		cout << "headline2: " << headline2 << endl;
		cout << "Initialize one object to another:\n";
		StringBad sailor = sports;
		cout << "sailor: " << sailor << endl;
		cout << "Assign one object to another:\n";
		StringBad knot;
		knot = headline1;
		cout << "knot: " << knot << endl;
		cout << "Exiting the block.\n";
	}
	cout << "End of main()\n";
	// std::cin.get();
	return 0;
}

void callme1(StringBad & rsb)
{
	cout << "String passed by reference:\n";
	cout << "    \"" << rsb << "\"\n";
}

void callme2(StringBad sb)
{
	cout << "String passed by value:\n";
	cout << "    \"" << sb << "\"\n";
}

执行结果:(有乱码)

Starting an inner block.
1: "Celery Stalks at Midnight" object created
2: "Lettuce Prey" object created
3: "Spinach Leaves Bowl for Dollars" object created
headline1: Celery Stalks at Midnight
headline2: Lettuce Prey
sports: Spinach Leaves Bowl for Dollars
String passed by reference:
    "Celery Stalks at Midnight"
headline1: Celery Stalks at Midnight
String passed by value:
    "Lettuce Prey"
"Lettuce Prey" object deleted, 2 left
headline2: 葺葺葺葺葺葺葺葺蔟
Initialize one object to another:
sailor: Spinach Leaves Bowl for Dollars
Assign one object to another:
3: "C++" default object created
knot: Celery Stalks at Midnight
Exiting the block.
"Celery Stalks at Midnight" object deleted, 2 left
"Spinach Leaves Bowl for Dollars" object deleted, 1 left
"葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺" object deleted, 0 left

string1.h 

// string1.h -- fixed and augmented string class definition

#ifndef STRING1_H_
#define STRING1_H_
#include <iostream>
using std::ostream;
using std::istream;

class String
{
private:
	char * str;             // pointer to string
	int len;                // length of string
	static int num_strings; // number of objects
	static const int CINLIM = 80;  // cin input limit
public:
	// constructors and other methods
	String(const char * s); // constructor
	String();               // default constructor
	String(const String &); // copy constructor
	~String();              // destructor
	int length() const { return len; }
	// overloaded operator methods    
	String & operator=(const String &);
	String & operator=(const char *);
	char & operator[](int i);
	const char & operator[](int i) const;
	// overloaded operator friends
	friend bool operator<(const String &st, const String &st2);
	friend bool operator>(const String &st1, const String &st2);
	friend bool operator==(const String &st, const String &st2);
	friend ostream & operator<<(ostream & os, const String & st);
	friend istream & operator>>(istream & is, String & st);
	// static function
	static int HowMany();
};
#endif

string1.cpp 

// string1.cpp -- String class methods
#include <cstring>                 // string.h for some
#include "string1.h"               // includes <iostream>
#pragma warning(disable:4996)
using std::cin;
using std::cout;

// initializing static class member

int String::num_strings = 0;

// static method
int String::HowMany()
{
	return num_strings;
}

// class methods
String::String(const char * s)     // construct String from C string
{
	len = std::strlen(s);          // set size
	str = new char[len + 1];       // allot storage
	std::strcpy(str, s);           // initialize pointer
	num_strings++;                 // set object count
}

String::String()                   // default constructor
{
	len = 4;
	str = new char[1];
	str[0] = '\0';                 // default string
	num_strings++;
}

String::String(const String & st)
{
	num_strings++;             // handle static member update
	len = st.len;              // same length
	str = new char[len + 1];  // allot space
	std::strcpy(str, st.str);  // copy string to new location
}

String::~String()                     // necessary destructor
{
	--num_strings;                    // required
	delete[] str;                    // required
}

// overloaded operator methods    

	// assign a String to a String
String & String::operator=(const String & st)
{
	if (this == &st)
		return *this;
	delete[] str;
	len = st.len;
	str = new char[len + 1];
	std::strcpy(str, st.str);
	return *this;
}

// assign a C string to a String
String & String::operator=(const char * s)
{
	delete[] str;
	len = std::strlen(s);
	str = new char[len + 1];
	std::strcpy(str, s);
	return *this;
}

// read-write char access for non-const String
char & String::operator[](int i)
{
	return str[i];
}

// read-only char access for const String
const char & String::operator[](int i) const
{
	return str[i];
}

// overloaded operator friends

bool operator<(const String &st1, const String &st2)
{
	return (std::strcmp(st1.str, st2.str) < 0);
}

bool operator>(const String &st1, const String &st2)
{
	return st2 < st1;
}

bool operator==(const String &st1, const String &st2)
{
	return (std::strcmp(st1.str, st2.str) == 0);
}

// simple String output
ostream & operator<<(ostream & os, const String & st)
{
	os << st.str;
	return os;
}

// quick and dirty String input
istream & operator>>(istream & is, String & st)
{
	char temp[String::CINLIM];
	is.get(temp, String::CINLIM);
	if (is)
		st = temp;
	while (is && is.get() != '\n')
		continue;
	return is;
}

 sayings1.cpp 

// sayings1.cpp -- using expanded String class
// compile with string1.cpp
#include <iostream>
#include "string1.h" 
const int ArSize = 10;
const int MaxLen = 81;
int main()
{
	using std::cout;
	using std::cin;
	using std::endl;
	String name;
	cout << "Hi, what's your name?\n>> ";
	cin >> name;

	cout << name << ", please enter up to " << ArSize
		<< " short sayings <empty line to quit>:\n";
	String sayings[ArSize];     // array of objects
	char temp[MaxLen];          // temporary string storage
	int i;
	for (i = 0; i < ArSize; i++)
	{
		cout << i + 1 << ": ";
		cin.get(temp, MaxLen);
		while (cin && cin.get() != '\n')
			continue;
		if (!cin || temp[0] == '\0')    // empty line?
			break;              // i not incremented
		else
			sayings[i] = temp;  // overloaded assignment
	}
	int total = i;              // total # of lines read

	if (total > 0)
	{
		cout << "Here are your sayings:\n";
		for (i = 0; i < total; i++)
			cout << sayings[i][0] << ": " << sayings[i] << endl;

		int shortest = 0;
		int first = 0;
		for (i = 1; i < total; i++)
		{
			if (sayings[i].length() < sayings[shortest].length())
				shortest = i;
			if (sayings[i] < sayings[first])
				first = i;
		}
		cout << "Shortest saying:\n" << sayings[shortest] << endl;;
		cout << "First alphabetically:\n" << sayings[first] << endl;
		cout << "This program used " << String::HowMany()
			<< " String objects. Bye.\n";
	}
	else
		cout << "No input! Bye.\n";
	// keep window open 
	/*    if (!cin)
			cin.clear();
		while (cin.get() != '\n')
			continue; */
	return 0;
}

执行结果:

Hi, what's your name?
>> Misty Gutz
Misty Gutz, please enter up to 10 short sayings <empty line to quit>:
1: a fool and his money are soon parted
2: penny wise,pound foolish
3: the love of money is the root of much evil
4: out of sight,out of mind
5: absence makes the heart grow fonder
6: absinthe makes the hart grow fonder
7:
Here are your sayings:
a: a fool and his money are soon parted
p: penny wise,pound foolish
t: the love of money is the root of much evil
o: out of sight,out of mind
a: absence makes the heart grow fonder
a: absinthe makes the hart grow fonder
Shortest saying:
penny wise,pound foolish
First alphabetically:
a fool and his money are soon parted
This program used 11 String objects. Bye.

sayings2.cpp 

// sayings2.cpp -- using pointers to objects
// compile with string1.cpp
#include <iostream>
#include <cstdlib>      // (or stdlib.h) for rand(), srand()
#include <ctime>        // (or time.h) for time()
#include "string1.h"
const int ArSize = 10;
const int MaxLen = 81;
int main()
{
	using namespace std;
	String name;
	cout << "Hi, what's your name?\n>> ";
	cin >> name;

	cout << name << ", please enter up to " << ArSize
		<< " short sayings <empty line to quit>:\n";
	String sayings[ArSize];
	char temp[MaxLen];               // temporary string storage
	int i;
	for (i = 0; i < ArSize; i++)
	{
		cout << i + 1 << ": ";
		cin.get(temp, MaxLen);
		while (cin && cin.get() != '\n')
			continue;
		if (!cin || temp[0] == '\0') // empty line?
			break;                   // i not incremented
		else
			sayings[i] = temp;       // overloaded assignment
	}
	int total = i;                   // total # of lines read

	if (total > 0)
	{
		cout << "Here are your sayings:\n";
		for (i = 0; i < total; i++)
			cout << sayings[i] << "\n";

		// use pointers to keep track of shortest, first strings
		String * shortest = &sayings[0]; // initialize to first object
		String * first = &sayings[0];
		for (i = 1; i < total; i++)
		{
			if (sayings[i].length() < shortest->length())
				shortest = &sayings[i];
			if (sayings[i] < *first)     // compare values
				first = &sayings[i];     // assign address
		}
		cout << "Shortest saying:\n" << *shortest << endl;
		cout << "First alphabetically:\n" << *first << endl;

		srand(time(0));
		int choice = rand() % total; // pick index at random
	// use new to create, initialize new String object
		String * favorite = new String(sayings[choice]);
		cout << "My favorite saying:\n" << *favorite << endl;
		delete favorite;
	}
	else
		cout << "Not much to say, eh?\n";
	cout << "Bye.\n";
	// keep window open
	/*    if (!cin)
			cin.clear();
		while (cin.get() != '\n')
			continue;
		cin.get();
	*/
	return 0;
}

执行结果:

Hi, what's your name?
>> Kirt Rood
Kirt Rood, please enter up to 10 short sayings <empty line to quit>:
1: a friend in need is a friend indeed
2: neither a borrower nor a lender be
3: a stitch in time saves nine
4: a niche in times saves stine
5: it takes a crook to catch crook
6: cold hands,warm heart
7:
Here are your sayings:
a friend in need is a friend indeed
neither a borrower nor a lender be
a stitch in time saves nine
a niche in times saves stine
it takes a crook to catch crook
cold hands,warm heart
Shortest saying:
cold hands,warm heart
First alphabetically:
a friend in need is a friend indeed
My favorite saying:
neither a borrower nor a lender be
Bye.

再执行一次得到的结果是:

Hi, what's your name?
>> Kirt Rood
Kirt Rood, please enter up to 10 short sayings <empty line to quit>:
1: a friend in need is a friend indeed
2: neither a borrower nor a lender be
3: a stitch in time saves nine
4: a niche in times saves stine
5: it takes a crook to catch crook
6: cold hands,warm heart
7:
Here are your sayings:
a friend in need is a friend indeed
neither a borrower nor a lender be
a stitch in time saves nine
a niche in times saves stine
it takes a crook to catch crook
cold hands,warm heart
Shortest saying:
cold hands,warm heart
First alphabetically:
a friend in need is a friend indeed
My favorite saying:
neither a borrower nor a lender be
Bye.

placenew1.cpp  

// placenew1.cpp  -- new, placement new, no delete
#include <iostream>
#include <string>
#include <new>
using namespace std;
const int BUF = 512;

class JustTesting
{
private:
	string words;
	int number;
public:
	JustTesting(const string & s = "Just Testing", int n = 0)
	{
		words = s; number = n; cout << words << " constructed\n";
	}
	~JustTesting() { cout << words << " destroyed\n"; }
	void Show() const { cout << words << ", " << number << endl; }
};
int main()
{
	char * buffer = new char[BUF];       // get a block of memory

	JustTesting *pc1, *pc2;

	pc1 = new (buffer) JustTesting;      // place object in buffer
	pc2 = new JustTesting("Heap1", 20);  // place object on heap

	cout << "Memory block addresses:\n" << "buffer: "
		<< (void *)buffer << "    heap: " << pc2 << endl;
	cout << "Memory contents:\n";
	cout << pc1 << ": ";
	pc1->Show();
	cout << pc2 << ": ";
	pc2->Show();

	JustTesting *pc3, *pc4;
	pc3 = new (buffer) JustTesting("Bad Idea", 6);
	pc4 = new JustTesting("Heap2", 10);
	cout << "Memory contents:\n";
	cout << pc3 << ": ";
	pc3->Show();
	cout << pc4 << ": ";
	pc4->Show();

	delete pc2;                          // free Heap1         
	delete pc4;                          // free Heap2
	delete[] buffer;                    // free buffer
	cout << "Done\n";
	// std::cin.get();
	return 0;
}

执行结果:

Just Testing constructed
Heap1 constructed
Memory block addresses:
buffer: 0153D830    heap: 0153CC50
Memory contents:
0153D830: Just Testing, 0
0153CC50: Heap1, 20
Bad Idea constructed
Heap2 constructed
Memory contents:
0153D830: Bad Idea, 6
01541250: Heap2, 10
Heap1 destroyed
Heap2 destroyed
Done

placenew2.cpp 

// placenew2.cpp  -- new, placement new, no delete
#include <iostream>
#include <string>
#include <new>
using namespace std;
const int BUF = 512;

class JustTesting
{
private:
	string words;
	int number;
public:
	JustTesting(const string & s = "Just Testing", int n = 0)
	{
		words = s; number = n; cout << words << " constructed\n";
	}
	~JustTesting() { cout << words << " destroyed\n"; }
	void Show() const { cout << words << ", " << number << endl; }
};
int main()
{
	char * buffer = new char[BUF];       // get a block of memory

	JustTesting *pc1, *pc2;

	pc1 = new (buffer) JustTesting;      // place object in buffer
	pc2 = new JustTesting("Heap1", 20);  // place object on heap

	cout << "Memory block addresses:\n" << "buffer: "
		<< (void *)buffer << "    heap: " << pc2 << endl;
	cout << "Memory contents:\n";
	cout << pc1 << ": ";
	pc1->Show();
	cout << pc2 << ": ";
	pc2->Show();

	JustTesting *pc3, *pc4;
	// fix placement new location
	pc3 = new (buffer + sizeof(JustTesting))
		JustTesting("Better Idea", 6);
	pc4 = new JustTesting("Heap2", 10);

	cout << "Memory contents:\n";
	cout << pc3 << ": ";
	pc3->Show();
	cout << pc4 << ": ";
	pc4->Show();

	delete pc2;           // free Heap1         
	delete pc4;           // free Heap2
// explicitly destroy placement new objects
	pc3->~JustTesting();  // destroy object pointed to by pc3
	pc1->~JustTesting();  // destroy object pointed to by pc1
	delete[] buffer;     // free buffer
	// std::cin.get();
	cout << "Done" << endl;
	return 0;
}

执行结果:

Just Testing constructed
Heap1 constructed
Memory block addresses:
buffer: 00B7D830    heap: 00B7CC50
Memory contents:
00B7D830: Just Testing, 0
00B7CC50: Heap1, 20
Better Idea constructed
Heap2 constructed
Memory contents:
00B7D850: Better Idea, 6
00B80CB0: Heap2, 10
Heap1 destroyed
Heap2 destroyed
Better Idea destroyed
Just Testing destroyed
Done

queue.h 

// queue.h -- interface for a queue
#ifndef QUEUE_H_
#define QUEUE_H_
// This queue will contain Customer items
class Customer
{
private:
	long arrive;        // arrival time for customer
	int processtime;    // processing time for customer
public:
	Customer() : arrive(0), processtime(0) {}
	void set(long when);
	long when() const { return arrive; }
	int ptime() const { return processtime; }
};

typedef Customer Item;

class Queue
{
private:
	// class scope definitions
		// Node is a nested structure definition local to this class
	struct Node { Item item; struct Node * next; };
	enum { Q_SIZE = 10 };
	// private class members
	Node * front;       // pointer to front of Queue
	Node * rear;        // pointer to rear of Queue
	int items;          // current number of items in Queue
	const int qsize;    // maximum number of items in Queue
	// preemptive definitions to prevent public copying
	Queue(const Queue & q) : qsize(0) { }
	Queue & operator=(const Queue & q) { return *this; }
public:
	Queue(int qs = Q_SIZE); // create queue with a qs limit
	~Queue();
	bool isempty() const;
	bool isfull() const;
	int queuecount() const;
	bool enqueue(const Item &item); // add item to end
	bool dequeue(Item &item);       // remove item from front
};
#endif

queue.cpp 

// queue.cpp -- Queue and Customer methods
#include "queue.h"
#include <cstdlib>         // (or stdlib.h) for rand()

// Queue methods
Queue::Queue(int qs) : qsize(qs)
{
	front = rear = NULL;    // or nullptr
	items = 0;
}

Queue::~Queue()
{
	Node * temp;
	while (front != NULL)   // while queue is not yet empty
	{
		temp = front;       // save address of front item
		front = front->next;// reset pointer to next item
		delete temp;        // delete former front
	}
}

bool Queue::isempty() const
{
	return items == 0;
}

bool Queue::isfull() const
{
	return items == qsize;
}

int Queue::queuecount() const
{
	return items;
}

// Add item to queue
bool Queue::enqueue(const Item & item)
{
	if (isfull())
		return false;
	Node * add = new Node;  // create node
// on failure, new throws std::bad_alloc exception
	add->item = item;       // set node pointers
	add->next = NULL;       // or nullptr;
	items++;
	if (front == NULL)      // if queue is empty,
		front = add;        // place item at front
	else
		rear->next = add;   // else place at rear
	rear = add;             // have rear point to new node
	return true;
}

// Place front item into item variable and remove from queue
bool Queue::dequeue(Item & item)
{
	if (front == NULL)
		return false;
	item = front->item;     // set item to first item in queue
	items--;
	Node * temp = front;    // save location of first item
	front = front->next;    // reset front to next item
	delete temp;            // delete former first item
	if (items == 0)
		rear = NULL;
	return true;
}

// customer method

// when is the time at which the customer arrives
// the arrival time is set to when and the processing
// time set to a random value in the range 1 - 3
void Customer::set(long when)
{
	processtime = std::rand() % 3 + 1;
	arrive = when;
}

 bank.cpp

// bank.cpp -- using the Queue interface
// compile with queue.cpp
#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime>   // for time()
#include "queue.h"
const int MIN_PER_HR = 60;

bool newcustomer(double x); // is there a new customer?

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;
	using std::ios_base;
	// setting things up
	std::srand(std::time(0));    //  random initializing of rand()

	cout << "Case Study: Bank of Heather Automatic Teller\n";
	cout << "Enter maximum size of queue: ";
	int qs;
	cin >> qs;
	Queue line(qs);         // line queue holds up to qs people

	cout << "Enter the number of simulation hours: ";
	int hours;              //  hours of simulation
	cin >> hours;
	// simulation will run 1 cycle per minute
	long cyclelimit = MIN_PER_HR * hours; // # of cycles

	cout << "Enter the average number of customers per hour: ";
	double perhour;         //  average # of arrival per hour
	cin >> perhour;
	double min_per_cust;    //  average time between arrivals
	min_per_cust = MIN_PER_HR / perhour;

	Item temp;              //  new customer data
	long turnaways = 0;     //  turned away by full queue
	long customers = 0;     //  joined the queue
	long served = 0;        //  served during the simulation
	long sum_line = 0;      //  cumulative line length
	int wait_time = 0;      //  time until autoteller is free
	long line_wait = 0;     //  cumulative time in line


// running the simulation
	for (int cycle = 0; cycle < cyclelimit; cycle++)
	{
		if (newcustomer(min_per_cust))  // have newcomer
		{
			if (line.isfull())
				turnaways++;
			else
			{
				customers++;
				temp.set(cycle);    // cycle = time of arrival
				line.enqueue(temp); // add newcomer to line
			}
		}
		if (wait_time <= 0 && !line.isempty())
		{
			line.dequeue(temp);      // attend next customer
			wait_time = temp.ptime(); // for wait_time minutes
			line_wait += cycle - temp.when();
			served++;
		}
		if (wait_time > 0)
			wait_time--;
		sum_line += line.queuecount();
	}

	// reporting results
	if (customers > 0)
	{
		cout << "customers accepted: " << customers << endl;
		cout << "  customers served: " << served << endl;
		cout << "         turnaways: " << turnaways << endl;
		cout << "average queue size: ";
		cout.precision(2);
		cout.setf(ios_base::fixed, ios_base::floatfield);
		cout << (double)sum_line / cyclelimit << endl;
		cout << " average wait time: "
			<< (double)line_wait / served << " minutes\n";
	}
	else
		cout << "No customers!\n";
	cout << "Done!\n";
	// cin.get();
	// cin.get();
	return 0;
}

//  x = average time, in minutes, between customers
//  return value is true if customer shows up this minute
bool newcustomer(double x)
{
	return (std::rand() * x / RAND_MAX < 1);
}

执行结果:

Case Study: Bank of Heather Automatic Teller
Enter maximum size of queue: 10
Enter the number of simulation hours: 100
Enter the average number of customers per hour: 15
customers accepted: 1426
  customers served: 1426
         turnaways: 0
average queue size: 0.15
 average wait time: 0.63 minutes
Done!
Case Study: Bank of Heather Automatic Teller
Enter maximum size of queue: 10
Enter the number of simulation hours: 100
Enter the average number of customers per hour: 30
customers accepted: 2824
  customers served: 2824
         turnaways: 133
average queue size: 4.82
 average wait time: 10.25 minutes
Done!
Case Study: Bank of Heather Automatic Teller
Enter maximum size of queue: 20
Enter the number of simulation hours: 100
Enter the average number of customers per hour: 30
customers accepted: 2928
  customers served: 2910
         turnaways: 95
average queue size: 9.90
 average wait time: 20.28 minutes
Done!
Case Study: Bank of Heather Automatic Teller
Enter maximum size of queue: 10
Enter the number of simulation hours: 4
Enter the average number of customers per hour: 30
customers accepted: 109
  customers served: 103
         turnaways: 0
average queue size: 1.32
 average wait time: 2.76 minutes
Done!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙有肥鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值