如何在C++中读取未知大小的字符串
How to read a string of unknown size in C++
我是新手,无论是编码还是英语。这是我的代码:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int n = 1;
char *a = new char[n], c = getchar();
while ((c != EOF) || (c != '\n'))
{
a[n-1] = c;
c = getchar();
n++;
}
cout << a;
delete[] a;
return 0;
}
我正在学习动态内存分配。问题是输入一个长度未知的字符串。我的思路是逐个字符读取字符串,读到EOF
或\n
时停止。能否请您指出错误?
还有一个问题:有人告诉我 new
选择指定大小的内存块。那么如果没有足够大的块会怎样?
感谢您的帮助!
#include <iostream>
#include <string>
int main() {
std::string line;
// first argument is the stream from whence the line comes.
// will read to newline or EOF
std::getline(std::cin, line);
}
首先,没有必要使用char*
和new char[n]
。您可以使用 std::string
.
那你要问问自己:
- 字符串可以包含空白字符吗?
- 字符串可以跨越多行吗?
- 如果可以跨越多行,跨越多少行?
如果第一个问题的答案是"No",您可以使用:
std::string s;
cin >> s;
如果第一个问题的答案是"Yes",第二个问题的答案是"No",那么可以使用:
std::string s;
getline(cin, s);
如果第二个问题的答案是"Yes",答案就更复杂了。
那么,您还需要寻找更多问题的答案吗?
- 行数是硬编码的吗?
- 如果不是硬编码,程序如何从用户那里得到那个号码?
根据这些问题的答案,您的代码会有所不同。
[I know adhering to best practices and methods available is the "good"
thing to do, but the OP should know why the current code doesn't work
and the other answers here do not seem to be answering that]
首先,您应该为此使用 C++ string
class。
其次,如果您想知道为什么您当前的代码不起作用,那是因为:
while里面的条件是错误的。它说,“如果字符不是 \n
或不是 EOF
,则执行此块”。所以即使你按下 enter(c
是 '\n'
),这个块仍然会执行,因为“c
不是 EOF
”,反之亦然。
您只为 char*
分配了 1 个字节的内存,这显然是不够的。
这应该可以很好地复制您想要的内容,但分配的内存是静态的,并且必须限制字符串。
int main()
{
int n=1;
char *a = new char[100],c=getchar();
while(true)
{
if(c == '\n' || c == EOF){
break;
}
a[n-1]=c;
c=getchar();
n++;
}
cout << a;
delete[] a;
return 0;
}
考虑到您的任务的限制(没有 std::string
、没有 std::vector
、动态内存分配),我将尝试为您提供一个经过修改但可以工作的代码版本。
My idea is read the string word my word and stop when it reach EOF or
\n. Could you please point out the error?
正如 molbdnilo 指出的那样,(c!=EOF) || (c!='\n')
始终为真,因此您的循环将永远不会结束。
正如 mah 所注意到的,您的 a
缓冲区只有 1 个字符长并且您没有检查溢出,此外,您忘记在它的末尾添加空终止符。
你的第二个问题是 new
无法分配足够的内存时会发生什么。它抛出一个异常,您的程序应该捕获该异常来管理这种情况,但您可以做的最好的事情(实际上不是唯一的,也许是最简单的)就是终止您的程序。
这是一个示例,说明如何在存在上述限制的情况下完成您的任务:
#include <iostream>
using namespace std;
int main()
{
const int INITIAL_SIZE = 8;
// The following block of code could rise an exception.
try
{
int n = 0;
char c;
// Allocate some memory to store the null terminated array of chars.
char *a = new char[INITIAL_SIZE];
// what happens if new fails? It throws an exception of type std::bad_alloc
// So you better catch it.
int allocated = INITIAL_SIZE;
// read a charachter from stdin. If EOF exit loop
while( cin.get(c) )
{
// If it's a newline or a carriage return stop.
if( '\n' == c || '\r' == c )
//^ Note that ^^^ putting the literals first helps avoiding common
// error like using "=" instead of "==" in conditions.
break;
// If the array is full, it's time to reallocate it.
if ( n == allocated )
{
// There are better alternatives, of course, but I don't know which library
// you are allowed to use, so I have to assume none.
// Allocate a bigger array. The growing strategy may be different.
allocated += 2 + allocated / 2;
char *b = new char[allocated];
// Copy the old one in the new one (again, you could use std::copy).
for ( int i = 0; i < n; ++i )
{
b[i] = a[i];
}
// Release the memory handled by the old one...
delete[] a;
// but keep using the same pointer. Just remember not to delete 'b'
// so that 'a' always points to allocated memory.
a = b;
}
a[n] = c;
// A new character has been succesfuly added.
++n;
}
// Now, before using a, we have to add the null terminator.
a[n] = '[=10=]';
// Note that a doesn't contain the '\n'.
cout << a << '\n';
// Clean up.
delete[] a;
// Normal program termination.
return 0;
}
// If 'new' fails to allocate memory a std::bad_alloc exception is thrown.
catch ( const exception &e )
{
cout << "Exception caught: " << e.what() << "\nProgram terminated.\n";
return -1;
}
}
我是新手,无论是编码还是英语。这是我的代码:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int n = 1;
char *a = new char[n], c = getchar();
while ((c != EOF) || (c != '\n'))
{
a[n-1] = c;
c = getchar();
n++;
}
cout << a;
delete[] a;
return 0;
}
我正在学习动态内存分配。问题是输入一个长度未知的字符串。我的思路是逐个字符读取字符串,读到EOF
或\n
时停止。能否请您指出错误?
还有一个问题:有人告诉我 new
选择指定大小的内存块。那么如果没有足够大的块会怎样?
感谢您的帮助!
#include <iostream>
#include <string>
int main() {
std::string line;
// first argument is the stream from whence the line comes.
// will read to newline or EOF
std::getline(std::cin, line);
}
首先,没有必要使用char*
和new char[n]
。您可以使用 std::string
.
那你要问问自己:
- 字符串可以包含空白字符吗?
- 字符串可以跨越多行吗?
- 如果可以跨越多行,跨越多少行?
如果第一个问题的答案是"No",您可以使用:
std::string s;
cin >> s;
如果第一个问题的答案是"Yes",第二个问题的答案是"No",那么可以使用:
std::string s;
getline(cin, s);
如果第二个问题的答案是"Yes",答案就更复杂了。
那么,您还需要寻找更多问题的答案吗?
- 行数是硬编码的吗?
- 如果不是硬编码,程序如何从用户那里得到那个号码?
根据这些问题的答案,您的代码会有所不同。
[I know adhering to best practices and methods available is the "good" thing to do, but the OP should know why the current code doesn't work and the other answers here do not seem to be answering that]
首先,您应该为此使用 C++ string
class。
其次,如果您想知道为什么您当前的代码不起作用,那是因为:
while里面的条件是错误的。它说,“如果字符不是
\n
或不是EOF
,则执行此块”。所以即使你按下 enter(c
是'\n'
),这个块仍然会执行,因为“c
不是EOF
”,反之亦然。您只为
char*
分配了 1 个字节的内存,这显然是不够的。
这应该可以很好地复制您想要的内容,但分配的内存是静态的,并且必须限制字符串。
int main()
{
int n=1;
char *a = new char[100],c=getchar();
while(true)
{
if(c == '\n' || c == EOF){
break;
}
a[n-1]=c;
c=getchar();
n++;
}
cout << a;
delete[] a;
return 0;
}
考虑到您的任务的限制(没有 std::string
、没有 std::vector
、动态内存分配),我将尝试为您提供一个经过修改但可以工作的代码版本。
My idea is read the string word my word and stop when it reach EOF or \n. Could you please point out the error?
正如 molbdnilo 指出的那样,(c!=EOF) || (c!='\n')
始终为真,因此您的循环将永远不会结束。
正如 mah 所注意到的,您的 a
缓冲区只有 1 个字符长并且您没有检查溢出,此外,您忘记在它的末尾添加空终止符。
你的第二个问题是 new
无法分配足够的内存时会发生什么。它抛出一个异常,您的程序应该捕获该异常来管理这种情况,但您可以做的最好的事情(实际上不是唯一的,也许是最简单的)就是终止您的程序。
这是一个示例,说明如何在存在上述限制的情况下完成您的任务:
#include <iostream>
using namespace std;
int main()
{
const int INITIAL_SIZE = 8;
// The following block of code could rise an exception.
try
{
int n = 0;
char c;
// Allocate some memory to store the null terminated array of chars.
char *a = new char[INITIAL_SIZE];
// what happens if new fails? It throws an exception of type std::bad_alloc
// So you better catch it.
int allocated = INITIAL_SIZE;
// read a charachter from stdin. If EOF exit loop
while( cin.get(c) )
{
// If it's a newline or a carriage return stop.
if( '\n' == c || '\r' == c )
//^ Note that ^^^ putting the literals first helps avoiding common
// error like using "=" instead of "==" in conditions.
break;
// If the array is full, it's time to reallocate it.
if ( n == allocated )
{
// There are better alternatives, of course, but I don't know which library
// you are allowed to use, so I have to assume none.
// Allocate a bigger array. The growing strategy may be different.
allocated += 2 + allocated / 2;
char *b = new char[allocated];
// Copy the old one in the new one (again, you could use std::copy).
for ( int i = 0; i < n; ++i )
{
b[i] = a[i];
}
// Release the memory handled by the old one...
delete[] a;
// but keep using the same pointer. Just remember not to delete 'b'
// so that 'a' always points to allocated memory.
a = b;
}
a[n] = c;
// A new character has been succesfuly added.
++n;
}
// Now, before using a, we have to add the null terminator.
a[n] = '[=10=]';
// Note that a doesn't contain the '\n'.
cout << a << '\n';
// Clean up.
delete[] a;
// Normal program termination.
return 0;
}
// If 'new' fails to allocate memory a std::bad_alloc exception is thrown.
catch ( const exception &e )
{
cout << "Exception caught: " << e.what() << "\nProgram terminated.\n";
return -1;
}
}