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

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

开始自己的C++复习进阶之路。


声明:

这次写的博文纯当是一个回顾复习的教程,一些非常基础的知识将不再出现,或者一掠而过,这次的主要风格就是示例代码很多~~~

所有代码在Ubuntu 14.04 LTS版,GCC4.8.1(g++)编译通过。其他的平台没试过,估计有些代码在VC6.0下面通过不了,因为有些语言特性是C++11标准的。

下面就是正文的开始吧。


一、C++必须说和必须略过的一些东西

1、工具

工具的话,简答的编程貌似现在已经习惯了在GCC(g++)下了。Linux平台下面,一般不需要很大的工程的时候我都是用VIM写好代码,直接运行了。稍微复杂一点的就用CodeBlocks。不过由于打字速度一般,觉得VIM的编辑功能也不是很强,所以一般是把代码什么的在VIM写好,然后注释文档以及详细的阅读修改的就直接上Sublime Text或者Gedit了。(Emacs还没用到过, -_-||).

Windows下面的话,如果写的代码用不到C++11的新特性那就用VC6.0吧,CodeBlocks也可以,不过写这篇教程的时候我用的是VS2010的cmd编译的,貌似Windows下面好多各种的编译器。。。喜欢什么用什么吧。如果要用C++11特性的话,貌似CodeBlocks最新版本的是可以支持的。其他的编译器布吉岛。。。

所以,关于编译器的问题,或者由于编译器导致的问题,就不说了,麻烦。

2、代码风格

代码风格神马的也貌似没什么可以说的,无非是你的花括号是怎么括,你的运算符两旁有没有空格,你的注释是写在哪里等等。。。

关于我的风格在具体的示例中可以看粗来。

所有的风格只要不要太标新立异或者奇葩的话,坚持你的风格就好啦。这个实在没有什么好说的。

3、文档注释

关于C++自动文档生成我选择了Doxygen,这个在Windows和Linux下面都能用,不过Windows下面还没用,不过目测应该要比Linux下面好看和易用一点吧。

关于这个文档的一些关键字和标准请查看官方文档或者自行百度,Google一下,很多人都写了技巧和用法。

所以,关于文档和注释什么不再解释。


下面开始具体的回顾复习了。。。

二、C++基础

2.1整数表达式

程序示例:输入一系列的整数,输出其平均值。当输入的数字小于0个的时候给出提示。

整数表达式这些的,实在没必要多费口舌。直接上代码。

代码如下:

/*************************************************************************
    > File Name: list0301_int_exp.cpp
    > Author: suool
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月16日 星期五 21时06分20秒
 ************************************************************************/

#include<iostream>
using namespace std;

int main()
{
    int sum(0);
    int count(0);
    int x;

    while(cin >> x)
    {
        sum += x;
        count += 1;
    }
    if(count <= 0)
    {
        cout << count << endl; 
        cout << "The couunt is below zero !" << endl;
    }
    else 
    {
        cout << count << endl;
        cout << "Average = " << sum/count << endl ;
    }
    return 0;
}

运行结果和示例略去。(当时运行的时候木有截图,现在也不想运行截了。)


2.2字符串与简单的输入输出

这一部分涉及到转义字符,关于转义字符,在C语言和其他语言里面大家应该都灰常清楚了,所以,不再说了-_-||。。。。。

很显然C++的输入输出操作符>> & <<大家都明白的:操作符箭头指向爱你过的方向是信息流向的方向:从流到变量是输入,从变量到流是输入。

       下面是一个字符串的简单示例:一个简单的人机交互对话。代码入下:

/*************************************************************************
    > File Name: list0502_cin_string.cpp
    > Author: suool
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月16日 星期五 21时23分43秒
 ************************************************************************/

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

int main()
{
    string name;
    string response;
    cout << "What's your name ?" << endl;
    cin >> name ;
    cout << "Hello " << name << ", how are you ?" <<endl;
    cin >> response ;
    cout << name << "Good bye !" << endl;
}


2.3格式化输出(流程控制语句)

关于if或者while或者for等等循环控制语句没有必要再讲了吧。这些实在是看代码都能看懂的东西。只要有点其他的语言基础都没问题的。

So,让我们直接进入C++的格式化输出。

我们首先要达到下面的输出效果,要求就是写出这个程序。

效果如下:


程序代码如下:

/*************************************************************************
    > File Name: list0801_cout_format.cpp
    > Author: suool
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月16日 星期五 21时31分52秒
 ************************************************************************/

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

int main()
{
    cout << " N    N^2    N^3" << endl;
    // cout.flags(ios::left);
    for (int i = 0; i < 21; i++ )
    {
        cout << setw(2) << i+1
             << setw(7) << (i+1)*(i+1)
             << setw(8) << (i+1)*(i+1)*(i+1)
             << endl;
    }
    cout << "Finaish it !" << endl;
    return 0;
}

从上面的代码应该就可以看出,C++关于对齐方式的设置是使用cout.flags(ios::left);进行设置的,下面的程序中有另外一种的设置方法,就是使用cout << right; 前提是声明#include<ios>。

So,下面看一个稍微复杂一点的格式化输出,输出的效果如下:(其实就是乘法表。。)

效果如下:



程序代码如下:

/*************************************************************************
    > File Name: list0807_table_cout.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月17日 星期六 19时14分40秒
 ************************************************************************/

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

// 输出10X10的一个乘法表
int main()
{
    // 基本变量设置
    int const min(1);
    int const max(10);
    int const colwidth(4);
    
    // cout << ios::right;
    // 打印表头
    cout << setw(colwidth) << '*' << '|';
    for (int i=1; i<=max ; i++)
        cout << setw(colwidth) << i;
    cout << endl;
    // 打印分割行
    // 设置填充符
    cout << setfill('-') << setw(colwidth) << ""
         << '+'
         << setw(max * colwidth) << ""
         << endl;
    
    // 重设填充符
    cout << setfill(' ');

    // 打印每一行
    for (int row=1; row<=max; row++)
    {
        cout << setw(colwidth) << row << '|';
        for (int col= 1; col<=row; col ++)
        {
            cout << setw(colwidth) << row*col;
        }
        cout << endl;
    }

    return 0;
}

下面的小程序是关于setw()函数和对其方式和默认填充方式设置的具体表现的示例:

示例一:

/*************************************************************************
> File Name: list0803.cpp
> Author: suool_hu
> Mail: 1020935219@qq.com
> Created Time: 2014年05月16日 星期五 22时56分42秒
************************************************************************/
/** Using Alternative Fill Characters  */
#include <iomanip>
#include <iostream>
#include <ostream>

int main()
{
    using namespace std;
    
    int day(16);
    int month(5);
    int year(2014);
    int dollars(42);
    int cents(7);
    
    // Print date in USA order. Later in the book, you will learn how to
    // handle internationalization. //setfill()填充方式设置
    cout << "Date: " << setfill('0') << setw(2) << month 
        << '/' << setw(2) << day
        << '/' << setw(2) << year << '\n';
    cout << "Pay to the order of: CASH\n";
    cout << "The amount of $" << setfill('*') << setw(8) << dollars << '.'
        << setfill('0') << setw(2) << cents << '\n';

    return 0;
}

效果如下:


示例二:

/*************************************************************************
    > File Name: list0804_format_cout.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月16日 星期五 21时56分42秒
 ************************************************************************/

#include<iostream>
#include<iomanip>
#include<string>
#include<ios>
using namespace std;
// 格式化输出练习
int main()
{
    cout << '|' << setfill('*') << setw(6) << 1234 << '|' << endl;
    cout << '|' << left <<         setw(6) << 1234 << '|' << endl;
    cout << '|' <<                 setw(6) << 1234 << '|' << endl;
    cout << '|' << right <<        setw(6) << 1234 << '|' << endl;

    return 0;
}

效果如下:


2.4数组和向量

现在我们要写一个程序,要求实现:从标准输入读取数字,然后将数字排序后输出,每行输出一个。

有些人可能先想到的数据结构是用数组解决,不过,在C++中,数组是一种比较劣等的数据结构了,大多数时候我们都更倾向于使用C++的容器类型的数据结构。这个程序我们就可以使用容器中的向量来解决,代码如下:

/*************************************************************************
    > File Name: list0904_iterator_alg.cpp
    > Author: suool_hu
    > Mail: 1020935219@qq.com 
    > Created Time: 2014年05月18日 星期日 07时47分42秒
 ************************************************************************/

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

using namespace std;

// 适用迭代器和算法读入数字并排序(向量存储)
int main()
{
    cout << "请输入数字:" << endl;
    vector<int> data;
    // 每次读取一个数字
    copy(istream_iterator<int>(cin),
        istream_iterator<int>(),
        back_inserter(data));

    // 排序
    sort(data.begin(), data.end());
    cout << "您输入的数字的排序结果为:"<< endl;
    // 打印向量,一行一个数字
    copy(data.begin(), data.end(), ostream_iterator<int>(cout, "\n"));
}

关于向量:

类型:在尖括号内部的是向量的类型vector<int> data;是int类型的向量

初始化:vector没有大小,可以随时扩充和缩小,没有数组的长度大小的限制,但是在初始化的时候依然可以声明其长度大小,如:

Vector<int>  full_zero(10);    // 默认以0初始化,这个含有10个0的向量
Vector<int> full_ten(41, 10);   // 包含41个10的向量,声明以10初始化

Vector有很多自带的方法,比如插入,删除等等内置方法,具体需要使用什么方法请自行百度吧。

迭代器

上面的代码中有一个调用的函数是sort,不要以为那个是vector的成员函数,那个其实是C++ STL中的一个函数,可以对所有传递给他的序列进行排序,只要该类型可以用比较操作符(即是大于或者小于),通过提供初始位置和末端位置。

关于上面的那个begin和end的位置,end是超出末端元素的下一个位置,如下图解:


Std::sort是泛型算法的一个例子,之所以称之为泛型,是因为这些函数实现了通用算法并且具有一般性。即是说,只要能够表示成一个序列且数据可以比较,就能调用泛型算法中函数。大部分在头文件<algorithm>中,一部分在<numeric>中。

几乎所有的泛型都使用迭代器(唯一的例外是std::min & std::max,他们返回序列中最大最小值)。C++中总共有五种迭代器,但是可以分为两类:读迭代器和写迭代器。

读迭代器:指向值序列中的一个位置,使得可以对该序列进行读操作。算法对于输入使用读迭代器,且不修改值。一般而言,必须指定一对读迭代器:开始位置和超出末端的下一个位置。

写迭代器:指向序列中的一个位置,从该位置算法开始写输出。一般而言,只需要指定输出序列的位置即可。算法不能检查溢出,因此必须保证输出序列有足够的空间容纳算法要写的所有内容。

Such as:  std::copy( )算法从一个输入序列中复制值到一个输出序列。函数有三个参数:两个读迭代器以指定范围,一集一个写迭代器指定输出范围的开始位置,因此必须要保证输出有足够大的容量。