《C++Primer》第五版课后习题解答_第六章(3)(16-26)


システム環境:windows 10 1703
コンパイル環境:Visual studio 2017
6.16
sは定数文字列参照として定義されるほうがよいが,そうでなければ非常量文字列および非字面量にのみバインドされ,限界がある.次のように変更できます.
bool is_empty(const string& s) { return s.empty(); }

6.17
(1)大文字があるか否かの判断
ExamUpper.h
#pragma once
#include 
#include 
using std::string;

bool ExamUpper(const string &s);
ExamUpper.cpp
#include "ExamUpper.h"

bool ExamUpper(const string &s)
{
    for (decltype(s.size()) i = 0; i != s.size(); ++i)
    {
        if (isupper(s[i]))
        {
            return isupper(s[i]);
        }
        else if (i != s.size())
        {
            continue;
        }
    }
    return isupper(s[0]);
}
ExamMain.cpp
#include "ExamUpper.h"

int main()
{
    string s;
    getline(std::cin, s);
    int a = ExamUpper(s);
    std::cout << a << std::endl;
    return 0;
}
入力:love leonie出力:0
入力:Love Leonie出力:1
(2)string対象をすべて小文字にする
s2lower.h
#pragma once
#include 
#include 
using std::string;

string s2lower( string &s);
s2lower.cpp
#include "s2lower.h"

string s2lower(string &s)
{
    for (auto &a : s)
    {
        a = tolower(a);
    }
    return s;
}
s2lowerMain.cpp
#include "s2lower.h"

int main()
{
    string s;
    getline(std::cin, s);
    s = s2lower(s);
    std::cout << s << std::endl;
    return 0;
}
入力:LOVE LEONIE
出力:love leonie
(3)2つの関数で私が使っているパラメータのタイプが違います.
文字列に大文字の関数があるかどうかを確認します.パラメータタイプは定数参照です.原因は二つある.大きな文字列のコピーによる効率の低下を回避し、参照タイプを使用します.2.関数で元の文字列の値を変更する必要がないので、定数参照タイプを使用します.
書き換え文字列は小文字の関数で、パラメータタイプは参照です.原因は二つある.大きな文字列のコピーによる効率の低下を回避し、参照タイプを使用します.2.関数で元の文字列の値を変更する必要があるので、非常に多くの参照タイプを使用します.
6.18
(a) 
    bool compare(matrix &matrix1, matrix &matrix2) { /*...*/ }
は、2つのマトリクスの内容が同じかどうかを比較し、ブール値を返します.
(b)
    vector::iterator change_val(int i, vector::iterator j) { /*...*/ }

6.19
(a)合法ではなく、形参は1つあるが、2つのパラメータが伝わっている.
(b)合法;
(c)合法;
(d)合法(入力された浮動小数点数3.8は、intタイプに強制的に変換され、関数演算に参加する).
6.20
(1)入力された実パラメータが定数である場合、または入力された実パラメータの値が変更される必要がない場合、または文字列参照を初期化するために文字列の文字面値を入力する必要がある場合、定数参照が必要である.
(2)パラメトリックが定数参照のはずなのに通常参照とすると,予想外の結果が生じる.たとえば、文字列のフォント値で参照を初期化すると、コンパイルエラーが発生します.あるいは、stringタイプのパラメータを定数参照として他の関数(正確に)定義すると、誤って定義された関数は、このような関数で正常に使用できない(教材p 192参照).
6.21
compare.h
#pragma once
#include 
using std::cout;
using std::cin;
using std::endl;

int compare(int ival, const int *ip);
compare.cpp
#include "compare.h"

int compare(int ival, const int *ip)
{
    int ans = (ival >= *ip) ? ival : *ip;
    return ans;
}
compareMain.cpp
#include "compare.h"

int main()
{
    int i = 0;
    int j = 0;
    cout << "Enter two integers: " << endl;
    cin >> i >> j;
    int ans = compare(i, &j);
    cout << "The bigger number is: " << ans << endl;
    return 0;
}
実パラメータの値を変更する必要がないため、ポインタのタイプは定数整数ポインタである必要があります.
6.22
swap.h
#pragma once
#include 
using std::cout;
using std::cin;
using std::endl;

void swap(int *&ip1, int *&ip2);
swap.cpp
#include "swap.h"

void swap(int *&ip1, int *&ip2)
{
    int *temp;
    temp = ip1;
    ip1 = ip2;
    ip2 = temp;
}
swapMain.cpp
#include "swap.h"

int main()
{
    int i = 0;
    int j = 0;
    int *ip = &i;
    int *jp = &j;

    cout << "Enter two integers: " << endl;
    cin >> i >> j;

    swap(ip, jp);
    cout << "ip " << *ip << " jp " << *jp << endl;
    return 0;
}
入力5 6
出力ip 6 jp 5
6.23
print.h
#pragma once
#include 
using std::cout;
using std::endl;
using std::begin;
using std::end;

void print(const int *ip); //    1

void print(const int *beg, const int *end);//    2

void print(const int *ip, size_t size);//    3

void print(int(&ip)[2]);//    4
print.cpp
#include "print.h"

void print(const int *ip)//    1
{
    if (ip)
    {
        while (*ip)
        {
            cout << *ip << endl;
            ++ip;
        }
    }
}

void print(const int *beg, const int *end)//    2
{
    while (beg != end)
    {
        cout << *beg++ << endl;
        ++beg;
    }
}

void print(const int *ip, size_t size)//    3
{
    for (size_t i = 0; i != size; ++i)
    {
        cout << ip[0] << endl;
    }
}

void print(int(&ip)[2])//    4
{
    for (auto a : ip)
    {
        cout << a << endl;
    }
}
printMain.cpp
#include "print.h"

int main()
{
    int i = 0, j[2] = { 0, 1 }, k[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    print(&i); print(k); //       1,        print(j),    。
                         //      1,   4          。      4      ,   print(k)       1   
    print(begin(j), end(j)); print(begin(k), end(k)); //      2
    
    print(j, end(j) - begin(j)); //     3

    //   4      ,        4      ,        1。          4          ,         。

    return 0;
}

6.24
関数は、長さ10の配列を出力します.ただし、配列はコピーできないため、1つの配列に転送されると、実際にはその配列の最初の要素を指すポインタが転送されます.したがって,問題に示すように関数を定義すると,実際に定義されたパラメータはポインタであり,配列の長さ情報は含まれていないため,エラーが発生する.
受信した実パラメータに配列の長さ情報を含めるには、次のように配列参照パラメータを使用します.
void print(const int (&ia)[10])
{
    for (size_t i = 0; i != 10; ++i)
    {
        cout << ia[i] << endl;
    }
}

6.25
#include 
#include 
using std::cout;
using std::endl;
using std::string;

int main(int argc, char* argv[])
{
    string ans;
    argc = 3;
    argv[3] = 0; //                0
    ans = static_cast(argv[1]) + " " + argv[2]; //             ,        ,                       
    cout << ans << endl;
    return 0;
}
実行可能ファイルの実行時にProject 1と入力.exe Love Leonie
出力Love Leonie
6.26
#include 
#include 
using std::cout;
using std::endl;
using std::string;

int main(int argc, char* argv[])
{
    string ans;
    argc = 5;
    argv[5] = 0; //                0
    ans = static_cast(argv[1]) + " " + argv[2] + " " + argv[3] + " " + argv[4];
    cout << ans << endl;
    return 0;
}
実行可能ファイルの実行時にProject 1と入力.exe -d -o ofile data0
出力-d-o ofile data 0