简体   繁体   中英

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

in c++ id like to read input into a c-style string one character at a time. how do you do this without first creating a char array with a set size (you don't know how many chars the user will enter). And since you can't resize the array, how is this done? I was thinking something along these lines, but this does not work.

char words[1];
int count = 0;

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

Since you cannot use std::vector , I am assuming you cannot use std::string either. If you can use std::string , you can the solution provide by the answer by @ilia .

Without that, your only option is to:

  1. Use a pointer that points to dynamically allocated memory.
  2. Keep track of the size of the allocated array. If the number of characters to be stored exceeds the current size, increase the array size, allocate new memory, copy the contents from the old memory to new memory, delete old memory, use the new memory.
  3. Delete the allocated memory at the end of the function.

Here's what I suggest:

#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] = '\0';

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

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

You asked for C-style array. Stack or dynamic allocation will not serve you in this case. You need to change the count of the array number in each time you add new element which is not possible automatically. You have to work around and delete and reserve the array each time a new chae is read. So you have to options:

  1. Use std::vector (which was created for this purpose)
  2. Duplicate what is inside std::vector and write it yourself during your code( which seems terrible)

std::vector solution:

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
    }
}

You have two ways, first is to use an zero size array, after each input you delete the array and allocate a new one that is +1 bigger, then store the input. This uses less memory but inefficient. (In C, you can use realloc to improve efficiency)

Second is to use a buffer, for example you store read input in a fixed size array and when it get full, you append the buffer at the end of main array (by deleting and re-allocating).

By the way, you can use std::vector which grows the size of itself automatically and efficiently.

If you're set on using c-style strings then:

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;
}

I would do what Humam Helfawi suggested and use std::vector<char> since you are using C++, it will make your life easier. The implementation above is basically the less elegant version of vector. If you don't know the size before hand then you will have to resize memory.

You need to allocate a string buffer of arbitrary size. Then, if the maximum number of characters is reached upon appending, you need to enlarge the buffer with realloc.

In order to avoid calling realloc at each character, which is not optimal, a growth strategy is recommended, such as doubling the size at each allocation. There are even more fine-tuned growth strategies, which depend on the platform.

Then, at the end, you may use realloc to trim the buffer to the exact number of appended bytes, if necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM