首页 > 代码库 > C++基础学习教程(二)

C++基础学习教程(二)

接上一节内容

2.5条件和逻辑

自增和自减操作符

这个主要区别就是在前和后,大多数学习过其他语言的应该都知道。所以,一个程序带过。

示例如下:

/*************************************************************************
    > File Name: list1001_++.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月18日 星期日 10时08分50秒
 ************************************************************************/

#include<iostream>
#include<string>
using namespace std;

// 自增测试
int main()
{
    int x = 42;
    cout << "x   = " << x   << "\n";
    cout << "++x = " << ++x << "\n";
    cout << "x   = " << x   << "\n";
    cout << "x++ = " << x++ << "\n";
    cout << "x   = " << x   << "\n";

    return 0;
}

结果如下:



下面继续一个小练习:从标准输入读取整数到一个向量,然后将其反序后输出,一行一个。

示例代码如下:

/*************************************************************************
    > File Name: list1003_iter_reverse.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月18日 星期日 22时36分41秒
 ************************************************************************/

#include<algorithm>
#include<iostream>
#include<iterator>
#include<string>
#include<vector>

using namespace std;
// 从标准输入读取数字存储到向量,将其反序输出(用循环,不要用内置方法)
int main()
{
    vector<int> data;
    int x;
    // 读取输入,并存储到vector
    cout << "请输入数字:" << endl;
    while(cin >> x)
    {
        data.push_back(x);
    }
    // 循环反序
    for (vector<int>::iterator start(data.begin()),end(data.end());
        start != end; // 空!!!)
    {
        -- end;
        if (start != end)
        {
            int tmp = *start;
            *start = *end;
            *end = tmp;
            ++start ;
        }
    }
    // 输出
    cout << "反序输出您输入的数字:" << endl;
    copy(data.begin(), data.end(), ostream_iterator<int>(cout, "\n"));
    return 0;
}

注意上述的for循环中的第三个语句为空,虽然不推荐如此写,但是在此处却不得不这样做。

I/O & bool类型

一个小示例:


/*************************************************************************
    > File Name: list1101_bool.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月19日 星期一 17时57分28秒
 ************************************************************************/

#include<iostream>
#include<string>
using namespace std;

// C++的I/O流允许读写bool值。默认情况下,流将他们当做数值.
// 即是true为1,false为0。
// 而操作子std::boolalpha可以通知流将bool值解析为单词(word)。
// 默认情况下,为true和false。
// 下为示例:
int main()
{
    cout << "默认情况下的输出:" << endl;
    cout << "true=" << true << '\n';
    cout << "false=" << false << '\n';
    cout << "操作子的修改:" << endl;
    cout << std::boolalpha;
    cout << "true=" << true << '\n';
    cout << "false=" << false << '\n';
    return 0;
}

C++可以将很多很多类型自动类型转换为bool类型,如下示例:

/*************************************************************************
    > File Name: list1002_auto_trans.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月20日 星期二 10时22分55秒
 ************************************************************************/

#include<iostream>
#include<string>
using namespace std;

// Automatic Type Conversion to boom

/*
 * C++ 不会将字符串的内容按照字面意思的解释以确定其是false或者true,所有的字符串都是true,即使空也是。
 */
int main()
{
    bool b;
    std::cout << std::boolalpha;
    b = false;                   std::cout << b << '\n';
    b = true;                    std::cout << b << '\n';
    b = false;                   std::cout << b << '\n';
    b = true;                    std::cout << b << '\n';
    b = 42;                      std::cout << b << '\n';
    b = 3.1415926535897;         std::cout << b << '\n';
    b = 0;                       std::cout << b << '\n';
    b = -0.0;                    std::cout << b << '\n';
    b = -1;                      std::cout << b << '\n';
    b = "1";                     std::cout << b << '\n';
    b = "0";                     std::cout << b << '\n';
    b = "false";                 std::cout << b << '\n';
    b = "";                      std::cout << b << '\n';
    b = '0';                     std::cout << b << '\n';
    b = '\0';                    std::cout << b << '\n';
    b = std::cout;               std::cout << b << '\n';
    b = std::cin;                std::cout << b << '\n';
    std::cout << '\n';
    return 0;
}

结果如下:



逻辑操作符

逻辑操作符我们之前或许一般习惯于使用符号,即&&、||、 !。其实我们更佳的选择是使用and, not, or因为上面的符号&也是一种操作符,|也是一种,我们往往使用错误,所以,推荐使用字符关键字版本的。

另:注意逻辑操作符的短路运算操作

下面是一个示例:

/*************************************************************************
    > File Name: list1104_logic.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月20日 星期二 10时42分20秒
 ************************************************************************/

#include <iostream>
#include <string>
#include <istream>
#include <iterator>
#include <vector>

using namespace std;

/*
 * 注意for循环里的逻辑判断符用的是关键字,不是&& || !的符号
 * 希望以后养成适用使用关键字的习惯,因为&和|本身就是一个有效的不同的操作符
 * 容易混淆
 */
int main()
{
    vector<int> data;
    // 标准输入读入数字
    data.insert(data.begin(),istream_iterator<int>(std::cin),istream_iterator<int>());
    
    vector<int>::iterator iter;
    for (iter = data.begin(); iter != data.end() and *iter == 0; ++iter)
        /*empty*/; // 空循环,只是检测是否有0存在 
    if (iter == data.end())
        std::cout << "data contains all zeroes\n";
    else
        std::cout << "data does not contain any zeroes\n";
        
    return 0;

}

比较操作符

关于向量的大小比较,下面是一个示例:

/*************************************************************************
    > File Name: list1105_campare_vector.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月20日 星期二 10时57分25秒
 ************************************************************************/

#include<iostream>
#include<string>
#include<vector>

using namespace std;

// 比较两个向量的大小
// 比较的方式和string一样的
int main()
{
    // 创建两个向量以及两个下标指示器并且初始化他们
    vector<int> a, b;
    vector<int>::iterator iter_a, iter_b;

    a.push_back(10);
    a.push_back(20);
    a.push_back(30);
    b.push_back(10);
    b.push_back(20);
    b.push_back(30);   // 初始化使他们相等
    // 第一次比较
    // 输出向量的内容
    cout << "向量a的内容是:" << endl;
    for(iter_a = a.begin(); iter_a!=a.end(); ++iter_a)
        cout << *iter_a << ' ';
    cout << endl;
    cout << "向量b的内容是:" << endl;
    for(iter_b = b.begin(); iter_b!=b.end(); ++iter_b)
        cout << *iter_b << ' ';
    cout << endl;

    if (a != b) cout << "wrong: a != b\n";
    if (a < b)  cout << "wrong: a < b\n";
    if (a > b)  cout << "wrong: a > b\n";
    if (a == b) cout << "okay: a == b\n";
    if (a >= b) cout << "okay: a >= b\n";
    if (a <= b) cout << "okay: a <= b\n";
    // 增加a的内容
    // 输出向量的内容
    // 输出向量的内容    
    a.push_back(40);
    cout << "向量a的内容是:" << endl;
    for(iter_a = a.begin(); iter_a!=a.end(); ++iter_a)
        cout << *iter_a << ' ';
    cout << endl;
    cout << "向量b的内容是:" << endl;
    for(iter_b = b.begin(); iter_b!=b.end(); ++iter_b)
        cout << *iter_b << ' ';
    cout << endl;
    
    if (a != b) std::cout << "okay: a != b\n";
    if (a < b)  std::cout << "wrong: a < b\n";
    if (a > b)  std::cout << "okay: a > b\n";
    if (a == b) std::cout << "wrong: a == b\n";
    if (a >= b) std::cout << "okay: a >= b\n";
    if (a <= b) std::cout << "wrong: a <= b\n";
    // 增加b,再次比较
    b.push_back(42);
    // 输出向量的内容
    cout << "向量a的内容是:" << endl;
    for(iter_a=a.begin(); iter_a!=a.end(); ++iter_a)
        cout << *iter_a <<' ';
    cout << endl;
    cout << "向量b的内容是:" << endl;
    for(iter_b = b.begin(); iter_b != b.end(); ++iter_b)
        cout << *iter_b << ' ';
    cout << endl;
    if (a != b) std::cout << "okay: a != b\n";
    if (a < b)  std::cout << "okay: a < b\n";
    if (a > b)  std::cout << "wrong: a > b\n";
    if (a == b) std::cout << "wrong: a == b\n";
    if (a >= b) std::cout << "wrong: a >= b\n";
    if (a <= b) std::cout << "okay: a <= b\n";
    
    return 0;

}


结果如下:




关于字符串的大小比较,下面是一个示例:

/*************************************************************************
    > File Name: list1106_campare_string.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月20日 星期二 11时17分58秒
 ************************************************************************/

#include<iostream>
#include<string>
using namespace std;

/*
 * 不要直接比较双引号里面的字符,除非你创建了string类型,并初始化他
 * 直接比较"help"和"SoS"是不对的,因为这样的比较是比较他们在内存中的位置,和内容本身无关,
 * 仅仅和编译器有关.
 * 因此要想比较"help"和"Sos"的大小,至少需要其中的一个为string类型
 */

int main()
{
    // 创建两个字符串并且初始化
    string a("abc"), b("abc");
    // 比较之前输出
    cout << "a的内容:" << a << endl;
    cout << "b的内容:" << b << endl;

    // 判断
    if(a != b)  cout << "wrong: abc != abc \n";
    if(a < b)   cout << "wrong: abc < abc \n" ;
    if(a > b)   cout << "wrong: abc > abc \n" ;
    if(a == b)  cout << "okay : abc = abc \n" ;
    if(a >= b)  cout << "okay : abc >= abc \n";
    if( a<= b)  cout << "okay : abc <= abc \n";

    // 增加a的内容
    a.push_back('d');
    cout << "a的内容:" << a << endl;
    cout << "b的内容:" << b << endl;
    if(a != b)  cout << "okay: abcd != abc \n";
    if(a < b)   cout << "wrong: abcd < abc \n" ;
    if(a > b)   cout << "okay: abcd > abc \n" ;
    if(a == b)  cout << "wrong : abcd = abc \n" ;
    if(a >= b)  cout << "okay : abcd >= abc \n";
    if(a<= b)   cout << "wrong: abcd <= abc \n";

    // 增加b的内容
    b.push_back('e');
    cout << "a的内容:" << a << endl;
    cout << "b的内容:" << b << endl;
    if(a != b)  cout << "okay: abcd != abce \n";
    if(a < b)   cout << "okay: abcd < abce \n" ;
    if(a > b)   cout << "wrong: abcd > abce \n";
    if(a == b)  cout << "wrong: abcd = abce \n";
    if(a >= b)  cout << "wrong:abcd >= abce \n";
    if( a<= b)  cout << "okay :abcd <= abce \n";
    
    cout << "下面的做法是不对的!!!下面直接用了\"help\" == \"hello\"的判断语句,而不是用string类型."  << endl;
    return 0;
}


运行结果:


2.6复合语句

关于C++的复合语句,必然要涉及到局部变量的说明,其实关于变量,其实就是在哪定义的就在那儿有用,在复合语句内部定义那么他的可见范围就是这个复合语句,如果实在main函数内部定义,那么就是整个main函数,如果在main函数外面,且不在其它函数内部,就是全局变量,他在整个文件都可见,但是局部变量可以覆盖全局变量。就是我的地盘听我的,地头蛇大于强龙啊。他的可见范围被称为作用域。

而好的编程实践就是尽量限制变量的作用域,限制作用域的好处是:

  • l防止出错
  • 交流意图:方便阅读啊,不然一个变量管的太宽,怎么理解。。。
  • 重用名字

C++ while语句的解析树如下所示:



下面是一个示例:


/*************************************************************************
    > File Name: list1202_vari.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月20日 星期二 18时25分17秒
 ************************************************************************/
#include<algorithm>
#include<cassert>
#include<iostream>
#include<iterator>
#include<string>
#include<vector>

using namespace std;
int main()
{
    vector<int> data;
    data.insert(data.begin(), istream_iterator<int>(cin),
               istream_iterator<int>());

    // 排序变量的笨方法
    // 假设向量中的迭代器iter之前的部分已经排好序.
    // 找到向量中已经排好序的部分中iter的位置,从向量中删除*iter,然后将其重新插入到排序位置.
    // 不变量: 下标[0, 1) 指向的元素都已经被排序
    for (vector<int>::iterator iter(data.begin());
        iter != data.end();++iter)
    {
        // 通过调用标准算法lower_bound,找到data.at(iter)的位置.lower_bound执行二分搜索.
        // 并返回一个迭代器,该迭代器指向value应该插入到data中的位置.
        int value(*iter);
        vector<int>::iterator here(lower_bound(data.begin(), iter, value));
        iter = data.erase(iter);
        data.insert(here, value);
    }

    // 调试代码:通过将向量中的每个元素与前一个元素比较,检查循环是否真正的被排序
    for (vector<int>::iterator iter(data.begin()),prev(data.end());
        iter != data.end(); ++iter)
    {
        if(prev != data.end())
            assert(not (*iter < *prev));
        prev = iter;
    }

    // 将排好序的向量打印,空向量打印{}
    cout << '{';

    string separator(" ");
    
    for (vector<int>::iterator iter(data.begin()); iter != data.end(); ++iter)
    {
        cout << separator << *iter;
        separator = ", ";
    }
    cout << "}\n";

    return 0;

}

结果如下: