c ++一次读入一个字符的c风格字符串?

c++ read into c-style string one char at a time?

在 c++ id 中,喜欢一次读取一个字符输入到 c 风格的字符串中。如果不首先创建具有设定大小的字符数组(您不知道用户将输入多少个字符),您将如何做到这一点。既然你不能调整数组的大小,这是怎么做到的?我在考虑这些问题,但这行不通。

char words[1];
int count = 0;

char c;
while(cin.get(c))
{
    words[count] = c;
    char temp[count+1];
    count++;
    words = temp;
    delete[] temp;
}

您要求使用 C 样式数组。在这种情况下,堆栈或动态分配不会为您服务。每次添加新元素时都需要更改数组编号的计数,这是不可能自动完成的。每次读取新的 chae 时,您都必须解决并删除和保留数组。所以你必须选择:

  1. 使用 std::vector(为此目的创建)
  2. 复制里面的东西 std::vector 并在你的代码中自己写(这看起来很糟糕)

std::vector 解决方案:

std::vector<char> words;
words.reserve(ESTIMATED_COUNT); // if you you do not the estimated count just delete this line
char c;
while(cin.get(c)){
    words.push_back(c);
}

你有两种方法,第一种是使用零大小的数组,每次输入后删除数组并分配一个大+1的新数组,然后存储输入。这使用较少的内存但效率低下。 (在C中可以使用realloc提高效率)

第二种是使用缓冲区,例如将读取的输入存储在固定大小的数组中,当它变满时,将缓冲区附加到主数组的末尾(通过删除和重新分配)。

顺便说一句,您可以使用 std::vector 它会自动有效地增加自身的大小。

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

int main()
{
    string s1;
    char c;
    while (cin.get(c))
    {
        if (c == '\n')
            continue;
        s1 += c;
        cout << "s1  is: " << s1.c_str() << endl; //s1.c_str() returns c style string
    }
}

如果您打算使用 C 风格的字符串,那么:

char* words;
int count = 0;

char c;
while(cin.get(c))
{
    // Create a new array and store the value at the end.
    char* temp = new char[++count];
    temp[count - 1] = c;

    // Copy over the previous values. Notice the -1.
    // You could also replace this FOR loop with a memcpy().
    for(int i = 0; i < count - 1; i++)
         temp[i] = words[i];

    // Delete the data in the old memory location.
    delete[] words;

    // Point to the newly updated memory location.
    words = temp;
}

我会按照 Humam Helfawi 的建议使用 std::vector<char>,因为您使用的是 C++,它会让您的生活更轻松。上面的实现基本上是不太优雅的 vector 版本。如果您事先不知道大小,那么您将不得不调整内存大小。

因为您不能使用 std::vector,我假设您也不能使用 std::string。如果你可以使用std::string,你可以使用.

提供的解决方案

否则,您唯一的选择是:

  1. 使用指向动态分配内存的指针。
  2. 跟踪分配数组的大小。如果要存储的字符数超过当前大小,增加数组大小,分配新内存,将内容从旧内存复制到新内存,删除旧内存,使用新内存。
  3. 删除函数末尾分配的内存。

这是我的建议:

#include <iostream>

int main()
{
   size_t currentSize = 10;

   // Always make space for the terminating null character.
   char* words = new char[currentSize+1];
   size_t count = 0;

   char c;
   while(std::cin.get(c))
   {
      if ( count == currentSize )
      {
         // Allocate memory to hold more data.
         size_t newSize = currentSize*2;
         char* temp = new char[newSize+1];

         // Copy the contents from the old location to the new location.
         for ( size_t i = 0; i < currentSize; ++i )
         {
            temp[i] = words[i];
         }

         // Delete the old memory.
         delete [] words;

         // Use the new memory
         words = temp;
         currentSize = newSize;
      }

      words[count] = c;
      count++;
   }

   // Terminate the string with a null character.
   words[count] = '[=10=]';

   std::cout << words << std::endl;

   // Deallocate the memory.
   delete [] words;
}

您需要分配一个任意大小的字符串缓冲区。然后,如果追加时达到最大字符数,则需要使用realloc扩大缓冲区。

为了避免在每个字符处都调用 realloc,这不是最优的,建议采用增长策略,例如在每次分配时将大小加倍。还有更多微调的增长策略,具体取决于平台。

然后,最后,如有必要,您可以使用 realloc trim 缓冲区到附加字节的确切数量。