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 时,您都必须解决并删除和保留数组。所以你必须选择:
- 使用
std::vector
(为此目的创建)
- 复制里面的东西 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
,你可以使用.
提供的解决方案
否则,您唯一的选择是:
- 使用指向动态分配内存的指针。
- 跟踪分配数组的大小。如果要存储的字符数超过当前大小,增加数组大小,分配新内存,将内容从旧内存复制到新内存,删除旧内存,使用新内存。
- 删除函数末尾分配的内存。
这是我的建议:
#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 缓冲区到附加字节的确切数量。
在 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 时,您都必须解决并删除和保留数组。所以你必须选择:
- 使用
std::vector
(为此目的创建) - 复制里面的东西 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
,你可以使用
否则,您唯一的选择是:
- 使用指向动态分配内存的指针。
- 跟踪分配数组的大小。如果要存储的字符数超过当前大小,增加数组大小,分配新内存,将内容从旧内存复制到新内存,删除旧内存,使用新内存。
- 删除函数末尾分配的内存。
这是我的建议:
#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 缓冲区到附加字节的确切数量。