C++ Printer Plus学习笔记 第四章 复合类型之字符串

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/soulwyb/article/details/89354007

数组

编译器不会去判断数组下标是否越界。但是在程序运行后,这种赋值可能引发问题。 它可能破坏数据或代码。也可能导致程序异常终止。

C++ 风格的数组初始化 int yamcosts[3] = {20, 30, 5}; 或者(C++11) int yamcosts[3] {20, 30, 5};

int yamcosts[8] = {20, 30, 5}; 这样只会初始化前三个 其他的全部默认为0

int yamcosts[] = {20, 30, 5};这样C++会计算大括号中的常量个数。然后将数组初始化为该个数的长度的数组。

int yamcosts[3] = {}; 这样会全部设置成0

禁止缩窄转换 

char yamcosts[3] = {'a', 30, 11111111111(long类型)};

字符串:

C风格:

char a[4] = {'a','b','c','c'} 这是字符数组

chara[4] = {'a','b','c','\0'}这是字符串,因为有\0做结尾  

初始化方法: char build[11] = "Mr. cheeps"; 数组长度比实际的字符长度多1位

或者 char build[] =  "Mr. cheeps"; 省事

‘s’ != "S" 类型不一样  字符串 是字符+‘\0’  无法转换成char类型 而且 “S”实际是指向该字符串所在的内存地址。

strlen()是计算字符串的长度。去掉空格,去掉'\0' 

sizeof()是计算数组的长度。包括了'\0'

直接使用cin输入字符串。 如果输入带有空格将会直接跳过第二次输入。然后把空格后面的字符串当做第二次输入赋值给第二个数组。

可以使用getline()来解决这个问题 面向行的输入  他会读取一行知道换行符的出现。然后去掉换行符,用空字符来替代换行符。存储到数组中 例子: getline(name(数组变量名), size(读入的字符数(包含了'\0')))

也可以使用get(),跟getline()的区别是  get()在读取换行符的时候会停止。但是他不会去掉换行符。例子:

get(name, size)  返回值为cin对象

但这里有一个问题  他不去掉换行符。在调一次get()的时候就读不下去了。咋办?  使用get()(注意,这里不带任何参数)

他会读取下一个字符。无论下一个字符是不是换行符。所以 要这么写: get(name, size).get() 

那如果碰到空行 get()会设置失效位,这样就无法接收接下来的输入了。 这时候就需要使用 cin.clear()

而getline()也有这个问题。但是他是在输入的字符串比分配的空间长的时候出现的。 同样也是cin.clear()

看如下代码:

#include <iostream>

int main()
{
  using namespace std;
  cout << "What year was your house built?\n";
  int year;
  cin >> year;
  cout << "What is its street address?\n";
  char address[80];
  cin.getline(address, 80);
  cout << "Year built: " << year << endl;
  cout << "Address: " << address << endl;
  cout << "Done!\n";
  return 0;
}

cin 与 cin.getline()(或get())混用的问题  在cin之后会将换行符留在输入流中。在第二行执行的时候就会读取到这个换行符,然后就会将空行赋值给下一个数组 然后就结束了。 如果是使用get()的话 还会导致失效位。 所以需要在cin>>year这里修改成:(cin>>year).get() 跳过换行符就没事了。

修改成:

#include <iostream>

int main()
{
  using namespace std;
  cout << "What year was your house built?\n";
  int year;
  (cin >> year).get();
  cout << "What is its street address?\n";
  char address[80];
  cin.getline(address, 80);
  cout << "Year built: " << year << endl;
  cout << "Address: " << address << endl;
  cout << "Done!\n";
  return 0;
}

C++风格字符串---string类

赋值:

#include <string>  

string str1;
string str2 = "panther";

char first_date[] = {"le chapon dodu"};
// or char first_date[] {"le chapon dodu"};
string second_date = {"the bread bowl"};
// or string second_date {"the bread bowl"};

都可以使用C++风格的初始化方法

输出方式与数组一样 包括通过下标选择字符

char a1[3];
char a2[3] = "ab";
char a1 = a2; // 错误 数组不能这样赋值

string s1;
string s2 = "ab";
s2 = s1; // string类允许这么干

s3 = s2 + s1 // 这样也行

以下代码指出了 用C风格的字符数组来存储字符串与C++风格的使用string类来存储字符串的区别:

#include <iostream>
#include <string>
#include <cstring>

int main()
{
  using namespace std;
  char charr1[20];
  char charr2[20] = "jaguar";
  string str1;
  string str2 = "panther";

  str1 = str2;
// 复制
  strcpy(charr1, charr2);
  str1 += " paste";
// 追加
  strcat(charr1, " juice");

  int len1 = str1.size();
  int len2 = strlen(charr1);
// strlen()会将空格不计算在内。
  cout << "The string " << str1 << " contains "
       << len1 << " characters.\n";
  cout << "The string " << charr1 << " contains "
       << len2 << " characters.\n";

  return 0;
}

除了以上之外还有两个问题

1. char[] 是固定长度的。 如果赋值超出长度的 将会覆盖相邻的内存数据。这会出现意想不到的异常

2. 可以使用strncat()和strncpy()来显示截取字符串长度。但是这样也增加了编写程序的复杂度。

3. 使用char[]存储字符串时, 在刚开始还没有赋值的时候 使用strlen()时 长度是随机的因为 strlen()函数是读取到空字符为止。但是因为初始化的时候没有赋值。所以字符数组的内存地址中的数据是有可能之前有用过的。

   而string的初始化时,如果没有赋值。则默认长度为0; 所以使用size()时 返回的长度是0

string字符串输入时 使用 getline(cin, str) 因为当初在设计getline时没有考虑到string类(那时候还没创造这货) 所以cin.getline()不支持string类。那就使用了友元函数的特性来完成string的输入

也可以使用cin >> str;的方式输入 但是 同样有空格问题。

关于原始字串输入的问题:

cout  << R"(Jim "King" Tutt uses "\n" instead of endl.)" << '\n';

等同于   Jim "King" Tutt uses "\n" instead of endl.)

这个使用方法 跟python的原始字符串输入的方法一模一样 只是前面的r是大写。 python是小写。

那如果要输入() 作为原始字符串的一部分时咋办

那就使用cout  << R"+*(Jim "King" Tutt (aa)uses "\n" instead of endl.)+*" << '\n';

也就是自定义定界符

在R和(之间添加任意数量的基本字符即可 不包括 空格,括号,斜杠和控制字符 比如换行符,制表符之类的。

宽字体类型的字符串与char的使用一样 只是赋值的时候在常量前加(L(wchar_t), u(char16_t), U(char32_t))即可 

然后原始字符串也是这样使用就是在R前面或后面加U或L之类的。

完结

第四章的字符串写完(第四章还没完)  好多内容。

猜你喜欢

转载自blog.csdn.net/soulwyb/article/details/89354007