gpt4 book ai didi

c++ - 输入两个不专门用于尺寸的矩阵

转载 作者:行者123 更新时间:2023-12-02 10:22:55 25 4
gpt4 key购买 nike

我需要输入两个大小不固定的矩阵,使用空白行来声明输入每个矩阵的结尾。

例如,输入:

1 2
3 4
(blank row here, end of input matrix 1)
5 6 7
8 9 10
(blank row here, end of input matrix 2)

将获得2 * 2矩阵和2 * 3矩阵。

我当前的想法是构建一个足够大的矩阵(例如1000 * 1000),然后设置循环并使用 cin输入每个元素(该代码仅显示了我如何输入矩阵1):
int matx1[1000][1000];
for (i = 0;i < 1000;i++)
{
for (j = 0;j < 1000;j++)
{
temp = getchar();
if (temp == '\n')
{
mat1.col = j;
break;
}
else
{
putchar(temp);
}
cin>>matx1[i][j];
}
temp = getchar();
if (temp == '\n')
{
mat1.row = i;
break;
}
else
{
putchar(temp);
}
}

当我在Xcode上运行此命令时,会发生错误,每次按 putchar()时, Enter函数都会通过打出一个数字来中断我在终端中的输入,输入结果会困惑。

我还尝试了以下代码,以避免使用 putchar():
for (i = 0; i < 1000; i++)
{
temp = getchar();
if (temp == '\n')
{
break;
}
else
{
matx1[i][0] = temp;
for (j = 1; j < 1000; j++)
{
cin >> matx1[i][j];
if (getchar() == '\n')
{
break;
}
}
}
}

尽管如此,仍然存在严重的问题。 temp变量存储 char,即使我使用ASCII将其转换为 int,它也仅在每行的第一个元素小于10时有效,否则每行的第一个元素的数据将被错误地存储。

因此,主要问题是:

一次按 Enter后如何切换到新行以输入相同的矩阵,再按 Enter后如何切换至输入下一个矩阵?

或说:如何在不干扰原始输入流的情况下获取 '\n'事件?

最佳答案

为了解决眼前的问题,有一种或多或少的标准方法。您要读取csv数据。

就您而言,这有点困难,因为您的csv数据确实有特殊格式。因此,首先是一个“”分隔列表,然后是2个条目之间的空行。

现在,该怎么办呢? C++是一种具有许多现有算法的面向对象语言。您可以创建定义Proxy类并覆盖提取器运算符。代理类,尤其是提取器,将完成所有工作。

如前所述,提取器(也是问题的核心)更加棘手。如何才能做到这一点?

在提取器中,我们将首先使用std::istream函数从std::getline中读取整行。在一行之后,我们看到一个std::string,其中包含用空格分隔的“数据字段”。需要分割std::string并存储“数据字段”-内容。

拆分字符串的过程也称为标记化。 “数据字段”的内容也称为“ token ”。为此,C++具有一个标准函数:std::sregex_token_iterator

并且因为我们已经为此目的设计了一些东西,所以我们应该使用它。

这个东西是一个迭代器。用于遍历字符串,因此使用sregex。开始部分定义了我们将在什么输入范围上进行操作,然后在输入字符串中有一个std::regex表示应该匹配的内容或不应该匹配的内容。匹配策略的类型由last参数给出。

1 --> give me the stuff that I defined in the regex and
-1 --> give me that what is NOT matched based on the regex.

我们可以使用此迭代器将 token 存储在 std::vector中。 std::vector具有范围构造器,该构造器接受2个迭代器一个参数,并将第一个迭代器和第二个迭代器之间的数据复制到 std::vector

该声明
std::vector token(std::sregex_token_iterator(line.begin(), line.end(), separator, -1), {});

定义类型为 std::vector<std::string>的变量“ token ”,拆分 std::string并将 token 放入 std::vector中。对于您的情况,我们将使用 std::transform将您的字符串更改为整数。

很简单的。

下一步。我们想从文件中读取。文件内容也包含某些相同的数据。相同的数据是行。

如上所述,我们可以迭代相似的数据。是文件输入还是其他。为此,C++具有std::istream_iterator。这是一个模板,作为模板参数,它获取应读取的数据类型,作为构造函数参数,它获取对输入流的引用。不管输入流是std::cin还是std::ifstream或std::istringstream。各种流的行为都相同。

而且由于没有SO的文件,因此我(在下面的示例中)使用std::istringstream来存储输入的csv文件。但是,当然可以通过定义std::ifstream csvFile(filename)来打开文件。没问题。

现在,我们可以读取完整的csv文件并将其拆分为 token 并获取所有数据,只需定义一个新变量并再次使用range构造函数即可。
Matrix matrix1( std::istream_iterator<ColumnProxy>(testCsv), {} );

这个非常简单的单行代码将读取完整的csv文件并完成所有预期的工作。

请注意:我正在使用C++ 17,并且可以在不使用模板参数的情况下定义 std::vector。编译器可以从给定的函数参数中推导出自变量。此功能称为CTAD(“类模板参数推导”)。

此外,您可以看到我没有明确使用“end()”迭代器。

该迭代器将从空括号括起来的初始值设定项列表中以正确的类型构造,因为由于std::vector构造函数要求与第一个参数的类型相同,因此可以推导该迭代器。

Ì希望我能回答您的基本问题。请参见下面完整的C++示例:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <regex>
#include <algorithm>

std::istringstream testCsv{ R"(1 2
3 4

5 6 7
8 9 10

)" };


// Define Alias for easier Reading
//using Columns = std::vector<std::string>;
using Columns = std::vector<int>;
using Matrix = std::vector<Columns>;
// The delimiter
const std::regex re(" ");

// Proxy for the input Iterator
struct ColumnProxy {
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, ColumnProxy& cp) {

// Read a line
cp.columns.clear();
if (std::string line; std::getline(is, line)) {

if (!line.empty()) {
// Split values and copy into resulting vector
std::transform(std::sregex_token_iterator(line.begin(), line.end(), re, -1),
std::sregex_token_iterator(),
std::back_inserter(cp.columns),
[](const std::string & s) {return std::stoi(s); });
}
else {
// Notify the caller. End of matrix
is.setstate(std::ios::eofbit | std::ios::failbit);
}
}
return is;
}

// Type cast operator overload. Cast the type 'Columns' to std::vector<std::string>
operator Columns() const { return columns; }
protected:
// Temporary to hold the read vector
Columns columns{};
};



int main()
{
// Define variable matrix with its range constructor. Read complete CSV in this statement, So, one liner
Matrix matrix1( std::istream_iterator<ColumnProxy>(testCsv), {} );

// Reset failbit and eofbit
testCsv.clear();

// Read 2nd matrix
Matrix matrix2(std::istream_iterator<ColumnProxy>(testCsv), {});

return 0;

}


再次:
可惜没有人读过这个。 。 。

关于c++ - 输入两个不专门用于尺寸的矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59305404/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com