C++ Primer Plus学习笔记:第六章 分支语句和逻辑运算符

1.C++可以连着赋值,但是不能连等于/大于/小于

2.cctype软件包(头文件)

函数名称 返回值
isalnum(ch) 数字或者字母返回true,其余false
isalpha(ch) 字母返回true
iscntrl(ch) 控制符返回true
isdigit(ch) 数字返回true
isgraph(ch) 除空格以外的打印字符返回dalse
islower(ch) 小写字母返回true
isprint(ch) 可打印字符返回true
ispunct(ch) 标点符号返回true
isspace(ch) 空白符返回true
isupper(ch) 大写字母返回true
isxfigit(ch) 16进制数字返回true
tolower(ch) 返回小写
toupper(ch) 返回大写

3.?:运算符

这是唯一一个三元运算符

第一个里面写的是一个人完整的逻辑判断,其他两个可以是一行语句,也可以是简简单单一个字符串

4.switch

放一个程序看格式

// switch.cpp -- using the switch statement
#include 
using namespace std;
void showmenu();   // function prototypes
void report();
void comfort();
int main()
{
     
    showmenu();
    int choice;
    cin >> choice;
    while (choice != 5)
    {
     
        switch(choice)
        {
     
            case 1  :   cout << "\a\n";
                        break;
            case 2  :   report();
                        break;
            case 3  :   cout << "The boss was in all day.\n";
                        break;
            case 4  :   comfort();
                        break;
            default :   cout << "That's not a choice.\n";
        }
        showmenu();
        cin >> choice;
    }
    cout << "Bye!\n";
    // cin.get();
    // cin.get();
    return 0;
}

void showmenu()
{
     
    cout << "Please enter 1, 2, 3, 4, or 5:\n"
            "1) alarm           2) report\n"
            "3) alibi           4) comfort\n"
            "5) quit\n";
}
void report()
{
     
    cout << "It's been an excellent week for business.\n"
        "Sales are up 120%. Expenses are down 35%.\n";
}
void comfort()
{
     
    cout << "Your employees think you are the finest CEO\n"
        "in the industry. The board of directors think\n"
        "you are the finest CEO in the industry.\n";
}

如果想要两个条件对应一个的话真好利用switch不退出的特性处理

switch(a){
     
	case 'a':
	case 'b':cout<<"111";
			 break;
	case 'c':
	case 'd':cout<<"222";
			 break;
	default :cout<<"Err";
}

这里注意可以使用枚举

    using namespace std;
    enum {
     red, orange, yellow, green, blue, violet, indigo};
    cout << "Enter color code (0-6): ";
    int code;
    cin >> code;
    while (code >= red && code <= indigo)
    {
     
        switch (code)
        {
     
            case red     : cout << "Her lips were red.\n"; break;
            case orange  : cout << "Her hair was orange.\n"; break;
            case yellow  : cout << "Her shoes were yellow.\n"; break;
            case green   : cout << "Her nails were green.\n"; break;
            case blue    : cout << "Her sweatsuit was blue.\n"; break;
            case violet  : cout << "Her eyes were violet.\n"; break;
            case indigo  : cout << "Her mood was indigo.\n"; break;
        }
        cout << "Enter color code (0-6): ";
        cin >> code;
    }

5.break,continue

continue在跳过这次循环的时候回执行for的第三个式子,break直接跳出,不执行


6.一种新的I/O方式:

首先要知道使用cin/cout执行I/O的时候如果输入/输出出错那么cin/cout就会带上一个错误标记,并且停止以后的所有读写,使用cin.clear()/cout.clear()可以清除这个标记让程序正常运行,利用这个特性我们写一个循环读入数字的程序

cout << "You must enter " << Max << " rounds.\n";
int i;
for (i = 0; i < Max; i++)
{
     
    cout << "round #" << i+1 << ": ";
    while (!(cin >> golf[i])) {
     
        cin.clear();     // reset input
        while (cin.get() != '\n')
            continue;    // get rid of bad input
        cout << "Please enter a number: ";
    }
}

反正我一般字符数组自己解析
值得注意的是while (!(cin >> golf[i])) { 本来cin>>是没有返回值,这个返回值来自>>的重载(已不记得结构体重载>>friend istream& operator>>(istream& is,ss& a){})重载后>>的返回值是个istream对象(如果遇到EOF返回0000 0000),但是因为istream类又有一个转化函数到bool,这就完成了这句话


7.理解输入/输出

最好理清楚这个关系:

  • 你可能发现一个问题,在其他编程语言(比如python)里面,输入输出是不需要特定的包的,但是c++却需要iostream,这是故意为之的,语言设计者希望这种东西留给编译器实现者处理,这样可以有更多,更精细的格式
  • 由上可知cin/cout实际上也是由iostream来的,如果我不用iostream这个包,那么就会有其他的I/O方式,那么cin/cout究竟是什么呢?我们记得在类重载>>的时候我们这样写道
friend istream& operator>>(istream& is,ss t){
     

        从这里就可以看出,cinistream类的一个的对象

  • 有了上面的内容,你忽然想自己写一个I/O了,于是你写下
int t;
istream my_in;
my_in>>t;

结果编译器报错了

E0291	类 "std::basic_istream>" 不存在默认构造函数
错误	C2512	“std::basic_istream<char,std::char_traits<char>>: 没有合适的默认构造函数可用		
参见“std::basic_istream<char,std::char_traits<char>>”的声明

嗯,你的这个对象有了,但是默认构造函数太水了,没有提供合适的值,无法执行构造函数,比如说是从键盘输入还是文件输入,多少进制输入…很多我们都没有写出来,所以这是不可以的,当然,你要是写成这样我没意见,但是注意&不能删,否则会删除局部变量

	istream& myin=cin;
	myin >> t;

下面我们来写两种I特殊的I/O

1.文件读写(fstream)

我们知道文件读写是一种普通的输入输出读写的形式(is-a形式)所以我们可以把文件读写类作为标准输入输出类的派生类,而派生类是可以访问基类的成员函数的,所以说我们可以在文件I/O中继续使用标准I/O中的函数像<< endl setf()(在fstream原文件中我们看到了许多虚函数,但是篇没有>>说明这个就是直接用的基类成员函数)
现在我们开始实现
首先我们要知道文件读写类是标准读写的派生类,当然不能用iostream头文件了,换用fstream头文件
还有istream换成ifstreamostream换成ofstream,这个派生类构造函数也是不能直接用,我们需要把这个对象和文件路径连接起来:

ofstream f;
f.oprn("1.txt");
f<<"12";

这样就实现了向cpp文件同目录下的1.txt写入12
然后关闭文件

f.close()

这个ofstream对象可以使用很多ostream的函数比如setf()设置格式,注意的是cout设置的是cout的,他设置的就是他的,不会互相干扰
然后就是如果cpp目录下无这个文件,会自动新建,有这个文件会先清空后写入数据
可以通过如下方式修改目录与是否清空
转载自:ToConnection的博客

fstream fout;
//(1)以输出的方式打开文件,若文件不存在建立文件,若文件存在将文件长度置为0
fout.open("D:/1.txt",ofstream::out|ofstream::trunc);//不能用||
if (!fout.is_open())
{
     
return;
}


//(2)以输出的方式打开文件,如果没有文件,那么生成空文件;如果有文件,那么清空该文件,写文件的时候是文件指针指向文件末尾
fout.open("D:/1.txt",ofstream::out|ofstream::ate);//不能用||
if (!fout.is_open())
{
     
return;
}


//(3)以输出方式打开文件,如果没有文件,那么生成空文件;如果有文件,那么在文件尾追加。写文件的时候是文件指针指向文件末尾
fout.open("D:/1.txt",ofstream::out|ofstream::app);//不能用||
if (!fout.is_open())
{
     
return;
}

如果是文件输入,请在最后多按一个回车
如果一个对象遇到EOF结束输入掷出异常可以用比如:

  • cin/cin.fail()验证是否输入异常
  • cin.eof()验证是否遇到了EOF
  • good()输出最后一次输出是否成功
2.字符串流读写(sstream)

以前没有接触过stringstream这个类的时候,常用的字符串和数字转换函数就是sscanf和sprintf函数,但是毕竟是属于c的。c++中引入了流的概念,通过流来实现字符串和数字的转换方便多了。在这里,总结之前的,并介绍新学的。

  • 常见格式串:
    %% 印出百分比符号,不转换。
      %c 整数转成对应的 ASCII 字元。
      %d 整数转成十进位。
      %f 倍精确度数字转成浮点数。
      %o 整数转成八进位。
      %s 整数转成字符串。
      %x 整数转成小写十六进位。
      %X 整数转成大写十六进位。
      %n sscanf(str, “%d%n”, &dig, &n),%n表示一共转换了多少位的字符

  • sscanf函数
      sscanf函数原型为int sscanf(const char *str, const char *format, …)。将参数str的字符串根据参数format字符串来转换并格式化数据,转换后的结果存于对应的参数内。具体功能如下:
     (1)根据格式从字符串中提取数据。如从字符串中取出整数、浮点数和字符串等。
     (2)取指定长度的字符串
     (3)取到指定字符为止的字符串
     (4)取仅包含指定字符集的字符串
     (5)取到指定字符集为止的字符串
    当然,sscanf可以支持格式串"%[]"形式的,有兴趣的可以研究一下。

int main(){
     
    char s[15] = "123.432,432";
    int n;
    double f1;
    int f2;
    sscanf(s, "%lf,%d%n", &f1, &f2, &n);
    cout<<f1<<" "<<f2<<" "<<n;
    return 0;
} 
  • 库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。
     1.stringstream::str(); returns a string object with a copy of the current contents of the stream.
     2.stringstream::str (const string& s); sets s as the contents of the stream, discarding any previous contents.
     3.stringstream清空,stringstream s; s.str("");
     4.实现任意类型的转换

template<typename out_type, typename in_value>
    out_type convert(const in_value & t){
     
      stringstream stream;
      stream<<t;//向流中传值
      out_type result;//这里存储转换结果
      stream>>result;//向result中写入值
      return result;
    }
int main(){
     
    string s = "1 23 # 4";
    stringstream ss;
    ss<<s;
    while(ss>>s){
     
        cout<<s<<endl;
        int val = convert<int>(s);
        cout<<val<<endl;
    }
    return 0;
}

最终实例:

#include
#include
#include
using namespace std;
int main(){
     
    string line;
    while(getline(cin,line)){
     
        int x;
        stringstream ss(line);  //建立stringstream对象,初始化流内容为line所代表的字符串
        while(ss>>x)            //从line中一次读取数字存入x
        cout<<x<<endl;
    }
    return 0;
}

注意stringstream很慢,还不如scanf一个字符数组自己解析,大不了多读几次

你可能感兴趣的:(#,C++)