【问题标题】:Storing all vector values in a data type将所有向量值存储在数据类型中
【发布时间】:2021-11-27 21:22:54
【问题描述】:

我声明了一个包含 n 个整数的向量。

vector <int> tostore[n];

我想将向量中的所有数字以其下标的格式存储在一个字符串中,例如 12345..n

例子:

vector <int> store_vec{1,2,3,4,5};
int store_str;     //to store the digits in order from vector store_vec
cout<<store_str;

期望的输出:

12345

如何在不打印的情况下将其存储在 store_str 中?

【问题讨论】:

  • 您真的需要将它们放在int 中吗?这只会让你最多有 8-9 个数字。
  • 一切正常。我只想按顺序存储它们
  • 向量中是否只有一位数?
  • 是的。总是个位数
  • 语法警告:vector &lt;int&gt; tostore[n]; 不是包含n整数的向量,它实际上创建了一个n空向量数组.

标签: c++ vector


【解决方案1】:

一种方法是每次迭代乘以10

int result = 0;

for (auto it : tostore)
{
    result = result * 10 + it;
}

如 cmets 中所述,更可靠的方法是连接到实际字符串,或者至少使用 64 位整数。

【讨论】:

  • 我不知道为什么我没有想到这一点。谢谢
【解决方案2】:

与其使用整数(如果它是 32 位宽将只能存储 8-9 位数字),不如构建一个包含所有元素组合的字符串,例如

vector <int> store_vec{1,2,3,4,5};
std::string merged;
merged.reserve(store_vec.size());
for (auto num : store_vec)
    merged += '0' + num;
// now merged is "12345"

【讨论】:

  • 我唯一的建议是,由于我们知道我们只存储 1 位数字值,因此向量 store_vec 可以是 int8_t 数据类型的向量,用于可能更紧凑的数据。
【解决方案3】:

由于您知道tostore 中的每个值都只有一个数字,因此您可以使用int_8uint8_t 数据类型来存储这些值。这样,您仍然可以对向量内的值执行算术运算(只要算术结果分别落在-128 to 1270 to 255 的范围内,请参阅integer types 了解更多详细信息)。这些数据类型的优点是只有一个字节长,从而使您的向量可能被更密集地打包并更快地遍历。然后,您可以使用std::cout &lt;&lt; unsigned(tostore[n]) 将整数转换为字符以进行显示。整个事情看起来像这样

#include <iostream>
#include <type_traits>
#include <vector>

int main()
{
    std::vector<uint8_t> tostore;
    tostore.reserve(32);

    for(int i = 0; i < 32; ++i) {
        tostore.push_back(i % 10);
    }

    for(uint i = 0; i < tostore.size(); ++i) {
        std::cout << unsigned(tostore[i]);
    }
}

或者,如果您知道您的数字将永远是正数,它会打开一个全新的可能性范围。将整数转换为字符列表时,程序需要将整数分解为其单独的数字,然后将 48 添加到该数字值以找到其等效的 ascii 字符代码(有关更多详细信息,请参阅asciiTable)。如果您计划经常显示这些字符或仅对数据执行一些算术运算,那么将整数拆分为其基数 10 位的过程可能过于繁琐(由您决定)。在这种情况下,您可以创建一个struct,它将整数的值存储为char 数据类型,但对数据执行算术运算,就好像它是一个整数一样。这样,在打印值时,不需要执行任何操作来正确格式化数据,并且为算术运算格式化数据需要执行的唯一操作是简单的 48 减法,这非常快。这样的结构可能看起来像这样:

#include <iostream>
#include <type_traits>
#include <vector>

struct notANumber {
    char data;

    notANumber() {}

    notANumber(const int& a) : data(a + 48) {}

    notANumber(const char& a) : data(a) {}

    notANumber operator+(const notANumber& b) {
        notANumber c;
        c.data = b.data + c.data - 48;
        return c;
    }

    notANumber operator-(const notANumber& b) {
        notANumber c;
        c.data = b.data - c.data + 48;
        return c;
    }

    notANumber operator*(const notANumber& b) {
        notANumber c;
        c.data = (b.data - 48) * (c.data - 48) + 48;
        return c;
    }

    notANumber operator/(const notANumber& b) {
        notANumber c;
        c.data = (b.data - 48) / (c.data - 48) + 48;
        return c;
    }
};

int operator+(const int& a, const notANumber& b) {
    int c;
    c = a + b.data - 48;
    return c;
}

int operator-(const int& a, const notANumber& b) {
    int c;
    c = a - b.data + 48;
    return c;
}

int operator*(const int& a, const notANumber& b) {
    int c;
    c = a * (b.data - 48);
    return c;
}

int operator/(const int& a, const notANumber& b) {
    int c;
    c = a / (b.data - 48);
    return c;
}



int main()
{
    std::vector<notANumber> tostore;
    tostore.reserve(32);

    for(int i = 0; i < 32; ++i) {
        tostore.push_back(i % 10);
    }

    std::cout.write(reinterpret_cast<char*>(tostore.data()), tostore.size());
}

现在这可能不是您想要的,但我希望它确实展示了编程的一个重要方面,即“您对正在使用的数据了解得越多,您就越能优化程序”所以确保您对正在使用的数据范围以及最常使用这些数据进行哪些操作(例如算术或打印)以及这些操作的成本有很好的了解。

【讨论】:

    【解决方案4】:

    由于您确认 store_vec 仅包含一位数字,因此执行此操作的简单方法是:

    std::vector<uint8_t> store_vec = {1,2,3,4,5};
    std::string str = std::accumulate(store_vec.begin(), store_vec.end(), std::string{}, 
            [](const std::string& res, uint8_t num){ return res + char('0' + num); });
    int resnum = atoi(str.c_str());
    

    或者基本上使用累加产生的 str,因为它已经代表了序列。

    【讨论】:

      猜你喜欢
      • 2015-05-16
      • 2012-03-18
      • 2016-01-30
      • 2021-11-09
      • 2012-12-15
      • 2015-06-04
      • 1970-01-01
      • 2020-09-29
      • 2018-09-23
      相关资源
      最近更新 更多