C++ 一次读入一个字符的 C 样式字符串

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

本文关键字:字符 样式 字符串 一个 一次 C++      更新时间:2023-10-16

在 C++ id 中,喜欢将输入读取到 C 样式字符串中,一次一个字符。 如何在不首先创建具有设定大小的 char 数组的情况下执行此操作(您不知道用户将输入多少个字符)。既然您无法调整数组的大小,那么如何做到这一点?我在想这些事情,但这行不通。

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

既然你不能使用std::vector,我假设你也不能使用std::string。如果可以使用std::string,则可以通过@ilia提供的答案提供解决方案。

如果没有它,您唯一的选择是:

  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] = '';
   std::cout << words << std::endl;
   // Deallocate the memory.
   delete [] words;
}

你要求 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);
}
#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中,可以使用realloc来提高效率)

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

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

如果您设置为使用 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版本。如果您事先不知道大小,那么您将不得不调整内存大小。

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

为了避免在每个字符上调用 realloc(这不是最佳选择),建议使用增长策略,例如在每次分配时将大小加倍。还有更多微调的增长战略,这取决于平台。

然后,在最后,如有必要,您可以使用 realloc 将缓冲区修剪为附加字节的确切数量。