首页 > 解决方案 > 在 2D 矢量数组中的特定标题下添加数据

问题描述

假设我们有一个数据,例如:

1A
1 
Hi World
2A
2
Hello Bob
Life is Good
3A
0

数据有一个标签1A、2A、3A,这是主标签。在该标签下,它显示该选项卡中的字符串数,即1,2,0,然后是字符串。我们如何在屏幕上显示数据,以便我们分别显示主标签和它下面的字符串?

编码:

vector<string> class_names;
vector<string> data;

    ifstream myfile;
    myfile.open("file.txt");
    string line;
    for (int lineno = 1; getline(myfile, line); lineno++) {
        if (lineno == 1 || lineno == 4 || lineno == 8) {
            class_names.push_back(line); // stores the class names
        }
        else if (lineno != 2 && lineno != 5 && lineno != 9) {
            data.push_back(line);   // stores the data in classes
        }
    }

我在这里所做的是将文件中的数据存储在向量中,它们可以单独打印,但我不能在这个文件中添加另一个类?我们如何将这些数据放在单个向量或 2D 向量中,以便用户可以将数据放入 1A 甚至创建一个新的数据选项卡,如 4A ?那怎么做?

例如,用户需要输入How are you in 1A ,how are you in 1A ,how are you in 1A ?我不打算在代码中提出解决方案,因为我是一个初学者。

标签: c++

解决方案


虽然您可以随心所欲地进行详细说明,但您的基本任务是填充一个对象,该对象存储.tag之后的下一行指定的字符串数量,然后填充一个字符串向量tag。该任务更多的是如何验证每个字符串的读取以及tag与该字符串关联的指定数量的字符串tag。为了协调数据的存储,您只需要一个存储tag字符串向量的对象。一个简单的stuct方法,例如

struct content {
    std::string tag;                    /* storage for tag */
    std::vector<std::string> str;       /* storage for each string */
};

要处理所有数据,您只需声明 astd::vector<content>然后使用临时实例content填充文件中的数据,然后.push_back()在完成对字符串的读取后将临时结构填充到向量中tag

为了让自己清楚您正在为哪个标签读取数据,您将打开文件并读取包含第一行的第一行tag,例如

    ...
    std::string line;                       /* storage to read each line */
    std::vector<content> contents {};       /* vector of content */
    std::ifstream f (argv[1]);              /* open file from 1st argument */

    while (getline (f, line)) {             /* read tag line */
        int nstr = 0;                       /* int for num strings */
        content tmp {};                     /* temp struct to fill */
        tmp.tag = line;                     /* set .tag in temp struct */

将您tag存储在临时结构中,将下一行读入int(或size_t)值(不要忘记忽略行尾以删除'\n'输入流中的左侧):

        if (!(f >> nstr)) {                 /* read no. strings as int */
            std::cerr << "error: invalid format - nstr.\n";
            return 1;
        }   /* ingore to end of line after nstr read as int */
        f.ignore (std::numeric_limits<std::streamsize>::max(), '\n');

将该标记的字符串数存储为int,只需循环读取与该标记关联的字符串的次数,并将它们添加到临时结构中的字符串向量中(不要忘记验证每次读取):

        while (nstr--) {                    /* loop nstr times */
            if (getline (f, line))          /* read line */
                tmp.str.push_back(line);    /* add to strings stored in temp */
            else {  /* early EOF reached */
                std::cerr << "error: early EOF.\n";
                return 1;
            }
        }

在循环并将每个字符串读入临时结构后,只需.push_back()将临时结构放入您的永久存储中即可:

        contents.push_back(tmp);            /* add tmp to contents */
    }

现在你有了content填充向量,你可以以任何你喜欢的方式使用数据。根据您的要求输出字符串tag,您可以使用一对嵌套的基于范围的for循环来很好地格式化输出:

    for (auto& c : contents) {              /* loop over each struct */
        std::cout << "\ntag: " << c.tag << '\n';    /* output tag */
        for (auto& s : c.str)               /* loop over each string */
            std::cout << "  " << s << '\n';         /* output string */
    }

把它放在一个简短的例子中,你可以这样做:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <limits>

struct content {
    std::string tag;                    /* storage for tag */
    std::vector<std::string> str;       /* storage for each string */
};

int main (int argc, char **argv) {

    if (argc < 2) { /* validate 1 argument given for filename */
        std::cerr << "usage: " << argv[0] << " <filename>\n";
        return 1;
    }

    std::string line;                       /* storage to read each line */
    std::vector<content> contents {};       /* vector of content */
    std::ifstream f (argv[1]);              /* open file from 1st argument */

    while (getline (f, line)) {             /* read tag line */
        int nstr = 0;                       /* int for num strings */
        content tmp {};                     /* temp struct to fill */
        tmp.tag = line;                     /* set .tag in temp struct */
        if (!(f >> nstr)) {                 /* read no. strings as int */
            std::cerr << "error: invalid format - nstr.\n";
            return 1;
        }   /* ingore to end of line after nstr read as int */
        f.ignore (std::numeric_limits<std::streamsize>::max(), '\n');

        while (nstr--) {                    /* loop nstr times */
            if (getline (f, line))          /* read line */
                tmp.str.push_back(line);    /* add to strings stored in temp */
            else {  /* early EOF reached */
                std::cerr << "error: early EOF.\n";
                return 1;
            }
        }
        contents.push_back(tmp);            /* add tmp to contents */
    }

    for (auto& c : contents) {              /* loop over each struct */
        std::cout << "\ntag: " << c.tag << '\n';    /* output tag */
        for (auto& s : c.str)               /* loop over each string */
            std::cout << "  " << s << '\n';         /* output string */
    }
}

(您可以重载>>以一次性读取临时结构,但代码本质上是相同的,只是移动到content该重载的成员函数中>>。这留给您)

示例使用/输出

将您的输入文件另存为dat/2darrtags.txt,您将执行以下操作:

$ ./bin/read2darrtags dat/2darrtags.txt

tag: 1A
  Hi World

tag: 2A
  Hello Bob
  Life is Good

tag: 3A

如果您还有其他问题,请仔细查看并告诉我。有不止一种方法可以做到这一点。这只是更直接的程序方法之一,您可以根据需要进行改进。


推荐阅读