【问题标题】:how to grow a dynamic array of char pointers (in C++)?如何增长 char 指针的动态数组(在 C++ 中)?
【发布时间】:2010-02-16 21:43:42
【问题描述】:

我正在尝试使用 char 指针数组。
假设我像这样动态声明这样一个数组:

int numrows=100;  
char** array = new char*[numrows];  

然后我使用 getline 从文件中获取字符串,将字符串转换为 char 数组,然后在我的数组中设置一个指针以指向所述 char 数组,如下所示:

string entry;  
int i=0;
while (getline(file,entry)){  
  char* cstring = new char[entry.length()];  
  array[i]=strncpy(cstring,entry.c_str(),entry.length());  
  free(cstring);  
  i++;  
}

(这可行,但有更好的方法吗?)
问题是,一旦 i 大于 numrows,我不知道如何增长数组。 我知道如何为一维数组执行此操作,但二维性让我失望。

我想我应该能够像你增长一维数组一样增长它,对吧?

if (i==numrows){  
  char** temp = new char*[numrows+numrows];  
  for (int j=0;j<i;j++){  
    char* cstring = new char[strlen(array[i])];  
    temp[i]=strncpy(cstrin,array[i],strlen(array[i]));  
    free(cstring);
  }
  delete [] array;
  array = temp;
}

因此,如果当前数组已满,则创建一个两倍于当前数组大小的第二个数组,并用当前数组的内容填充它。然后删除数组并让数组指向temp。我可以将 temp 设置为新数组。我可以将array的内容放入temp,但是当我删除array并设置array = temp时,array的内容不是temp的内容。

所以我的问题是我如何/应该如何增长这个动态的 char 指针数组?

【问题讨论】:

  • 有什么特别的原因让你让自己如此痛苦,而不仅仅是使用std::vector&lt;std::string&gt;?也不要不要在您使用new 分配的内容上调用free。当您使用new 分配时,您必须始终使用delete(或delete[])解除分配。使用 free 是未定义的行为。
  • 好吧,一旦我读取了所有数据,我需要根据排序键对其进行排序(即从字符 1 到 3);我开始使用 string 类,但每当我必须通过将它们解析为 cstrings 并比较指定区域来比较两个字符串时,它会大大降低我的程序速度。
  • 深入阅读后,这段代码有很多问题。重新分配数组是最少的问题。您需要对指针的工作原理进行基本审查。
  • @zebraman,了解std::string 的成员如何帮助您完成这项任务要比尝试在 C++ 中执行这些 C 风格的杂技要容易得多。最好将您的排序问题作为一个单独的问题发布。
  • 你应该使用 std::string 的 std::vector,然后你应该使用 std::sort。

标签: c++ dynamic pointers char


【解决方案1】:

使用 std::vector - 它是你的朋友

 std::vector<std::string> arr;
 while(getline(file, entry))
   {
       arr.push_back(entry);
  }

完成

可以使用带有自定义比较的矢量排序来完成排序

 bool less3(const std::string &s1, const std::string &s2)
 {
      return s1.compare(0, 3, s2, 0, 3) == 0;
 }

 std::sort(arr.begin(), arr.end(), less3);

我敢打赌,less3 可以提高效率,但可读性胜出,除非你真的很痛苦

根据 gman 的好评论进行编辑修复

【讨论】:

  • @pm100 谢谢,直到现在我才知道 substr() 函数。这将使事情变得容易得多。不过,我对 substr 的错误处理有疑问。假设我有一个字符串 s="Hello";它的长度是 5。如果我调用 s.substr(4,6) 会发生什么?
  • @zebraman:它会夹住它。也就是说,你得到“o”。如果索引为&gt;= size(),则抛出out_of_range 异常。
  • @pm100:您的比较效率低于必要。您将为 2 个大小为 3 的字符串分配空间,将子字符串复制到其中,比较它们,然后删除内存。而是使用compare 函数:return s1.compare(0, 3, s2, 0, 3) == 0;
  • @zeb - 啊哈 - 例外,一个全新的世界等待着你的发现
  • @GMan 比较函数如何处理超出范围的索引?
【解决方案2】:

除了 Tyler McHenry 的评论以及您应该使用 STL 的事实之外,问题很可能是您在复制每个 cstring 后释放了它。也许您打算释放原始字符串?

  for (int j=0;j<i;j++){  
    char* cstring = new char[strlen(array[i])];  
    temp[i]=strncpy(cstring,array[i],strlen(array[i]));  
    delete[] array[i];
  }

当你第一次填充数组时,不要在字符串上调用 free()。首先,你应该使用delete[],但更重要的是,你以后还想访问那个字符串,对吧?

【讨论】:

  • 确实如此。这是一个类,不允许使用 STL。
  • @zebraman 我已经用“作业”标签标记了这个。以后在学校发布问题时,请自己这样做。 (不过,您发布的内容很好,因为您展示了您已经尝试过的内容)
【解决方案3】:

现在我看到你说这是一个允许你使用 STL 的类。禁止主要语言功能之一的 C++ 课程! - 反正路过

你不需要复制字符串来调整数组的大小,你只需要复制指针。

 if (i==numrows){  
   char** temp = new char*[numrows+numrows];  
   for (int j=0;j<i;j++){  
     temp[j]=array[j];
    }
    delete [] array;
    array = temp;
 }

我确信仍然有一些人在那里 - 作为家庭作业留下

【讨论】:

    猜你喜欢
    • 2014-04-15
    • 2012-01-09
    • 2021-01-26
    • 2021-04-21
    • 2013-05-06
    • 1970-01-01
    • 2012-03-19
    • 2021-04-15
    • 2017-05-27
    相关资源
    最近更新 更多