【问题标题】:Using string array as function argument使用字符串数组作为函数参数
【发布时间】:2015-01-19 20:04:19
【问题描述】:

我打算编写一个程序,它会简单地从用户输入的输入中删除单个字母,假设我们有一些文本,例如:“猴子吃香蕉”,我们应该从上面的文本中删除字母“a” .

最终的输出应该是这样的: '猴子等 bnn'

我的代码可以完美地处理单个字符串,但是我必须使用 getline() 函数来获取更长的文本,这就是为什么我必须声明字符串数组,以便传递它的大小在 getline() 函数的第二个参数中,如下所示:

string text[256]; 
getline(text, 256); 

我想使用 getline() 函数而不给出数组的大小,但我认为这是不可能的,因此我需要坚持使用字符串数组而不是字符串。

我遇到的问题是我不知道如何正确传递字符串数组,以将其用作函数的参数。这是我的代码;

#include <iostream> 
#include <string> 

using namespace std; 

void deleteLetter(string &text[], char c) 
{ 
   size_t positionL = text.find(c); 
   if(positionL == string::npos) 
      cout << "I'm sorry, there is no such letter in text" << endl; 
   else 
      text.erase(positionL, positionL); 
      cout << "After your character removed: " << text << endl; 
} 

int main() 
{ 
   string str1[256]; 
   char a = 'a'; 
   cin.getline(str1, 256); 

   deleteLetter(str1, a); 
} 

我知道这是基本的东西,但我仍然无法自己解决。 Perhpahs 我应该寻求你的帮助。

【问题讨论】:

  • 使用std::vector&lt; std::string &gt;而不是数组;传递给函数更容易。
  • 另外,在传递数组时不要忘记传递数组的容量和元素个数。当您传递一个数组时,没有函数可以确定数组中的容量或项数。
  • cin.getline 在 C 字符串(字符数组)上运行,而不是在 std::string 上运行。我猜你想要的是独立的getline 函数:getline(cin, str),它在std::string 上运行 - 然后将它放在一个循环中以读取多行直到结束:while(getline(cin, str)) { deleteLetter(str, a); }
  • @ThomasMatthews 只要您不想修改 容器,使用std::string* 或类似array_view&lt;std::string&gt; 作为函数参数类型可能是更好的选择:它不需要用户使用特定的容器。

标签: c++ arrays string function


【解决方案1】:

在我看来,您不需要字符串数组。只是将用户键入的尽可能多的字符读入字符串。 getline 应该可以解决这个问题。

int main() 
{ 
    std::string str1; // just a string here, not an array.
    std::getline (std::cin,str1);

    deleteLetter(str1, 'a'); 
} 

现在您应该更改 DeleteLetter 的签名以将单个字符串作为参数。

void deleteLetter(std::string& text, char c);

您将如何实施 deleteLetter 是另一个问题。按照你的方式,它只会删除第一次出现的“a”。

【讨论】:

  • 你说得对,我的工作方式和你描述的一样。它只删除包含字母“a”的第一个单词中的字符,这是有问题的..
  • 尝试将删除字符的代码放入while循环中,它应该可以工作。只要 text.find 返回 npos 以外的内容,就删除它。
  • 像这样:while(text.find() != string::npos) {text.erase(positionL, positionL); } 我做到了,但它不起作用
  • 差不多。您必须将 text.find() 的结果存储到 positionL。即 while( (positionL = text.find()) != string::npos) {text.erase(positionL, positionL); }
  • 你打错了:它应该是'a' 而不是a 传递给deleteLetter 函数。
【解决方案2】:

要从控制台输入 (cin) 读取 string,您可以使用 getline() 函数:

std::string line;
std::getline(std::cin, line);

要从字符串中删除所有出现的给定字母,可以使用所谓的erase-remove idiom,结合string::erase() 方法和std::remove() 算法。
(注意这个成语通常显示应用于std::vector,但不要忘记std::string也可以看作是一个“字符容器”按顺序存储,类似于@987654330 @,所以这个成语也可以应用于string内容。)

要将std::string 传递给函数/方法,请使用常用的 C++ 规则,即:

  • 如果函数观察字符串(不修改它),使用const reference传递:const std::string &amp;
  • 如果函数修改字符串的内容,你可以使用non-const reference传递:std::string &amp;

一个简单的可编译代码如下:

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

//
// NOTE:
// Since the content of 'text' string is changed by the
// removeLetter() function, pass using non-const reference (&).
//
void removeLetter(string& text, char letter)
{
    // Use the erase-remove idiom
    text.erase(remove(text.begin(), text.end(), letter), 
               text.end());
}

int main()
{
    string line;
    getline(cin, line);
    cout << "Read string: " << line << endl;

    removeLetter(line, 'a');
    cout << "After removing: " << line << endl;
}

这是我用 MSVC 得到的:

C:\Temp\CppTests>cl /EHsc /W4 /nologo test.cpp
test.cpp

C:\Temp\CppTests>test.exe
monkey eats banana
Read string: monkey eats banana
After removing: monkey ets bnn

如果您还想传递字符串向量(可能在代码的其他部分),我从您的问题中不太清楚...

无论如何,如果您想要 strings 中的 vector(即您想在 vector 容器中存储一些 strings),您可以像这样简单地组合这些 STL 类模板:

std::vector<std::string> strings;

要将其传递给函数/方法,请使用常用的 C++ 规则,即:

  • 如果函数观察字符串数组(不修改它),使用const referencesconst &amp;)传递:vector&lt;string&gt; &amp;
  • 如果函数修改向量的内容,你可以使用非常量引用&amp;)传递:vector&lt;string&gt; &amp;

【讨论】:

  • 哇!令人印象深刻,我非常感谢您回答的复杂性,您在这个特定答案中付出的工作量给我留下了深刻的印象:) 非常感谢
  • @PaulRatklif:不客气。我很高兴它有帮助。因此,您可能希望将此标记为答案(或任何您认为是该线程中最好的答案)。这是 * 说“谢谢”的方式 :)