【问题标题】:How do I assign to a C++ string null pointer parameter?如何分配给 C++ 字符串空指针参数?
【发布时间】:2017-08-02 18:18:17
【问题描述】:

我正在自学 C++,并且正在完成一本教程书中的练习。在当前问题中,我应该将一个空指针传递给一个用于触发分配姓氏提示的姓氏参数的方法。

我的问题是:

  1. 引发异常。
  2. 如果我以避免异常的方式进行分配,则不会在方法之外返回。
  3. 根据我当前的搜索结果,似乎需要双指针或引用。但是,我需要为方法使用指针参数(我使用引用参数作为另一个练习),并且文本中还没有介绍双指针(所以我觉得这是作弊/错过了课程的重点)。

如何将空指针赋值给字符串,以便在不使用引用或双指针的情况下将其保留在方法之外?

当前代码:

#include <iostream>
#include <string>

using namespace std;

void getNameByPointer(string* firstName, string* lastName)
{
    cout << "Please enter your first name: ";
    cin >> *firstName;

    // Check for null. 
    // Only request last name IF null, as per the book exercise statement.
    if (!lastName) 
    {
        string tempLastName;
        cout << "Please enter your last name: ";
        cin >> tempLastName;

        // Note: All assignment methods below fail in some way if lastName is null. 
        // I cannot find a way to assign to a null pointer that carries out 
        // of the method without using a double pointer or pointer 
        // reference, which are not yet introduced in the book.

        // (1) Throws exception 'Read Access violations': std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >::_Myres(...) returned 0x18.
        // *lastName = tempLastName;    

        // (2) This assignment is limited to the method scope.
        // lastName = &tempLastName;

        // (3) This assignment is limited to the method scope.
        // lastName = new string(tempLastName);     
    }
}

int main()
{
    string firstName;
    string lastName;

    getNameByPointer(&firstName, &lastName);
    cout << "Your name is " << firstName << " " << lastName << '\n';

    cout << "Calling method with NULL...\n";
    string firstName1;
    // Null pointer
    string *lastName1 = nullptr;

    getNameByPointer(&firstName1, lastName1);
    if(lastName1)
    {
        cout << "Your name is " << firstName1 << " " << *lastName1 << '\n';
    }
    else
    {
        cout << "Your name is " << firstName1 << '\n';
    }
}

编辑:为了更好地澄清我是否误读了问题,或者更好地传达我的限制,问题如下:

练习 3

修改您为练习 1 编写的程序,使其不再提示用户输入姓氏,而是仅在调用者为姓氏传入 NULL 指针时才这样做。

(习题 1 已经解出,但作为习题 3 的基础。)

练习 1

编写一个函数,提示用户输入他或她的名字和姓氏,作为两个单独的值。此函数应通过传递给函数的附加指针(或引用)参数将这两个值返回给调用者。尝试先使用指针,然后使用引用。

(对于练习 3,对引用函数进行了类似的解决方案,仅检查变量是否为空,因为无法在引用参数中检查 NULL。)

【问题讨论】:

  • 您确定要使用指针吗?您可以通过引用传递字符串,如果它们为空,您可以使用empty() 进行检查。
  • 我已经通过引用作为练习的另一部分。所以我的问题是关于实施而不是战略。或者他们在练习中所要求的可能由于范围可变的问题在技术上是不可行的?
  • 是否允许接受对指针的引用?喜欢:void getNameByPointer(string* firstName, string*&amp; lastName)?
  • 使用单独的函数。经验法则是,如果您有一个“可选”参数完全切断了一半的函数处理,则该函数做的太多了。
  • 向我们展示练习的全文。也许你错过了一些东西。或者我们可以向您展示解决问题的更好方法。

标签: c++ pointers


【解决方案1】:

编辑: 我相信这都是关于练习 3 中的错误,它应该是“非空”而不是 NULL 指针的情况,但这不是一个正确的答案,所以让我们分析给定的情况,看看它是否会导致矛盾。

所以当我们给一个函数一个nullptr时我们必须返回值。由于指针的值为空,它不包含应该修改哪个对象的值的信息。只有解决方法,例如在您的第三点中,但它并没有将答案更改为:“如何分配给字符串空指针,以便在不使用引用或双指针的情况下将其保留在方法之外?” - 你根本不能,因为只有空指针携带它的信息是空的。与调用者范围无关,因此无法对其进行修改。

旧: 您的问题出在 if 语句中:

    // Check for null
    if (!lastName || lastName->empty()) 

试试

    if (lastName) 

!lastName 如果等于 nullptr 则进入。您不必检查它是否为空(除非您不想覆盖当前字符串)。更重要的是,如果它是 nullptr 你不能调用它的成员函数(虽然在这里它没有被调用,因为它没有被评估,因为 !lastName 是真的)。​​

其余代码工作正常,因此与空指针传递无关:)

【讨论】:

  • !lastName || lastName-&gt;empty() 是短路评估规则的基础,所以如果!lastNametruelastName-&gt;empty() 将永远不会被执行;如果lastName 是一个空指针,它不会被取消引用。此外,这并不能回答问题。 OP 有一个练习要解决,但他在这样做时遇到了麻烦。练习需要传递一个空指针。
  • @Downvoter - 倒置条件是问题所在。而if (lastName) 解决方案。
  • @StoryTeller 代码中有三个选项,都被注释掉了,因为都不起作用。 OP 正在寻找一种替代方法来做同样的事情,这就是我眼中的问题。这个答案可能会解决一些问题,但不能解决问题。 if (lastName) 会提示用户 lastName 是否已经用非空指针初始化,这绝对不是 OP 想要的。
  • @Downvoter - 第一个不起作用,因为 OP 在 nullptr 中滑动。回想一下lastNamestring*,而不是string。 IE。这就是 *lastName = tempLastName; 崩溃的原因,UB。这些是 C 风格的输出参数。当然,只有当指针指向有效对象时,OP才想写入指向的对象。
  • @StoryTeller 这个答案说“如果它是 nullptr 你不能调用它的成员函数。”我假设这里的成员函数调用是lastname-&gt;empty()。但是,由于短路评估,它不会被空指针调用,这就是我想说的。答案甚至提到,自相矛盾(“你不能调用它的成员函数 [...] 虽然在这里它没有被调用”。将其更改为 if (lastName) 会忽略该练习,因为如果参数是 not null;练习 3 要求正好相反,所以这是错误的开始。
【解决方案2】:

我认为这里的问题是对练习 1 的误解导致练习 3 出现问题。从提供的文本中我相信这是措辞不当的练习,因此会造成混淆。下面是一种可能的解决方案来锻炼一个。

#include <string>
#include <iostream>

void ExerciseOne(std::string *, std::string *, std::string *);

int main(){

    std::string first, second, result;

    ExerciseOne(&first, &second, &result);

    return 0;
}

void ExerciseOne(std::string *first, std::string *last, std::string *result){
    std::string temp;
    std::cout << "What is your first name?\n";
    std::getline(std::cin, temp);
    *first = temp;
    std::cout << "What is your last name?\n";
    std::getline(std::cin, temp);
    *last = temp;
    *result = *first + ' ' + *last;
    return;
}

注意这句话:

这个函数应该通过额外的方法将这两个值返回给调用者 传递给函数的指针(或引用)参数。

为什么我们需要额外的参数?我只能假设这意味着应该有更多的输入,而不仅仅是名字和姓氏。没有看到完整的文本,我无法确定。也许重点是表明指针(和引用)可以用作输入和输出。练习 3 通过简单地检查其中一个指针是否有效。

void ExerciseThree(std::string *first, std::string *last, std::string *result){
    *result = *first + ' ';
    if (last == NULL){
        std::string temp;
        std::cout << "What is your last name?\n";
        std::getline(std::cin, temp);
        *result += temp;
    }
    else {
        *result += *last;
    }
    return;
}

正如您在测试中看到的那样,您不能将本地 string 分配给指针并让它在您的函数之外保持有效。如果没有更多的输入参数,这个练习就没有多大意义。当然你可以让函数简单地返回一个string,完全避免第三个参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多