I want to copy a 64-bit member variable into a vector byte by byte.
Please avoid telling me to use bit operation to extract each byte and then copy them into vector.
I want to do this by one line.
I use memcpy and copy methods, but both of them failed.
Here is the sample code:
#include <iostream>
#include <vector>
#include <cstdint>
#include <cstring>
using namespace std;
class A {
public:
A()
: eight_bytes_data(0x1234567812345678) {
}
void Test() {
vector<uint8_t> data_out;
data_out.reserve(8);
memcpy(data_out.data(),
&eight_bytes_data,
8);
cerr << "[Test]" << data_out.size() << endl;
}
void Test2() {
vector<uint8_t> data_out;
data_out.reserve(8);
copy(&eight_bytes_data,
(&eight_bytes_data) + 8,
back_inserter(data_out));
cerr << "[Test2]" << data_out.size() << endl;
for (auto value : data_out) {
cerr << hex << value << endl;
}
}
private:
uint64_t eight_bytes_data;
};
int main() {
A a;
a.Test();
a.Test2();
return 0;
}
As the others already showed where you were getting wrong, there is a one line solution that is dangeurous.
First you need to make sure that you vector has enough size to receive 8 bytes. Something like this:
data_out.resize(8);
The you can do a reinterpret_cast to force your compiler to interpret those 8 bytes from the vector to be seen as an unique type of 8 bytes, and do the copy
*(reinterpret_cast<uint64_t*>(data_out.data())) = eight_bytes_data;
I can't figure out all the possibilities of something going wrong. So use at your own risk.
If you want to work with the bytes of another type structure, you could use a char* to manipulate each byte:
void Test3()
{
vector<uint8_t> data_out;
char* pbyte = (char*)&eight_bytes_data;
for(int i = 0; i < sizeof(eight_bytes_data); ++i)
{
data_out.push_back(pbyte[i]);
}
cerr << "[Test]" << data_out.size() << endl;
}
Unfortunately, you requested a one-line-solution, which I don't think is viable.
If you are interested in more generic version:
namespace detail
{
template<typename Byte, typename T>
struct Impl
{
static std::vector<Byte> impl(const T& data)
{
std::vector<Byte> bytes;
bytes.resize(sizeof(T)/sizeof(Byte));
*(T*)bytes.data() = data;
return bytes;
}
};
template<typename T>
struct Impl<bool, T>
{
static std::vector<bool> impl(const T& data)
{
std::bitset<sizeof(T)*8> bits(data);
std::string string = bits.to_string();
std::vector<bool> vector;
for(const auto& x : string)
vector.push_back(x - '0');
return vector;
}
};
}
template<typename Byte = uint8_t,
typename T>
std::vector<Byte> data_to_bytes(const T& data)
{
return detail::Impl<Byte,T>::impl(data);
}
int main()
{
uint64_t test = 0x1111222233334444ull;
for(auto x : data_to_bytes<bool>(test))
std::cout << std::hex << uintmax_t(x) << " ";
std::cout << std::endl << std::endl;
for(auto x : data_to_bytes(test))
std::cout << std::hex << uintmax_t(x) << " ";
std::cout << std::endl << std::endl;
for(auto x : data_to_bytes<uint16_t>(test))
std::cout << std::hex << uintmax_t(x) << " ";
std::cout << std::endl << std::endl;
for(auto x : data_to_bytes<uint32_t>(test))
std::cout << std::hex << uintmax_t(x) << " ";
std::cout << std::endl << std::endl;
for(auto x : data_to_bytes<uint64_t>(test))
std::cout << std::hex << uintmax_t(x) << " ";
std::cout << std::endl << std::endl;
}
Output:
0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1
0 0 0 1 0 0 0 1 0 0 0 1 0 0
44 44 33 33 22 22 11 11
4444 3333 2222 1111
33334444 11112222
1111222233334444
Related
I need to insert for every element of vector it's opposite.
#include <iostream>
#include <vector>
int main() {
std::vector < int > vek {1,2,3};
std::cout << vek[0] << " " << vek[1] << " " << vek[2] << std::endl;
for (int i = 0; i < 3; i++) {
std::cout << i << " " << vek[i] << std::endl;
vek.insert(vek.begin() + i + 1, -vek[i]);
}
std::cout << std::endl;
for (int i: vek) std::cout << i << " ";
return 0;
}
OUTPUT:
1 2 3
0 1 // it should be 0 1 (because vek[0]=1)
1 -1 // it should be 1 2 (because vek[1]=2)
2 1 // it should be 2 3 (because vek[2]=3)
1 -1 1 -1 2 3 // it should be 1 -1 2 -2 3 -3
Could you explain me why function insert doesn't insert the correct value of vector? What is happening here?
Note: Auxiliary vectors (and other data types) are not allowed
During the for loop, you are modifying the vector:
After the first iteration which inserts -1, the vector becomes [1, -1, 2, 3]. Therefore, vec[1] becomes -1 rather than 2. The index of 2 becomes 2. And after inserting -2 into the vector, the index of the original value 3 becomes 4.
In the for loop condition, you need to add index i by 2, instead of 1:
#include <iostream>
#include <vector>
int main() {
std::vector < int > vek {1,2,3};
std::cout << vek[0] << " " << vek[1] << " " << vek[2] << std::endl;
for (int i = 0; i < 3 * 2; i+=2) {
std::cout << i << " " << vek[i] << std::endl;
vek.insert(vek.begin() + i + 1, -vek[i]);
}
std::cout << std::endl;
for (int i: vek) std::cout << i << " ";
return 0;
}
#include <iostream>
#include <stdio.h>
using namespace std;
struct Table{
char fullname [100];
int group;
int firstMarks[5];
int secondMarks[5];
};
void ReadTable (Table *&data, int N);
void ShowTable (Table *data, int N);
int main() {
int N = 5;
Table *data = new Table[N]{
{},
{},
{},
{},
{}
};
ReadTable(data, N);
ShowTable(data, N);
}
void ReadTable (Table *&data, int N){
FILE *fl = fopen("table.txt","r");
if (!fl) {
cout << "Помилка";
exit(1);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
fscanf(fl, "%[^|] | %d | %d %d %d %d %d | %d %d %d %d %d ", &data[i].fullname, &data[i].group,
&data[i].firstMarks[j], &data[i].firstMarks[j], &data[i].firstMarks[j], &data[i].firstMarks[j], &data[i].firstMarks[j],
&data[i].secondMarks[j], &data[i].secondMarks[j], &data[i].secondMarks[j], &data[i].secondMarks[j], &data[i].secondMarks[j]);
}
fscanf(fl, "\n");
}
fclose(fl);
}
void ShowTable (Table *data, int N){
for (int i = 0; i < N; i++) {
cout << data[i].fullname << " ";
cout << " | ";
cout << data[i].group << " ";
cout << " | ";
for (int j = 0; j < N; j++) {
cout << data[i].firstMarks[j] << " ";
}
cout << " | ";
for (int j = 0; j < N; j++) {
cout << data[i].secondMarks[j] << " ";
}
cout << endl;
}
}
file table.txt:
Новикова Аделина Максимовна | 1151 | 5 2 3 1 2 | 1 2 1 3 2
Воронина Анна Леоновна | 2151 | 2 4 3 2 1 | 5 4 5 5 4
Медведева Елена Михайловна | 4452 | 4 2 1 3 4 | 2 4 5 2 1
Зайцев Пётр Миронович | 1148 | 2 3 4 5 1 | 5 2 1 5 5
Кочергин Алексей Семёнович | 3252 | 4 4 3 4 5 | 2 1 3 4 2
Console output:
Кочергин Алексей Семёнович | 3252 | 2 1 4 1 5 | 2 4 1 5 2
| 0 | 0 0 0 0 0 | 0 0 0 0 0
| 0 | 0 0 0 0 0 | 0 0 0 0 0
| 0 | 0 0 0 0 0 | 0 0 0 0 0
| 0 | 0 0 0 0 0 | 0 0 0 0 0
Hi all, there is a table, one row of the table corresponds to one student and contains the following information: student's name, group number, exam grades for the first semester, exam grades for the second semester.
How do I read the information from the file into my structure variables? My attempts are unsuccessful, hope for your help!
C++ is an old, mutating language. Thus, it is hard for new users to discern, which language features belong to which state of mutation of the language.
First, you can do everything with <iostream>. Mixing in <stdio> just complicates matters, IMHO.
Second, you declare your Table struct (naming! it is one RECORD in a table, only) in C style (very old mutation) and you could make good use of newer C++ features. Assuming, of course, you do not sit on an ancient tool chain like BorlandC++ 6.0 or something (which would be your first mistake).
Now, with <iostream>, solving such tasks is always following the same pattern, repeatedly:
For input from a stream to a type, write yourself an overloaded operator>>.
For output to a stream for a type, write yourself an overloaded operator<<.
A further complication of your task is, that you use kyrillic names (utf8 file encoding?!). This can be a pitfall, but sometimes, as long as you do not try to dissect the name string, you get away with ignoring this.
See below a modernized (in terms of C++ mutation progress) version of your code, which, at least worked on my machine after copy and pasting your data into emacs and saving it.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <array>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cctype>
#include <locale>
using MarksArray = std::array<int,5>;
struct Data {
std::string fullname;
int group;
MarksArray firstMarks;
MarksArray secondMarks;
};
using DataVector = std::vector<Data>;
// trim functions taken from:
// https://stackoverflow.com/a/217605/2225104
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(),
s.end(),
[](unsigned char ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(),
s.rend(),
[](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
std::istream& operator>> (std::istream& stream, Data& data) {
bool success = true;
auto verify = [&success](const char* step) {
if (!success) {
std::cerr
<< "reading " << step << " failed!" << std::endl;
throw std::runtime_error(step);
}
};
success = success && std::getline(stream, data.fullname, '|');
verify("fullname");
trim(data.fullname);
std::string temp;
success = success && std::getline(stream, temp, '|');
verify("group");
data.group = std::stoi(temp);
success = success && std::getline(stream, temp, '|');
verify("firstMarks");
std::istringstream ss1(temp);
for (size_t i = 0; i < data.firstMarks.size(); i++) {
ss1 >> data.firstMarks[i];
}
success = success && std::getline(stream, temp);
verify("secondMarks");
std::istringstream ss2(temp);
for (size_t i = 0; i < data.secondMarks.size(); i++) {
ss2 >> data.secondMarks[i];
}
return stream;
}
std::ostream& operator<< (std::ostream& stream,
const MarksArray& data) {
bool first = true;
for (const auto& x : data) {
if (first) {
stream << x;
first = false;
} else
stream << " " << x;
}
return stream;
}
std::ostream& operator<< (std::ostream& stream, const Data& data) {
stream << data.fullname << " | "
<< data.group << " | "
<< data.firstMarks << " | "
<< data.secondMarks << std::endl;
return stream;
}
template <class T>
std::ostream& operator<< (std::ostream& stream,
const std::vector<T> & data) {
for (const auto &x : data) {
stream << x;
}
return stream;
}
DataVector ReadTable(const std::string& inPath) {
DataVector result;
std::ifstream stream(inPath);
size_t line = 1;
while (!std::ws(stream).eof()) {
try {
Data d;
stream >> d;
result.push_back(d);
line++;
}
catch (std::runtime_error& ex) {
std::cerr
<< "reading line " << line << " failed." << std::endl;
throw;
}
}
return result;
}
void WriteTable(std::ostream& stream, const DataVector& data) {
stream << data;
}
int main (int argc, const char* argv[]) {
std::string inputFilePath{"./data.txt"};
if (argc > 1) {
inputFilePath = argv[1];
}
std::cout << "reading "
<< inputFilePath << "..." << std::endl;
auto dv = ReadTable(inputFilePath);
std::cout << "... done" << std::endl
<< "number of records: " << dv.size() << std::endl;
//std::cout << dv << std::endl;
WriteTable(std::cout, dv);
return 0;
}
My code (below) works unless the required key isn't in the list yet (so if a node doesn't have a reference to its parent). It ignores the nodes and just makes a tree without them. How can I fix it? I'm thinking about just re-looping once all the keys are in and just keep adding and removing accordingly.
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <map>
struct Foo {
int data{0};
int left{-1};
int right{-1};
};
std::istream& operator>>(std::istream& in, Foo& ff) {
in >> ff.data >> ff.left >> ff.right;
return in;
}
struct Del {
template <class T>
void operator()(T* p) {
std::cout << "[deleted #" << (p ? p->data : 0) << "]\n";
delete p;
}
};
struct Bar {
int data{0};
std::unique_ptr<Bar, Del> lef;
std::unique_ptr<Bar, Del> rig;
};
void print(const std::unique_ptr<Bar, Del>& node) {
if (node) {
std::cout << ' ' << node->data;
print(node->lef);
print(node->rig);
}
}
int main() {
std::string input =
"101 1 3 102 2 8 104 6 7 103 -1 5 109 -1 -1 106 4 -1 107 -1 -1 108 -1 "
"-1 105 -1 -1";
std::istringstream IN(input);
std::map<int, std::pair<Bar*, bool>> mlist;
std::unique_ptr<Bar, Del> root;
int row = 0;
Foo entry;
while (IN >> entry) {
if (0 == row) {
root.reset(new Bar);
Bar* node = root.get();
node->data = entry.data;
std::cout << row << " [created #" << entry.data << ']';
if (0 <= entry.left)
mlist.emplace(entry.left, std::make_pair(node, true));
if (0 <= entry.right)
mlist.emplace(entry.right, std::make_pair(node, false));
} else {
auto it = mlist.find(row);
if (mlist.end() != it) {
if (it->second.second) {
it->second.first->lef.reset(new Bar);
Bar* node = it->second.first->lef.get();
node->data = entry.data;
std::cout << row << " [created #" << entry.data << ']';
if (0 <= entry.left)
mlist.emplace(entry.left, std::make_pair(node, true));
if (0 <= entry.right)
mlist.emplace(entry.right, std::make_pair(node, false));
mlist.erase(it);
} else {
it->second.first->rig.reset(new Bar);
Bar* node = it->second.first->rig.get();
node->data = entry.data;
std::cout << row << " [created #" << entry.data << ']';
if (0 <= entry.left)
mlist.emplace(entry.left, std::make_pair(node, true));
if (0 <= entry.right)
mlist.emplace(entry.right, std::make_pair(node, false));
mlist.erase(it);
}
// mlist.erase( it );
}
}
std::cout << " list size " << mlist.size() << '\n';
++row;
}
std::cout << "final list size " << mlist.size() << "\n\n";
print(root);
std::cout << "\n\n";
std::cout << "Lets see whats left in the list:";
return 0;
}
Actually, I just used a vector of nodes and it worked perfectly. Sorry for all the confusion!
I have made this section of code and would like it to print out like so:
Element Value
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
Instead of being underneath of each other. Could any one point me in the correct direction?
#include <iostream>
int main(){
int n[10] = {1,2,3,4,5,6,7,8,9,10};
int x[10] = {0,0,0,0,0,0,0,0,0,0};
std::cout << "Element" <<std::endl;
for(int i = 0; i < 10; i++)
{
std::cout <<n[i] << std::endl;
}
std::cout << "Value" <<std::endl;
for(int y = 0; y <10; y++)
{
std::cout << x[y] << std::endl;
}
std::cout << "size of array: " << sizeof(n) << std::endl;
}
Print the values next to each other in one loop instead of using two loops (I changed the contents of x to make sure we see what's going on):
#include <iostream>
int main(){
int x[10] = {5,8,1,2,4,6,7,1,0,9};
std::cout << "Element Value" << std::endl;
for(int i = 0; i < 10; i++) {
std::cout << " " << i << " " << x[i] << std::endl;
}
std::cout << "size of array: " << sizeof(x) << std::endl;
return 0;
}
https://ideone.com/vAaLyl
Output:
Element Value
0 5
1 8
2 1
3 2
4 4
5 6
6 7
7 1
8 0
9 9
size of array: 40
Other than that, there's no need for the array n; use your index as the index.
double a = 0;
double b = -42;
double result = a * b;
cout << result;
The result of a * b is -0, but I expected 0. Where did I go wrong?
The bit representation of -0.0 and 0.0 are different, but they are same value, so -0.0==0.0 would return true. In your case, result is -0.0, because one of the operand is negative.
See this demo:
#include <iostream>
#include <iomanip>
void print_bytes(char const *name, double d)
{
unsigned char *pd = reinterpret_cast<unsigned char*>(&d);
std::cout << name << " = " << std::setw(2) << d << " => ";
for(int i = 0 ; i < sizeof(d) ; ++i)
std::cout << std::setw(-3) << (unsigned)pd[i] << " ";
std::cout << std::endl;
}
#define print_bytes_of(a) print_bytes(#a, a)
int main()
{
double a = 0.0;
double b = -0.0;
std::cout << "Value comparison" << std::endl;
std::cout << "(a==b) => " << (a==b) <<std::endl;
std::cout << "(a!=b) => " << (a!=b) <<std::endl;
std::cout << "\nValue representation" << std::endl;
print_bytes_of(a);
print_bytes_of(b);
}
Output (demo#ideone):
Value comparison
(a==b) => 1
(a!=b) => 0
Value representation
a = 0 => 0 0 0 0 0 0 0 0
b = -0 => 0 0 0 0 0 0 0 128
As you can see yourself, the last byte of -0.0 is different from the last byte of 0.0.
Hope that helps.