【问题标题】:Reading in a file that has strings and ints in c++在 C++ 中读取具有字符串和整数的文件
【发布时间】:2021-12-31 14:29:58
【问题描述】:

所以我有一个我想读入的示例文件,看起来像:

data 1
5
data 2
0
9
6
6
1
data 3
7
3
2

我基本上想将这些中的每一个分配给我在结构中的变量,例如。我的结构看起来像:

struct sample_struct

{ int data1; 

double* data2; 

double* data3; 

};

我该如何回答这个问题?

如果我在每个字符串标题后面都有整数的样本数,我想我可以做到,但像这样我不知道。请帮忙。

【问题讨论】:

  • 你考虑过std::fstream吗?这是一种非常常见的文件输入类型。如果您已经计划使用std::fstream,请edit 您的问题更多地关注您的确切问题。问题“我该如何处理?”非常开放。
  • 我会摆脱指针。请改用std::vector<int>,因为数据似乎是未知数量的整数。
  • 确实,考虑不使用指针。 “原始指针”和“编码新手”是危险的组合。
  • 这个问题(虽然文件格式略有不同)应该有助于读取未知的整数数量:https://stackoverflow.com/questions/19602407/read-integers-from-a-file-into-a-vector-in-c/19602428 奇怪的是,您的问题和链接要求读取整数,但出于某种原因使用 double。跨度>

标签: c++ file struct


【解决方案1】:

你必须解决 2 个问题。

  1. 动态内存管理。
  2. 检测我们在哪里、在哪个部分以及存储数据的位置。

数字 1 通常在 C++ 中用std::vector 解决。 C++ 中不使用所拥有内存或 C 样式数组的原始指针。

如果您不想或不允许使用std::vetor,则需要手工制作一些动态数组。我给你做了一个例子。

对于第二部分,我们可以简单地将字母数字字符串作为源文件不同部分的分隔符。因此,如果我们看到一个字母字符,我们会转到一个新部分,然后将数据存储在适当的结构成员中。

C++ 中的输入和输出通常使用提取器>> 和插入器<< 运算符完成。这允许读取和写入任何类型的流。而且,在 C++ 中,我们经常使用面向对象的编程。在这里,数据和方法被打包在一个类/结构中。只有类/结构应该知道如何读取和写入其数据。

基于以上思路,我们可以提出以下解决方案:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cctype>

// Ultra simle dynamic array
struct DynamicDoubleArray {

    // Constructor and Destructor
    DynamicDoubleArray() { values = new double[capacity]; }; //  Allocate default memory
    ~DynamicDoubleArray() { delete[] values; };              // Release previously allocated memory

    // Data
    double* values{};                                        // Here we store the values. This is a dynamic array
    int numberOfElements{};                                  // Number of elements currently existing in dynamic array
    int capacity{ 2 };                                       // Number of elements that could be stored in the dynamic array

    void push_back(double v) {                               // Add a new aelement to our dynamic array
        if (numberOfElements >= capacity) {                  // Check, if we have enough capacity to store the new element
            capacity *= 2;                                   // No, we have not. We need more capacity
            double* temp = new double[capacity];             // Get new, bigger memory
            for (int k = 0; k < numberOfElements; ++k)       // Copy old data to new bigger memory
                temp[k] = values[k];
            delete[] values;                                 // Delete old data
            values = temp;                                   // And assign new temp  data to our original pointer
        }
        values[numberOfElements++] = v;                      // Store new data and increment element counter
    }
};

// Our sample struct
struct SampleStruct {

    // Data part
    int data1{};
    DynamicDoubleArray data2{};
    DynamicDoubleArray data3{};

    // Help functions. We overwrite the inserter and extractor operator 

    // Extract elements from whatever stream
    friend std::istream& operator >> (std::istream& is, SampleStruct& s) {
        std::string line{};                                  // Temporaray storage to hold a complete line   
        int section = 0;                                     // Section. Where to store the data
        while (std::getline(is, line)) {
            if (std::isalpha(line[0])) {                     // If we see an alpha character then we are in the next section
                ++section;                                   // Now, we will use the next section
                continue;
            }
            switch (section) {                               // Depending on in which section we are
            case 1:
                s.data1 = std::stoi(line);                   // Section 1 --> Store int data
                break;
            case 2:
                s.data2.push_back(std::stod(line));          // Section 2 --> Add/Store double data 2
                break;
            case 3:
                s.data3.push_back(std::stod(line));          // Section 3 --> Add/Store double data 2
                break;
            default: 
                std::cerr << "\nError: internal mode error\n";
                break;
            }
        }
        return is;
    }
    // Simple output
    friend std::ostream& operator << (std::ostream& os, const SampleStruct& s) {
        os << "\nData 1: " << s.data1 << "\nData 2: ";
        for (int k = 0; k < s.data2.numberOfElements; ++k)
            os << s.data2.values[k] << ' ';
        os << "\nData 3: ";
        for (int k = 0; k < s.data3.numberOfElements; ++k)
            os << s.data2.values[3] << ' ';
        return os;
    }
};

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多