容器——string

news/2024/6/3 18:35:44 标签: 字符串, c++, string, 容器

目录

    • 背景
    • 介绍
    • 常用接口
        • 构造
        • 赋值运算符
        • 访问操作
            • `[]`访问
            • `at`访问
            • 访问首尾元素
        • 迭代器
        • 容量操作
            • 有效长度
            • 容量大小
            • 修改有效长度
            • 修改容量
            • 清空有效字符
            • 判空
            • 调整大小
            • 注意事项:
        • 内容操作
            • `+=`追加操作
            • `append`追加操作
            • 尾插操作
            • `assign`整体替换操作
            • `insert`插入操作
            • `erase`删除操作
            • `replace`部分替换操作
            • `swap`交换成员函数
            • 尾删操作
            • 字符串空间地址
            • 复制操作
            • `find`正向查找
            • `rfind`反向查找
            • (非)对象中的单个字符查找
            • 截取操作
            • `compare`比较操作
            • 输入输出
            • 一些外部函数
    • 模拟实现

背景

  在 C 语言中,字符类型是char类型,字符串类型则是以\0结尾的一些字符的集合,也就是char类型数组,末尾自带\0;而在 C 语言中,为了方便我们使用自己创建的字符串,因此在string.h头文件中包含了许多字符串操作函数,但是 C++ 是面向对象编程的语言,而 C 语言中这样的操作很明显的将对象与行为分离了,不符合主思想;另外在使用这些函数时,参数什么的都需要用户自己管理,很容易造成访问越界,非常不友好;
  因此在 C++ 中,在 STL 的容器中,出现了封装好的string类,在该类中提供了很多接口供我们使用,使字符串的操作变得更加简单安全了,很好地实现了对象与行为的结合;

介绍

  1. string是表示字符串字符串类;
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作;
  3. string在底层实际是:basic_string模板类的实例化,typedef basic_string<char, char_traits, allocator> string;
  4. 不能操作多字节或者变长字符的序列。
  5. 在使用string类时,必须包含#include<string>头文件以及using namespace std;

常用接口

构造

  • string s;:构造一个空的对象;
string s1; //空
string s2(string">"hello"); //"hello"
  • string s = const char* s;:单参构造的隐式类型转换,和上一个构造方式类似,用 C 风格字符串构造,这是上一个的简写形式;
string s2 = string">"hello";
string s3(s2); //"hello"
  • string s(const string& str, size_t pos, size_t len = npos);:从一个string对象的 pos 位置开始,截取 len 个字符构造一个对象,第三个参数如果不传,则使用缺省值, 这个值的大小不要怕越界,内部会做处理;
string s4(s2, 2, 2); //"ll"
  • string s(const char* s, size_t n);:将传入的 C 风格的字符串的前 n 个用来构造对象;
string s5(string">"hello", 3); //"hel"
  • string s(size_t n, char c);:用 n 个字符 从c 来构建一个对象;
string s6(5, string">'a'); //"aaaaa"
  • 模板迭代器:使用模板类,两个参数为另一个string对象的迭代器,注意范围为左闭右开;
template <class InputIterator>
string  (InputIterator first, InputIterator last);
string s7 = (s6.begin(), s6.end); //"aaaaa"

赋值运算符

string s1;
s1 = string">"hello:";
  • string& operator= (char c);:使用单个字符给string对象进行赋值;
string s2;
s2 = string">'m';
  • string& operator= (const string& str);:使用string对象给string对象进行赋值,该函数的返回值为string对象的引用,因此赋值运算符可以连续调用,连续赋值;
string s3;
s3 = s2 = s1;

访问操作

[]访问
  • char& operator[] (size_t pos);:将string对象的每个字符当做数组元素一样来进行访问,要注意下标不能越界,可读可写,在[]中输入下标即可返回访问元素的引用;
string s1 = string">"hello";
s1[2] = string">'a';
//输出 a
cout << s1[2] << endl;
  • const char& operator[] (size_t pos) const;:将string对象的每个字符当做数组元素一样来进行访问,要注意下标不能越界,只能进行读操作,不能进行写操作,并返回访问元素的引用,且被const修饰,只读不可写;
const string s2 = string">"hello";
//下面代码错误,不可写
//s2[2] = 'a';
//输出 l,可读
cout << s2[2] << endl;
at访问
  • char& at (size_t pos);:输入下标,返回对应下标元素的引用,可读可写,要注意下标不能越界;
string s3 = string">"hello";
//可写
s3.at(2) = string">'a';
//输出 a,可读
cout << s3.at(2) << endl;
  • const char& at (size_t pos) const;:与const char& operator[] (size_t pos) const;使用类似;
访问首尾元素
  • char& back();:无参,访问string对象的最后一个非\0的字符,返回最后一个字符的引用值,因此可以修改此字符;
string s4 = string">"hello";
//访问最后一个字符,输出 o
cout << s4.back() << endl;
  • char& front();:无参,访问string对象的第一个的字符,返回第一个字符的引用值,因此可以修改此字符;
string s5 = string">"hello";
//访问第一个字符,输出 h
cout << s5.front() << endl;
  • 注意:
    • 当调用者为const修饰的对象时,那么就会自动调用对应的被const修饰的函数,得到的返回值是被const修饰的引用值,是不可以修改的;
    • 在使用at进行访问时总是做边界检查,而使用[]进行访问时不做边界检查,因此使用[]越界时会触发断言错误,使用at()越界时会抛出异常;

迭代器

  • 概念:迭代器的本质就是字符指针,是一个字符空间的地址,它是由typedef type* iterator形式定义的,也就是说他其实是指针的别名,注意在使用迭代器时,迭代的区间是左闭右开的,也就是说从左边的地址开始,直到右边地址的前一个结束;
  • iterator begin();:返回指向字符串的第一个字符的迭代器,可以使用iterator类型变量接受,然后将解引用和 ++ 操作结合可以访问到每个字符;
  • iterator end();:返回指向字符串结束位置的后一个字符的迭代器,可以使用iterator类型变量接受,被认为是正向迭代器遍历的结束符;
string str (string">"Test string");
  for (string::iterator it = str.begin(); it != str.end(); ++it)
    cout << *it; //"Test string"
  • reverse_iterator rbegin();:返回指向字符串的最后一个字符的反向迭代器,可以使用iterator类型变量接受,使用该迭代器进行遍历时,照样是执行 ++ 的操作才能从最后一个位置向前遍历,而不是想当然的执行 - - 操作,所以反向迭代器执行 ++ 操作,进行的是向前遍历的操作;
  • reverse_iterator rend();:返回指向string对象的第一个字符之得前一个空间的反向迭代器,可以使用iterator类型变量接受,被认为是反向迭代器遍历的结束符;
string str (string">"now step live...");
  for(string::reverse_iterator rit = str.rbegin(); rit != str.rend(); ++rit)
    cout << *rit; //"...evil pets won"
  • cbegin() / cend / crbegin / crend:这四个函数的使用和上面四个一一对应,返回值类型是在上面的返回值类型前加const_;这八个函数当操作const修饰的对象时,他们都是一样的,都只有可读权限,没有可写权限,而当操作普通的string对象时,上面的四个函数可以进行读写操作,而这四个函数只能执行只读操作,因为这四个函数为只读迭代器;

容量操作

有效长度
  • size_t size() const;:以字节为单位返回字符串的长度,也就是有效长度;
  • size_t length() const;:以字节为单位返回字符串的长度,也就是有效长度;
容量大小
  • size_t capacity() const;:获取当前为字符串分配的存储空间大小,也就是最大容量,以字节表示;
  • size_t max_size() const;:获取字符串可以达到的最大长度;
string s (string">"Test string");
  cout << string">"The size of str is " << s.size() << string">" bytes." << endl;
  cout << string">"The size of str is " << s.length() << string">" bytes." << endl;
  cout << string">"The size of str is " << s.capacity() << string">" bytes." << endl;
  cout << string">"The size of str is " << s.max_size() << string">" bytes." << endl;
修改有效长度
  • void resize (size_t n);:将字符串的有效字符长度调整为 n 个字符,如果是增加有效字符的个数,那么新增的位置填充\0,如果调整的大小大于最大容量,则编译器会自动增加最大容量来保证有效长度,如果是减小有效字符个数,那么将会减小 size 值;
  • void resize (size_t n, char c);:该函数和上面的接口功能相似,区别在于如果容量增加,那么则以指定字符来填充;
修改容量
  • void reserve (size_t n = 0);:只能增加容量,将最大容量增加至指定大小;
string s (string">"Test string");
s.resize(15, string">'a');
cout << s << endl << s.size() << endl << s.capacity() << endl;
s.resize(40);
s.reserve(60);
cout << s.size() << endl << s.capacity() << endl;
清空有效字符
  • void clear();:清空有效字符,意味着将 size 置为 0;
判空
  • bool empty() const;:判断字符串是否为空,返回布尔值,为空返回true,不为空返回flase
调整大小
  • void shrink_to_fit();:适当调整容量大小,使得容量与有效长度尽量保持在一个数量级上;
注意事项:
  1. size()length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()
  2. clear()只是将string中有效字符清空,不改变底层空间大小;
  3. resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg=0)string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。
  5. 一般情况下,我们在频繁增容时,使用reserve先增加到一个合适的大小,避免后续的频繁增容降低效率;

内容操作

+=追加操作
  • string& operator+= (const string& str);:在尾部追加string对象;
  • string& operator+= (const char* s);:在尾部追加 C 风格字符串
  • string& operator+= (char c);:在尾部追加单个字符;
string s1 = string">"abc";
string s2 = string">"123";
s2 += s1; //"123abc"
s2 += string">"def"; //"123abcdef"
s2 += string">'g'; //"123abcdefg"
append追加操作
  • string& append (const string& str);:在当前值的末尾添加string对象来扩展字符串
  • string& append (const string& str, size_t subpos, size_t sublen);:在当前值的末尾添加string对象的部分内容来扩展字符串,添加的内容为从string对象的 subpos 位置开始添加 sublen 长度的字符内容;
  • string& append (const char* s);:在当前值的末尾添加 C 风格字符串来扩展字符串
  • string& append (const char* s, size_t n);:在当前值的末尾添加 C 风格字符串的前 n 个字符来扩展字符串
  • string& append (size_t n, char c);:在当前值的末尾添加 n 个指定字符来扩展字符串
  • :在当前值的末尾添加string对象迭代器区间内的内容来扩展字符串,可以使用函数模板,所以也可以是 C 风格字符串的地址区间;
template <class InputIterator>
   string& append (InputIterator first, InputIterator last);
string str;
string str2=string">"Writing ";
string str3=string">"print 10 and then 5 more";
str.append(str2);                       // 添加"Writing "
str.append(str3,6,3);                   // 添加"10 "
str.append(string">"dots are cool",5);          // 添加"dots "
str.append(string">"here: ");                   // 添加"here: "
str.append(10u,string">'.');                    // 添加".........."
str.append(str3.begin()+8,str3.end());  // 添加" and then 5 more"
尾插操作
  • void push_back (char c);:尾插一个字符;
string s1 = string">"abc";
s1.push_back(string">'d'); //"abcd"
assign整体替换操作
  • string& assign (const string& str);:将当前字符串内容替换为string对象;
  • string& assign (const string& str, size_t subpos, size_t sublen);:将当前字符串内容替换为string对象的部分内容,替换为从string对象的 subpos 位置开始后续的 sublen 长度的内容;
  • string& assign (const char* s);:将当前字符串内容替换为指定 C 风格字符串
  • string& assign (const char* s, size_t n);:将当前字符串内容替换为指定 C 风格字符串的前 n 个字符;
  • string& assign (size_t n, char c);:将当前字符串内容替换为 n 个指定字符;
  • 函数模板,将当前字符串内容替换为指定内容的某一区间的内容,可以是迭代器,也可以是地址空间;
template <class InputIterator>
   string& assign (InputIterator first, InputIterator last);
string str;
string base=string">"The quick brown fox jumps over a lazy dog.";
str.assign(base);
str.assign(base,10,9);// "brown fox"
str.assign(string">"pangrams are cool",7);// "pangram"
str.assign(string">"c-string");// "c-string"
str.assign(10,string">'*');// "**********"
str.assign(base.begin()+16,base.end()-12);// "fox jumps over"
insert插入操作
  • string& insert (size_t pos, const string& str);:在 pos 位置插入string对象;
  • string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);:在 pos 位置插入string对象的部分内容,插入部分为string对象的 subpos 位置开始后续的 sublen 长度的内容;
  • string& insert (size_t pos, const char* s);:在 pos 位置插入 C 风格的字符串
  • string& insert (size_t pos, const char* s, size_t n);:在 pos 位置插入 C 风格的字符串的前 n 个字符;
  • string& insert (size_t pos, size_t n, char c);:在 pos 位置插入 n 个指定字符;
  • void insert (iterator p, size_t n, char c);:在迭代器 p 的位置插入 n 个指定字符;
  • iterator insert (iterator p, char c);:在迭代器 p 的位置插入一个指定字符;
  • 函数模板,在迭代器 p 的位置,插入另一个对象在某个区间的内容;
template <class InputIterator>
   void insert (iterator p, InputIterator first, InputIterator last);
string str=string">"to be question";
string str2=string">"the ";
string str3=string">"or not to be";
string::iterator it;
str.insert(6,str2);                 // to be (the )question
str.insert(6,str3,3,4);             // to be (not )the question
str.insert(10,string">"that is cool",8);    // to be not (that is )the question
str.insert(10,string">"to be ");            // to be not (to be )that is the question
str.insert(15,1,string">':');               // to be not to be(:) that is the question
it = str.insert(str.begin()+5,string">','); // to be(,) not to be: that is the question
str.insert (str.end(),3,string">'.');     // to be, not to be: that is the question(...)
str.insert (it+2,str3.begin(),str3.begin()+3); // to be, (or) not to be: that is the question...
erase删除操作
  • string& erase (size_t pos = 0, size_t len = npos);:删除string对象的某一下标范围内的字符内容;
  • iterator erase (iterator p);:删除string对象的某一迭代器所指向的字符;
  • iterator erase (iterator first, iterator last);:删除string对象的某一迭代器范围内的字符内容;
std::string str (string">"This is an example sentence.");// "This is an example sentence."
str.erase (10,8);                     	  // "This is an sentence."
str.erase (str.begin()+9);            	  // "This is a sentence."
str.erase (str.begin()+5, str.end()-9);   // "This sentence."
replace部分替换操作
  • string& replace (size_t pos, size_t len, const string& str);:将string对象的某一下标区间内的内容替换为另一个string对象;
  • string& replace (iterator i1, iterator i2, const string& str);:将string对象的某一迭代器区间内的内容替换为另一个string对象;
  • string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);:将string对象的某一下标区间内的内容替换为另一个string对象的某个下标区间内的内容;
  • string& replace (size_t pos, size_t len, const char* s);:将string对象的某一下标区间内的内容替换为一个 C 风格字符串
  • string& replace (iterator i1, iterator i2, const char* s);:将string对象的某一迭代器区间内的内容替换为一个 C 风格字符串
  • string& replace (size_t pos, size_t len, const char* s, size_t n);:将string对象的某一下标区间内的内容替换为一个 C 风格字符串的前 n 个字符;
  • string& replace (iterator i1, iterator i2, const char* s, size_t n);:将string对象的某一迭代器区间内的内容替换为一个 C 风格字符串的前 n 个字符;
  • string& replace (size_t pos, size_t len, size_t n, char c);:将string对象的某一下标区间内的内容替换为 n 个指定字符;
  • string& replace (iterator i1, iterator i2, size_t n, char c);:将string对象的某一迭代器区间内的内容替换为 n 个指定字符;
  • 函数模板,:将string对象的某一迭代器区间内的内容替换为某一字符指针范围内的内容;
template <class InputIterator>
  string& replace (iterator i1, iterator i2,  InputIterator first, InputIterator last);
string base=string">"this is a test string.";
string str2=string">"n example";
string str3=string">"sample phrase";
string str4=string">"useful.";
string str=base;           // "this is a test string."
str.replace(9,5,str2);          // "this is an example string." (1)
str.replace(19,6,str3,7,6);     // "this is an example phrase." (2)
str.replace(8,10,string">"just a");     // "this is just a phrase."     (3)
str.replace(8,6,string">"a shorty",7);  // "this is a short phrase."    (4)
str.replace(22,1,3,string">'!');        // "this is a short phrase!!!"  (5)

str.replace(str.begin(),str.end()-3,str3);        // "sample phrase!!!"   (1)
str.replace(str.begin(),str.begin()+6,string">"replace"); // "replace phrase!!!"   (3)
str.replace(str.begin()+8,str.begin()+14,string">"is coolness",7);// "replace is cool!!!"  (4)
str.replace(str.begin()+12,str.end()-4,4,string">'o');  // "replace is cooool!!!"  (5)
str.replace(str.begin()+11,str.end(),str4.begin(),str4.end());// "replace is useful."  (6)
swap交换成员函数
  • void swap (string& str);:交换两个string对象的内容;
string buyer (string">"money");
string seller (string">"goods");
cout << buyer << seller << string">'\n'; //"moneygoods"
seller.swap (buyer);
cout << buyer << seller << string">'\n';//"goodsmoney"
尾删操作
  • void pop_back();:尾删string对象的一个字符;
string str (string">"hello world!");
str.pop_back();
cout << str << string">'\n'; //"hello world"
字符串空间地址
  • const char* c_str() const;:返回string类中的存放字符串空间的首地址,且以const修饰;
  • const char* data() const;:返回string类中的存放字符串空间的首地址,且以const修饰;
  • cout << str;cout << str.c_str();str.data();虽然都是输出字符串,但是前者是输出所有有效字符,哪怕该有效字符是\0,但是后两个则是遇到\0就结束输出;
复制操作
  • size_t copy (char* s, size_t len, size_t pos = 0) const;:将string对象当前值的一个子字符串复制到 s 所指向的数组中。这个子字符串包含从pos位置开始的 len 个字符;
char buffer[20];
string str (string">"Test string...");
size_t length = str.copy(buffer,6,5);//"string"
find正向查找
  • size_t find (const string& str, size_t pos = 0) const;:从string对象的 pos 位置开始向后查找另一个string对象第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
  • size_t find (const char* s, size_t pos = 0) const;:从string对象的 pos 位置开始向后查找一个 C 风格字符串第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
  • size_t find (const char* s, size_t pos, size_t n) const;:从string对象的 pos 位置开始向后查找一个 C 风格字符串的前 n 个字符第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
  • size_t find (char c, size_t pos = 0) const;:从string对象的 pos 位置开始向后查找一个字符第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
string str (string">"There are two needles in this haystack with needles.");
string str2 (string">"needle");
size_t found = str.find(str2); //14
found=str.find(string">"needles are small",found+1,6); //44
found=str.find(string">"haystack"); //30
found=str.find(string">'.'); //51
rfind反向查找
  • size_t rfind (const string& str, size_t pos = npos) const;:从string对象的 pos 位置开始向前查找另一个string对象第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
  • size_t rfind (const char* s, size_t pos = npos) const;:从string对象的 pos 位置开始向前查找一个 C 风格字符串第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
  • size_t rfind (const char* s, size_t pos, size_t n) const;:从string对象的 pos 位置开始向前查找一个 C 风格字符串的前 n 个字符第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
  • size_t rfind (char c, size_t pos = npos) const;:从string对象的 pos 位置开始向前查找一个字符第一次出现的位置,如果查找到返回下标,未查找到则返回 npos;
string str (string">"The sixth sick sheik's sixth sheep's sick.");
string key (string">"sixth");
size_t found = str.rfind(key);
str.replace (found,key.length(),string">"seventh");//"The sixth sick sheik's seventh sheep's sick."
(非)对象中的单个字符查找
  • size_t find_first_of (const string& str, size_t pos = 0) const;:返回string对象 str 中任意字符在string对象中从 pos 位置向后的第一次出现位置;
  • size_t find_first_of (const char* s, size_t pos = 0) const;:返回 C 风格字符串中任意字符在string对象中从 pos 位置向后的第一次出现位置;
  • size_t find_first_of (const char* s, size_t pos, size_t n) const;:返回 C 风格字符串前 n 个字符中的任意字符在string对象中从 pos 位置向后的第一次出现位置;
  • size_t find_first_of (char c, size_t pos = 0) const;:返回某个指定字符在string对象中从 pos 位置向后的第一次出现位置;
  • find_last_not_of:该函数的四种用法和上面的四个函数一一对应,不同的是参数 pos 的缺省值由 0 变为 npos,而且由从前向后找变为从后向前找;
  • find_first_not_of:该函数的四种用法和上面的四个函数一一对应,不同的是,功能从找属于第一个参数的任意字符第一次出现的位置变为找不属于第一个参数的任意字符第一次出现的位置;
  • find_last_not_of:该函数的四种用法和上面的四个函数一一对应,不同的是,功能从找属于第一个参数的任意字符从前向后第一次出现的位置变为找不属于第一个参数的任意字符从后向前第一次出现的位置,且参数 pos 由 0 变为 npos;
string str (string">"Please, replace the vowels in this sentence by asterisks.");
size_t found = str.find_first_of(string">"aeiou");
while (found != string::npos){
	str[found] = string">'*';
	found = str.find_first_of(string">"aeiou",found+1);
	//Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.
}
截取操作
  • string substr (size_t pos = 0, size_t len = npos) const;:截取string对象从 pos 位置开始的 len 个字符,然后用该部分内容创建一个新的string对象,并返回该对象的值;
string str=string">"We think in generalities, but we live in details.";
string str2 = str.substr (3,5);     // "think"
compare比较操作
  • 比较函数:如果比较的两个字符串完全相等则返回 0;如果两个字符串中的第一个不匹配的字符的值在比较字符串中更低,或者所有匹配的字符都匹配但比较的字符串更短,则返回小于 0 的值;如果两个字符串中的第一个不匹配的字符的值在比较字符串中更大,或者所有匹配的字符都匹配但比较的字符串更长,则返回大于 0 的值;
  • int compare (const string& str) const;:和string对象比较大小;
  • int compare (size_t pos, size_t len, const string& str) const;:拿调用者的从 pos 位置开始的 len 个字符和string对象比较大小;
  • int compare (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const;:拿调用者的从 pos 位置开始的 len 个字符和string对象的某一区间内的字符内容比较大小;
  • int compare (const char* s) const;:和 C 风格字符串比较大小;
  • int compare (size_t pos, size_t len, const char* s) const;:拿调用者的从 pos 位置开始的 len 个字符和和 C 风格字符串比较大小;
  • int compare (size_t pos, size_t len, const char* s, size_t n) const;:拿调用者的从 pos 位置开始的 len 个字符和和 C 风格字符串的前 n 个字符比较大小;
输入输出
  • operator>>:输入运算符,使用此运算符进行输入时遇到空格或者换行则结束输入;
  • istream& getline (istream& is, string& str);:输入函数,第一个参数为cin,将字符内容输入到string对象中,遇到换行时结束输入;
  • istream& getline (istream& is, string& str, char delim);:输入函数,第一个参数为cin,将字符内容输入到string对象中,遇到 delim 字符或者换行时结束输入;
  • operator<<:输出运算符,将字符串打印在终端上;
string name;
cout << string">"Please, enter your full name: ";
getline (cin,name);
cout << string">"Hello, " << name << string">"!\n";
一些外部函数
  • operator+:将两个string对象拼接在一起,返回结果的副本,不建议使用,尽量使用operator+=
  • swap():外部交换函数;

模拟实现

  • 链接

http://www.niftyadmin.cn/n/1578924.html

相关文章

Unity 3D 游戏上线之后的流水总结

原地址&#xff1a;http://tieba.baidu.com/p/2817057297?pn1 首先、unity 灯光烘焙 &#xff1a;Unity 3D FBX模型导入、选项Model 不导入资源球、Rig 不导入骨骼、Animations 不导入动画。在Model选项勾选 Generate Linghtmap UVs 。否则、灯光烘焙、会出现阴影错乱。灯光烘…

C++中刷新输出缓冲区

by——CSDN&#xff0c;flychildc

谈C#中的Delegate

引言Delegate是Dotnet1.0的时候已经存在的特性了&#xff0c;但由于在实际工作中一直没有机会使用Delegate这个特性&#xff0c;所以一直没有对它作整理。这两天&#xff0c;我再度翻阅了一些关于Delegate的资料&#xff0c;并开始正式整理这个C#中著名的特性。本文将由浅入深的…

进程操作

目录创建进程pid_t vfork()pid_t fork()进程终止退出原因退出方法零碎内容进程等待概念阻塞与非阻塞wait函数waitpid函数获取status程序演示进程程序替换概念分类内部执行应用实例——shell模拟创建进程 pid_t vfork() 概念&#xff1a;通过复制调用该函数的进程创建一个子进…

SQL Server 高可用性(六)日志传送

日志传送是非常古老的高可用性技术。一、日志传送的实现日志传送依赖于传统的Windows技术与SQL Server代理。简单地说&#xff0c;日志传送是通过以下3个步骤实现的。1. 为主数据库创建一个事务日志备份计划2. 为辅助数据库创建一个文件复制计划3. 为辅助数据库创建一个事务日志…

string容器简单功能模拟实现

第一次尝试 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string> #include<assert.h> using namespace std;class mystring { public://迭代器,其实就是字符指针typedef char* iterator;typedef const char* const_iterator;//首地址iter…

定制了一个仿jquery的ajax函数

2019独角兽企业重金招聘Python工程师标准>>> ajax习惯了jquery的ajax函数&#xff0c;但不方便引入jquery。只好自己造轮子。以下是代码&#xff1a; function ajax(s) {var def{type:"GET",cache:false,url: location.href,contentType: "applicati…

Linux 输出流重定向缓冲设置

by——CSDN&#xff0c;Frank_Liuxing