我无法使用 cin.getline() 从用户那里获取 3 个字符串并使用指针数组来存储它们

Posted

技术标签:

【中文标题】我无法使用 cin.getline() 从用户那里获取 3 个字符串并使用指针数组来存储它们【英文标题】:I am having trouble getting 3 strings from the user using cin.getline() and using a pointer array to store them 【发布时间】:2019-02-25 16:46:54 【问题描述】:

我的 cin.getline 出现异常。我是 C++ 新手,如果代码真的很糟糕,我很抱歉。

GetInput 函数应执行以下操作: 此函数接受三行用户输入文本并将输入的行存储为三个单独的字符串。使用指针数组来存储字符串。该函数应要求用户输入三行数据。该函数将信息存储在指针数组中。 (cin.getline())。应该在 GetInput 内部分配,并且应该是每个字符串的正确大小。

int main() 
    char* str[2];
    GetInput(str); 



void GetInput(char* ptr[]) 
    for (int i = 0; i < 3; i++) 
        cout << "Enter a string: ";
        cin.getline(ptr[i], strlen(ptr[i]), '\n');
    

【问题讨论】:

问问自己:char* str[2]; 指向什么内存? 正确。那么当您尝试将数据复制到它所指向的位置时呢? @Jolly_Jimmy 我建议您研究标准 c++ 功能 std::stringstd::vector(或 std::array)。 你可能想要std::vector&lt;std::string&gt; 具体要求是什么?请将其添加到问题中,因为要从用户那里获取 3 个字符串,您不需要单个指针 【参考方案1】:

不幸的是,赋值需要指针,因为使用std::vector&lt;std::string&gt; 会很容易。如果确实需要使用指针,请使用智能指针,例如 std::unique_ptr。当它们被销毁(超出范围)时,它们将delete/delete[]它们拥有的原始指针,因此有助于防止内存泄漏。因此,使用数组和指针,这是可以做到的一种方式。

#include <iostream>
#include <array>    // std::array
#include <cstring>  // std::memcpy
#include <memory>   // std::unique_ptr

constexpr size_t max_line_length = 256;

// convenience alias
using CStrPtr = std::unique_ptr<char[]>;

void GetInput(std::array<CStrPtr, 3>& ptrs) 
    char buf[max_line_length]; // temporary buffer when reading a line

    // loop through the 3 pointers in the array
    for(CStrPtr& cptr : ptrs) 
        std::cout << "Enter a string: ";
        std::cin.getline(buf, max_line_length);
        size_t len = std::strlen(buf) + 1; // +1 to make place for the string terminator, '\0'
        // create a new pointer to a char[] with space for the string
        // and assign it to the pointer in the array
        cptr = std::make_unique<char[]>(len);
        // copy the string in buf into the space the raw pointer held by cptr now points to
        std::memcpy(cptr.get(), buf, len);
    


int main() 
    std::array<CStrPtr, 3> strs;
    GetInput(strs);
    for(const CStrPtr& cptr : strs) 
        std::cout << cptr.get() << "\n";
    

如果您不允许使用标准智能指针,您可以创建自己的智能指针或简单的字符串类。这是上面的一个版本,但有一个简单的字符串类:

#include <iostream>
#include <array>     // std::array
#include <cstring>   // std::strlen
#include <algorithm> // std::copy

constexpr size_t max_line_length = 256;

class cstring 
    char* m_mem; // the precious pointer
public:
    cstring() : // default constructor
        m_mem(new char[1]) // make place for the string terminator
    
        m_mem[0] = '\0'; // the string terminator
    
    cstring(char const* buf) : // converting constructor
        m_mem
    
        // allocate memory
        size_t len = std::strlen(buf) + 1;
        m_mem = new char[len];
        // and copy buf to m_mem
        std::copy(buf, buf+len, m_mem);
    
    cstring(const cstring& o) : // copy ctor
        cstring(o.m_mem) // delegate to converting ctor
    
    cstring(cstring&& o) : // move ctor
        // copy the pointer from o and set o:s pointer to nullptr
        m_mem(std::exchange(o.m_mem, nullptr))
    
    cstring& operator=(const cstring& o)  // copy assignment
        *this = cstring(o); // using copy ctor + move assignment
        return *this;
    
    cstring& operator=(cstring&& o)  // move assignment
        // swap pointers: let o destroy our old pointer for us
        std::swap(m_mem, o.m_mem);
        return *this;
    
    ~cstring()  delete[] m_mem;  // destructor

    // user-defined conversions
    operator char const* () const  return m_mem; 
    operator char* ()  return m_mem; 
;

void GetInput(std::array<cstring, 3>& ptrs) 
    char buf[max_line_length]; // temporary buffer when reading a line

    // loop through the 3 pointers in the array
    for(cstring& cptr : ptrs) 
        std::cout << "Enter a string: ";
        std::cin.getline(buf, max_line_length);
        // create a new cstring and assign it to the cstring in the array
        cptr = cstring(buf);
    


int main() 
    std::array<cstring, 3> strs;
    GetInput(strs);
    for(const cstring& cptr : strs) 
        // cptr will here use the user-defined conversion to "char const*"
        // for which there's a standard operator<< defined
        std::cout << cptr << "\n";
    

【讨论】:

智能指针会很好,但我不相信它们是允许的。 @Jolly_Jimmy 这听起来很糟糕,但在这种情况下,我会将原始指针封装在我自己的字符串类中。添加了一个示例。【参考方案2】:
#include <iostream>
#include <string>

using namespace std;

void getLine(string ptr[]) 
    for (int index = 0; index < 3; ++index) 
        string line;
        getline(cin, line);
        ptr[index] = line;
    


int main() 
    string ptr[3];
    getLine(ptr);

    for (int index = 0; index < 3; ++index) 
        cout << ptr[index] << endl;
    

您的代码有几个地方有问题。首先,您没有为数组分配足够的空间。您的长度应该是数组的长度,而不是最后一个元素的索引。因此,如果是 3 个字符串,则为 [3]。

接下来,我不会使用 char * 而是使用 string 类。查看我的代码。

第三,你的 strlen 东西——嗯,你有一个指向内存中随机位置的指针数组,或者可能是一个空指针数组。不管怎样,都是错的。

你可以这样做:

char myStrings[3][1000];

然后在您的 getline 中,使用 1000 作为最大长度(可能是 999 - 我不使用您所做的形式的 getline)。这将分配 3 个字符数组,每个 1000 字节。

但是 strlen 只是 flat 的东西不会起作用,因为你没有从任何字符串开始 strlen 。

【讨论】:

感谢您的帮助,不幸的是,我无法使用字符串类进行此分配,并且在 getline 中它应该准确分配字符串所需的内容。 Getline 不分配空间。你给它你已经分配的缓冲区的最大长度。您可以创建一个非常大的缓冲区,然后使用 strdup() 将其复制到位。

以上是关于我无法使用 cin.getline() 从用户那里获取 3 个字符串并使用指针数组来存储它们的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 cin.getline 读取字符数组

关于cin,getline一起出现无法正常输入的问题

使用 cin.getline() 和 cin.get()

c++中 cincin.get()cin.getline()cin.getchar()的区别

std::cin.getline() 与 std::cin

C++ 中 cin.getline() 的意外返回