跳转至

3.5 数组

练习 3.24

请使用迭代器重做3.3.3节(第94页)的最后一个练习。

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> ivec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    for (auto iter1 = ivec.cbegin(); iter1 != ivec.cend() - 1; ++iter1)
    {
        std::cout << *iter1 + *(iter1 + 1) << std::endl;
    }

    auto begin = ivec.begin();
    auto end = ivec.end();
    auto mid = ivec.begin() + (end - begin)/2 + (end - begin)%2;
    //std::cout << begin + end << std::endl;    // 迭代器并没有实现+运算符
    std::cout << end - begin << std::endl;
    for (auto iter2 = ivec.cbegin(); iter2 != mid; ++iter2)
    {
        if (iter2 != end - 1)
        {
            std::cout << *iter2 + *(end-1) << std::endl;
        }
        else 
        {
            std::cout << *iter2 << std::endl;
        }
        --end;
    }

    return 0;
}

练习 3.25

3.3.3节(第93页)划分分数段的程序是使用下标运算符实现的,请利用迭代器改写该程序并实现完全相同的功能。

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> ivec(11, 0);

    int grade = 0;
    while(grade != -1)
    {
        std::cin >> grade;
        auto iter = ivec.begin();
        if(grade>100 || grade < 0)
        {
            continue;
        }
        iter += grade/10;
        std::cout << grade/10 << std::endl;
        (*iter)++;
    }

    for (auto i : ivec)
    {
        std::cout << i << std::endl;
    }

    return 0;
}

练习 3.26

在100页的二分搜索程序中,为什么用的是mid = beg + (end - beg) / 2, 而非mdi = (beg + end) / 2;?

因为迭代器并没有实现迭代器相加的操作符error: no match for ‘operator+’ (operand types are ‘gnu_cxx::normal_iterator >’ and ‘gnu_cxx::normal_iterator >’)

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> ivec;
    auto beg = ivec.begin();
    auto end = ivec.end();
    auto mid1 = beg + (end - beg) / 2;
    auto mid2 = (beg + end) / 2;    

    return 0;
}

练习 3.27

假设txt_size是一个无参数的函数,它的返回值是int。请回答下列哪个定义是非法的?为什么?

unsigned buf_size =1024;
(a)int ia[buf_size];    非标准用法标准为数组定义长度必须为常量非法一些编译器合法
(b)int ia[4*7-14]       合法          
(c)int ia[txt_size()]   非法一些编译器合法
(d)char st[11] = "fundamental";    非法一些编译器合法
#include <stdio.h>

int txt_size()
{
    return 0;
}

int main ()
{
    unsigned int buf_size = 1024;
    //int ia[buf_size];    // 非标准用法,标准为数组定义长度必须为常量,非法。一些编译器合法。
    //int ia[4 * 7 - 14];    // 合法
    //int ia[txt_size()];    // 非法,一些编译器合法
    char st[11] = "fundamental"; // 非法,字符串包含\n字符,初始值过多


    return 0;
}

练习 3.28

下列数组中元素的值是什么?

string sa[10];
int ia[10];
int main() {
    string sa2[10];
    int    ia2[10];
}

都默认初始化,但一些编译器不会默认初始化值,一般需要自己初始化。

#include <iostream>

std::string sa[10];
int ia[10];


int main()
{
    std::string sa2[10];
    int ia2[10];

    for (auto i : ia)
    {
        std::cout << i << std::endl;
    }
    for (auto i : ia2)
    {
        std::cout << i << std::endl;
    }
    for (auto s : sa)
    {
        std::cout << s << std::endl;
    }
    for (auto s : sa2)
    {
        std::cout << s << std::endl;
    }

    return 0;
}

练习 3.29

相比于vector来说,数组有那些缺点,请列举一些。

 * 1.定长,一旦数组容量确定就不能再改变其容量
 * 2.不一定有默认初始化值,数组默认初始化需要看编译器的支持.
 * 3.操作多数需要做数组下标越界判断.
 * 4.支持的操作符较少,如初始化一个数组.

练习 3.30

指出下面代码的索引错误

constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
    ia[ix] = ix;
#include <iostream>

int main()
{
   constexpr size_t array_size =10;
   int ia[array_size];
   // 数组下标从0开始,最后一个元素下标为array_size - 1
   for (size_t ix = 1; ix <= array_size; ++ix)
   {
       ia[ix] = ix;
   }

    return 0;
}

练习 3.31

编写一段程序,定义一个含有10个int的数组,令每个元素的值就是其下标值。

#include <iostream>

int main()
{
    const size_t array_size = 10;

    int ia[array_size] = { 0 };

    for (size_t ix = 0; ix < array_size; ++ix)
    {
        ia[ix] = ix;
        std::cout << ia[ix] << std::endl;
    }


    return 0;
}

练习 3.32

将上一题刚刚创建的数组拷贝给另外一个数组。利用vector重写程序,实现类似的功能。

#include <iostream>
#include <vector>

int main()
{
    int ia[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int ai[10] = { 0 };
    for (int i = 0; i < 10; ++i)
    {
        ai[i] = ia[i];
    }

    std::vector<int> av = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> va = av;
    for (auto a : va)
    {
        std::cout << a << std::endl;
    }


    return 0;
}

练习 3.33

对于104页的程序来说,如果不初始化scores将发生什么?

不初始化数组可能会出现垃圾值

#include <iostream>

int main()
{
    unsigned scores[11];

    for (auto s : scores)
    {
        std::cout << s << std::endl;
    }

    return 0;
}

练习 3.34

假定p1和p2指向同一个数组中的元素,则下面程序的功能是什么?什么情况下改程序非法?

#include <iostream>

int main()
{
    int a[10];

    int *p1 = a;
    int *p2 = &a[4];

    // 地址相加减结果为有符号的步长间隔
    auto length1 = p2 - p1;          // p2到p1的步长间隔,为正
    auto length2 = p1 - p2;          // p1到p2的步长间隔,为负

    std::cout << length1 << std::endl;
    std::cout << length2 << std::endl;

    //p1 += length1;
    p1 += length2;                  // 编译器并不会报错



    return 0;
}

练习 3.35

编写一段程序,利用指针将数组中的元素直为0.

#include <iostream>
#include <vector>

int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    // 迭代
    auto pbegin = std::begin(a);
    auto pend = std::end(a);
    for (pbegin; pbegin != pend; ++pbegin)
    {
        *pbegin = 0;
    }

    for (int *i = a; i != &a[5]; ++i)
    {
        std::cout << *i << std::endl;
    }

    return 0;
}

练习 3.36

编写一段程序,比较两个数组是否相等。再写一段程序,比较两个vector对象是否相等。

#include <iostream>
#include <vector>

bool isEqualIntArr(int arr1[],int arr1_count, int arr2[], int arr2_count)
{
    if (arr1_count != arr2_count)
    {
        return false;
    }

    for (int i = 0; i < arr1_count; i++)
    {
        if (arr1[i] != arr2[i])
        {
            return false;
        }
    }

    return true;
}

bool isEqualIntVec(std::vector<int> &v1, std::vector<int> &v2)
{
    if (v1.size() != v2.size())
    {
        return false;
    }

    for (int i = 0; i < v1.size(); i++)
    {
        if (v1[i] != v2[i])
        {
            return false;
        }
    }

    return true;
}

int main()
{
    int arr1[3] = { 1, 2, 3 };
    int arr2[3] = { 1, 2, 3 };
    bool ia = isEqualIntArr(arr1, sizeof(arr1)/sizeof(*arr1), arr2, sizeof(arr2)/sizeof(*arr2));
    std::cout << ia << std::endl;

    std::vector<int> v1 = { 1, 2 ,3 };
    std::vector<int> v2 = { 1, 2, 3 };
    bool va = isEqualIntVec(v1, v2);
    std::cout << va << std::endl;

    return 0;
}

C风格字符串的函数

Name Descriptions
strlen(p) 返回p的长度,空字符串不计算在内
strcmp(p1, p2) 比较p1和p2的相等性。如果p1==p2,返回0;如果p1>p2,返回一个正值;如果p1<p2,返回一个负值
strcat(p1, p2) 将p2附加到p1之后,返回p1
strcpy(p1, p2) 将p2拷贝给p1,返回p1

练习 3.37

下面的程序是何含义,程序的输出结果是什么?

#include <iostream>
#include <vector>

int main()
{
    const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
    const char *cp = ca;
    while (*cp)
    {
        std::cout << *cp << std::endl;
        ++cp;
    }

    return 0;
}

练习 3.38

在本节中我们提到,将两个指针相加不但是非法的,而且也是没什么意义。请问为什么两个指针相加没什么意义?

两个指针相加得到一个不该访问的内存空间的指针。

error: invalid operands of types ‘int’ and ‘int’ to binary ‘operator+’

#include <iostream>

int main()
{
    int *a;
    int *b;

    std::cout << a + b << std::endl;

    return 0;
}

练习 3.39

编写一段程序,比较两个sring对象。再编写一段程序比较两个C风格字符串的内容。

#include <iostream>
#include <cstring>

int main()
{
    std::string s1 = "hello", s2 = "hell";
    if (s1 == s2)
    {
        std::cout << "s1 == s2" << std::endl;
    }
    else if(s1 > s2)
    {
        std::cout << "s1 > s2" << std::endl;
    }
    else
    {
        std::cout << "s1 < s2" << std::endl;
    }

    char cs1[1024] = "hell";
    char cs2[1024] = "hello";

    if (strcmp(cs1, cs2) == 0)
    {
        std::cout << "cs1 == cs2" << std::endl;
    }
    else if(strcmp(cs1, cs2) > 0)
    {
        std::cout << "cs1 > cs2" << std::endl;
    }
    else 
    {
        std::cout << "cs1 < cs2" << std::endl;
    }

    return 0;
}

练习 3.40

编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前两个数组连接后的结果。使用strcpy和strcat把前;两个数组的内容拷贝到第三个数组中。

#include <iostream>
#include <cstring>

int main()
{
    char s1[] = { 'h', 'e', 'l', 'l', 'o', ' ' };
    char s2[] = { 'w', 'o', 'r', 'l', 'd' };

    const int length = strlen(s1) + strlen(s2);
    char s[length + 1];
    memset(s, 0, sizeof(s));

    strcpy(s, s1);
    std::cout << s << std::endl;

    strcat(s, s2);
    std::cout << s << std::endl;

    return 0;
}

练习 3.41

编写一段程序,用整型数组初始化一个vector对象。

#include <iostream>
#include <vector>

int main()
{
    int arr[4] = { 1, 2, 4, 5 };

    std::vector<int> iv(std::begin(arr), std::end(arr));
    for (auto i : iv)
    {
        std::cout << i << std::endl;
    }


    return 0;
}

练习 3.42

编写一段程序,将含有整数元素的vector对象拷贝给一个整型数组。

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> iv = { 0, 2, 4 };
    int arr[iv.size()];

    for (decltype(iv.size()) i = 0; i < iv.size(); ++i)
    {
        arr[i] = iv[i];
    }

    for (auto i : arr)
    {
        std::cout << i << std::endl;
    }

    return 0;
}