I'm trying to write a function that takes a user input of digits, eg 830948234681764 and creates a vector with as many values as the full length of that input, and creates one element for every digit:
Input: 830948234681764
etc
I've had issues using maths to extract the individual digits because the sequence has to be potentially several thousand characters long.
Using a string, however, means that each element of the vector becomes that digits's ascii code, and I'm not sure how to convert them to the original values.
Here's the meat of the code:
string s = "12345"
int size = s.length();
std::vector <double> v (size);
for (int i = 0; i < size; i++) {
v[i] = s[i];
}
Whether it's converting the array from ascii to int values afterwards, or taking each character and converting it to an int before injecting it into the vector, I'm new to C++ and am a bit stuck figuring this one out. Any help would be much appreciated!
Cheers
One way to do it is the push the successive digits into an initially empty vector.
std::string s = "07563157289";
std::vector<int> v;
for (auto c : s) { // for each char in s
v.push_back(c - '0');
}
An alternative is to first create the vector with the right size, then use a loop over indices to fill the vector
unsigned size = s.size();
std::vector<int> v(size);
for (unsigned i=0; i<size; ++i) { // for i in {0,1, ..size-1}
v[i] = s[i] - '0';
}
It is slightly more efficient with huge strings, because it avoids the costs of (hidden) reallocations of the underlying array.
EDIT : I compiled several versions (with g++ --std=c++11 -Os -S) to have a look on the code produced by the compiler.
The winner is
std::vector<int> digits_transform_alloc(const std::string &s)
{
std::vector<int> v(s.size());
std::transform(s.begin(), s.end(),
v.begin(),
[](char ch) { return ch - '0';});
return v;
}
where the vector is first allocated to the right size, then filled with values. The loop is 5 machine instructions only.
.L61:
cmpq %r13, %rax
je .L66
movl $0, (%r12,%rax,4)
incq %rax
jmp .L61
And the same code is generated for the "declare vector with size + for loop with index" version (1st ex-aequo).
Using transform+back_inserter is 2x-longer and involves a costly call to an auxiliary procedure (about 50 instructions) for emplace_back
.L48:
cmpq %r12, %rbp
je .L54
movsbl 0(%rbp), %edx
leaq 12(%rsp), %rsi
movq %rbx, %rdi
subl $48, %edx
movl %edx, 12(%rsp)
.LEHB2:
call _ZNSt6vectorIiSaIiEE12emplace_backIIiEEEvDpOT_
.LEHE2:
incq %rbp
jmp .L48
You can avoid the loops and use std::transform
.
#include <algorithm>
#include <vector>
#include <iterator>
#include <string>
//...
std::string InputSequence;
std::vector <double> MainVector;
//...
std::transform(InputSequence.begin(), InputSequence.end(),
std::back_inserter(MainVector), [](char ch) { return ch - '0'; });
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.