【问题标题】:Reading constant number of characters in C++在 C++ 中读取常量字符数
【发布时间】:2011-12-02 11:38:56
【问题描述】:

如果字符串不超过 20 个字符并且在 C++ 中可以包含空格,您将如何读取它?例如我有这种文件:

3
Namama               4 5 12
Cool                 4 2 34
Not So Cool          4 2 45

我想用最基本的方式来写它。在这种情况下,我宁愿只使用 C++(没有 C 的东西)。这意味着我想将它存储在 std::string 中。

我可以使用 istream::getistream::getline 但我必须避免使用换行符。这是有问题的(我正在编写的代码将向初学者展示)。

你对这个问题有什么解决方案?

编辑:

按照要求,我将告诉您我尝试过的方法,但我认为这不会有任何好处。我不是 C++ 初学者,通常我会使用诸如 istream::get 和 char 数组之类的东西,但对于某些人来说,删除换行符可能看起来太技术了。

所以... 使用 istream::operator>> 读取 char 数组或 std::string 失败,因为当他们看到空格字符时它会停止读取(而我可能要读几个字)。这意味着以下代码失败:

char name[21];
std::cin >> name;

或者...

std::string name;
std::cin >> name;

另一件事是换行符因系统而异,实际上 Windows 默认使用其中两个,我尝试在 Windows 上使用 istream::ignore 和 2 作为参数,那是忽略新行的唯一方法,我得出的结论是,这是因为 Windows 使用两个字符作为新行标记。这意味着它不能在 Linux 上运行,而且它必须更复杂......再次 - 对初学者不利。

【问题讨论】:

  • 你试过什么?请显示您目前拥有的代码,以便人们可以帮助修复/改进它的特定部分。
  • “新行字符因系统而异” - 解决方法是以字符模式而不是二进制模式打开文件。然后无论本地换行序列是什么,它都会在读取时转换为\n
  • 您只需要初始字符串,还是要解析整行,包括数字?如果您想要后者,我会采用整体方法。
  • “换行符因系统而异”——也许它们在存储在磁盘上时会有所不同,但在您的 C++ 程序中并没有区别。 '\n'总是代表一行的结束,其他什么都没有。
  • @SteveJessop 和 Rob 有两种 istream 函数 - 格式化和未格式化。他们的行为不同。

标签: c++ string spaces istream


【解决方案1】:

如果您想准确地阅读 20 个字符,

for(int i=0; i<3; ++i) {
    std::string result;
    int one, two, three;

    result.resize(20);
    if (!std::cin.read(&result[0], 20)) throw std::runtime_error("reading buffer failed!");

    if (!std::cin >> one >> two >> three) throw std::runtime_error("reading numbers failed!");
    if (!std::cin.ignore(1000, '\n')) throw std::runtime_error("ignore failed!");
}

如果你不想要正好 20 个字符,你怎么知道你什么时候到达了字符串的末尾?

【讨论】:

  • 还没有使用过 iostream::read 但参考资料说它是一个未格式化的输入函数,这是否意味着它将读取最后一次读取后留下的换行符?我仍然必须使用 istream::ignore。无论如何,会在几分钟内尝试
  • @Valdo:我把它改成了 20 读,有一阵子和.get() 混淆了。这将留下 20 个字符之后的任何内容,包括换行符。
  • 但它也读取了新行。实际上它会导致一些我不理解但试图弄清楚的非常奇怪的行为。我一直认为这个函数只用于二进制读取(记得使用它)但显然不是。
  • @Valdo:它应该准确读取 20 个字节,包括空格和换行符。有什么奇怪的行为?
  • @Mooning Duck 好吧,读取输入时会导致错误。在读取第一行后,它无法读取以下行...试图找出问题所在...
【解决方案2】:

实现此目的的一种方法是使用 istream::read 进入足够大小的临时缓冲区,然后使用该缓冲区初始化 std::string。

char name[21];
std::cin.read(name, 20);
std::string nameString(name); // If you want it in a std::string

这正好读取 20 个字符、换行符和所有内容。如果是为了锻炼,那么这至少非常简单。如果您有时需要少于 20 个字符,则可以通过 std::istream::unget 或等效项来确定读取了多少额外字符并返回 get 指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多