What if the EEPROM used is greater than 32K, such as at24c32, and the register address is 16bit? It seems that smbus only supports 8bit registers?
I can read 0xff, but the written content will return - 5, which fails.
I want to know whether the kernel only supports 8-bit registers, but not 16 bit registers?
This is my code:
#include <fcntl.h>
#include <stdio.h>
#include <linux/i2c-dev.h>
#include <errno.h>
#include <stddef.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <signal.h>
#define AT24C32_ADDR 0x53
__s32 i2c_smbus_access(int file, char read_write, __u8 command,
int size, union i2c_smbus_data* data)
{
struct i2c_smbus_ioctl_data args;
__s32 err;
args.read_write = read_write;
args.command = command;
args.size = size;
args.data = data;
err = ioctl(file, I2C_SMBUS, &args);
if (err == -1)
err = -errno;
return err;
}
__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value)
{
union i2c_smbus_data data;
data.byte = value;
return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
I2C_SMBUS_BYTE_DATA, &data);
}
__s32 i2c_smbus_read_byte_data(int file, __u8 command)
{
union i2c_smbus_data data;
int err;
err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
I2C_SMBUS_BYTE_DATA, &data);
if (err < 0)
return err;
return 0x0FF & data.byte;
}
static int32_t i2c_smbus_write_word_data(int file, uint8_t cmd, uint16_t value)
{
union i2c_smbus_data data;
data.word = value;
return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
I2C_SMBUS_WORD_DATA, &data);
}
static int32_t i2c_smbus_read_word_data(int fd, uint8_t cmd)
{
union i2c_smbus_data data;
int err;
err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
I2C_SMBUS_WORD_DATA, &data);
if (err < 0)
return err;
return data.word;
}
int set_slave_addr(int file, int address, int force)
{
/* With force, let the user read from/write to the registers
even when a driver is also running */
if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0) {
fprintf(stderr,
"Error: Could not set address to 0x%02x: %s\n",
address, strerror(errno));
return -errno;
}
return 0;
}
I have a school project and I have to use the AM in the Student.h as a char*.The AM have to have numbers in it. I can't understand why what I am doing is not working.
Student.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
int main()
{
Student dlg;
dlg.AM[10]={2,1,3,9,0,2,6,6};
}
Student.h
#pragma once
#include <string>
using namespace std;
class Student
{
public:
char *AM[20];
string Name;
unsigned int Semester = 1;
};
If you really need your student number to be a char string, then you need to convert your ints to char* before assigning them to the array.
int main()
{
Student dlg;
int j = 0;
for (auto i : {2,1,3,9,0,2,6,6})
{
auto strInt { std::to_string(i) }; // create a C++ string containing a int
// next copy the internal memory of the C++ string to a read-writable memory buffer
// and assign a pointer to that buffer casted to a char* to the appropriate slot in the array
dlg.AM[j++] = static_cast<char*> (std::memcpy (new char[16], strInt.c_str(), strInt.size()));
}
// test
for (int i = 0; i < 8; i++)
{
cout << dlg.AM[i] << ' ';
}
}
Are you sure the student number should be a char* ?
This is the problem of the SPOJ "SEGSQRSS - Sum of Squares with Segment Tree" the link to the problem is http://www.spoj.com/problems/SEGSQRSS/ I'm trying to do it using lazy propagation but cannot find the correct solution, can anyone help where I'm going wrong.
#include <map>
#include <set>
#include <math.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define inf 0x7fffffff
#define mod 1000000007
#define ll long long int
#define all(c) c.begin(),c.end()
#define tr(c,i) for(typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
// it uses lazy propagation
struct seg
{
ll x;// which stores the value of the 2*(sum of the elements of the segment)
ll sum;// stores the sum of the square of the elements of the segment
};
seg tree[2000050];
ll arr[100005],lazyadd[2000050],lazycha[2000050];
ll query_tree(ll node,ll a,ll b,ll i,ll j);
void build_tree(ll node,ll a,ll b);
void build_tree(ll node,ll a,ll b)
{
if(a>b)return ;
if(a==b)
{
tree[node].x=2*arr[a];
tree[node].sum=arr[a]*arr[a];
return ;
}
build_tree(2*node,a,a+((b-a)/2));
build_tree(2*node+1,1+a+((b-a)/2),b);
tree[node].x=tree[2*node].x+tree[2*node+1].x;
tree[node].sum=tree[2*node].sum+tree[2*node+1].sum;
return ;
}
ll query_tree(ll node,ll a,ll b,ll i,ll j)
{
if(a > b || a > j || b < i) return 0;
ll ans;
ll mid=(a+b)/2;
if((lazyadd[node]!=0)||(lazycha[node]!=0))
{
// this is for type 0
if(i!=j){
if(lazycha[node]!=0){
tree[2*node].sum=(mid-a+1)*lazycha[node]*lazycha[node];
tree[2*node].x=(mid-a+1)*lazycha[node]*2;
tree[2*node+1].sum=(b-mid)*lazycha[node]*lazycha[node];
tree[2*node+1].x=(b-mid)*lazycha[node]*2;
lazycha[2*node]=lazycha[2*node]+lazycha[node];
lazycha[2*node+1]=lazycha[2*node+1]+lazycha[node];
}
// this is for type 1
if(lazyadd[node]!=0){
tree[2*node].sum=tree[2*node].sum+tree[2*node].x*lazyadd[node]+(mid-a+1)*lazyadd[node]*lazyadd[node];
tree[2*node].x=tree[2*node].sum+(mid-a+1)*lazyadd[node]*2;
tree[2*node+1].sum=tree[2*node+1].sum+tree[2*node+1].x*lazyadd[node]+(b-mid)*lazyadd[node]*lazyadd[node];
tree[2*node+1].sum=tree[2*node+1].sum+(b-mid)*lazyadd[node]*2;
lazyadd[2*node]=lazyadd[2*node]+lazyadd[node];
lazyadd[2*node+1]=lazyadd[2*node+1]+lazyadd[node];
}
}
lazyadd[node]=0;
lazycha[node]=0;
}
if((i<=a)&&(b<=j))return tree[node].sum;
ll ans1=query_tree(2*node,a,a+((b-a)/2),i,j);
ll ans2=query_tree(2*node+1,a+((b-a)/2)+1,b,i,j);
ans=ans1+ans2;
return ans;
}
void update_tree(ll node,ll a,ll b,ll i,ll j,ll value,ll type)
{
if(a > b || a > j || b < i) return ;
ll mid=(a+b)/2;
if((lazyadd[node]!=0)||(lazycha[node]!=0))
{
// this is for type 0
if(i!=j){
if(lazycha[node]!=0){
tree[2*node].sum=(mid-a+1)*lazycha[node]*lazycha[node];
tree[2*node].x=(mid-a+1)*lazycha[node]*2;
tree[2*node+1].sum=(b-mid)*lazycha[node]*lazycha[node];
tree[2*node+1].x=(b-mid)*lazycha[node]*2;
lazycha[2*node]=lazycha[2*node]+lazycha[node];
lazycha[2*node+1]=lazycha[2*node+1]+lazycha[node];
}
// this is for type 1
if(lazyadd[node]!=0){
tree[2*node].sum=tree[2*node].sum+tree[2*node].x*lazyadd[node]+(mid-a+1)*lazyadd[node]*lazyadd[node];
tree[2*node].x=tree[2*node].sum+(mid-a+1)*lazyadd[node]*2;
tree[2*node+1].sum=tree[2*node+1].sum+tree[2*node+1].x*lazyadd[node]+(b-mid)*lazyadd[node]*lazyadd[node];
tree[2*node+1].sum=tree[2*node+1].sum+(b-mid)*lazyadd[node]*2;
lazyadd[2*node]=lazyadd[2*node]+lazyadd[node];
lazyadd[2*node+1]=lazyadd[2*node+1]+lazyadd[node];
}
}
lazyadd[node]=0;
lazycha[node]=0;
}
if((i<=a)&&(b<=j))
{
if(type==0)
{
tree[node].sum=(b-a+1)*value*value;
tree[node].x=(b-a+1)*value*2;
lazycha[node]+=value;
return;
}
else if(type==1)
{
tree[node].sum=tree[node].sum+tree[node].x*value+(b-a+1)*value*value;
tree[node].x+=(b-a+1)*value*2;
lazyadd[node]+=value;
return;
}
}
update_tree(2*node,a,a+((b-a)/2),i,j,value,type);
update_tree(2*node+1,1+a+((b-a)/2),b,i,j,value,type);
tree[node].sum=tree[2*node].sum+tree[2*node+1].sum;
}
int main()
{
ll t,x,n,c,i,j,v;
cin>>t;
for(x=1;x<=t;x++){
memset(lazyadd,0,sizeof(lazyadd));
memset(lazycha,0,sizeof(lazycha));
ios_base::sync_with_stdio(0);//this is the boost :)
scanf("%lld%lld",&n,&c);
for(i=1;i<=n;i++)scanf("%lld",&arr[i]);//cin>>arr[i];
build_tree(1,1,n);
cout<<"Case "<<x<<endl;
while(c--)
{
int type;
scanf("%d",&type);
if(type==2)
{
scanf("%lld%lld",&i,&j);
printf("%lld\n",query_tree(1,1,n,i,j));
}
else
{
scanf("%lld%lld%lld",&i,&j,&v);
update_tree(1,1,n,i,j,v,type);
}
}
}
return 0;
}
Thanks in Advance.
I'm looking to implement a multi-map that maintains insertion order of the entries, and allows in-place insertion/replacement without affecting the order. Guava's LinkedListMultimap is almost perfect, but doesn't allow the type of replacement I'm looking for. LinkedListMultimap is implemented as a hash map and multiple linked lists; it looks like this:
________________
/ \
(A,1) -> (B,2) -> (A,3) -> (C,4) -> (B,5) -> (C,6) -> (A,7)
\________\_______/\________________/_________________/
\_______________________/
Internally, every node has a pointer to the next node in the sequence, as well as the next node with the same key, and a hash table maintains a mapping from keys to the first node with that key.
Unfortunately, this doesn't allow for efficient in-place insertions or replacements. For example, to replace (C,4) with (B,8), I'd have to walk backwards an arbitrarily long way to find (B,2) in order to update its "next of same key" pointer.
The best idea I have to far is to associate each element with a sequence number, and keep a sorted set for each key. But to insert in the middle of the sequence, I would need infinitely divisible sequence numbers.
(By the way, I'm implementing this in C++, but I'm just looking for a description of a data structure that would work. If there's a pre-existing library that would work that would be great, but even boost::multi_index_container doesn't seem up to the task.)
Answer #1
Why is Boost.MultiIndex not helping you here?
Live On Coliru
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
using namespace boost::multi_index;
#include <iosfwd>
template<typename T,typename Q>
struct pair_
{
T first;
Q second;
};
template<typename T,typename Q>
std::ostream& operator<<(std::ostream& os,const pair_<T,Q>& p)
{
return os<<"("<<p.first<<","<<p.second<<")";
}
template<typename T,typename Q>
using list_multimap=multi_index_container<
pair_<T,Q>,
indexed_by<
sequenced<>,
ordered_non_unique<
composite_key<
pair_<T,Q>,
member<pair_<T,Q>,T,&pair_<T,Q>::first>,
member<pair_<T,Q>,Q,&pair_<T,Q>::second>
>
>
>
>;
template<typename T,typename Q>
std::ostream& operator<<(std::ostream& os,const list_multimap<T,Q>& lmm)
{
for(const auto& p:lmm)os<<p<<" ";
return os;
}
#include <string>
#include <iostream>
int main()
{
list_multimap<std::string,int> lmm{{"A",1},{"B",2},{"A",3},{"C",4},{"B",5},{"C",6},{"A",7}};
auto& mm=lmm.get<1>();
std::cout<<lmm<<"\n";
// List values with key "A"
auto r=mm.equal_range("A");
while(r.first!=r.second)std::cout<<*(r.first)++<<" ";
std::cout<<"\n";
// replace (C,4) with (B,8)
mm.replace(mm.find(std::make_tuple("C",4)),{"B",8});
std::cout<<lmm<<"\n";
}
Answer #2
My first answer can be refined to get what you're after, I think:
Live On Coliru
#include <algorithm>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <functional>
using namespace boost::multi_index;
#include <iosfwd>
template<typename T,typename Q>
struct pair_
{
T first;
Q second;
using compare=std::function<bool(const pair_&,const pair_&)>;
mutable compare* subcmp;
pair_(const T& first,const Q& second,compare* subcmp=nullptr):
first(first),second(second),subcmp(subcmp){}
};
namespace std{
template<typename T,typename Q>
struct less<pair_<T,Q>>
{
bool operator()(const pair_<T,Q>& x,const pair_<T,Q>& y)const
{
if(x.first<y.first)return true;
if(y.first<x.first)return false;
if(x.subcmp) return (*x.subcmp)(x,y);
if(y.subcmp) return (*y.subcmp)(x,y);
return false;
}
template<typename R>
bool operator()(const R& x,const pair_<T,Q>& y)const
{
return x<y.first;
}
template<typename R>
bool operator()(const pair_<T,Q>& x,const R& y)const
{
return x.first<y;
}
};
} // namespace std
template<typename T,typename Q>
std::ostream& operator<<(std::ostream& os,const pair_<T,Q>& p)
{
return os<<"("<<p.first<<","<<p.second<<")";
}
template<typename T,typename Q>
using list_multimap=multi_index_container<
pair_<T,Q>,
indexed_by<
random_access<>,
ordered_non_unique<identity<pair_<T,Q>>>
>
>;
template<typename T,typename Q>
std::ostream& operator<<(std::ostream& os,const list_multimap<T,Q>& lmm)
{
for(const auto& p:lmm)os<<p<<" ";
return os;
}
#include <string>
#include <iostream>
int main()
{
list_multimap<std::string,int> lmm{{"A",1},{"B",2},{"A",3},{"C",4},{"B",5},{"C",6},{"A",7}};
auto& mm=lmm.get<1>();
std::cout<<lmm<<"\n";
// list values with key "A"
auto r=mm.equal_range("A");
while(r.first!=r.second)std::cout<<*(r.first)++<<" ";
std::cout<<"\n";
// replace (C,4) with (B,8)
pair_<std::string,int>::compare subcmp=[&](const auto&x, const auto& y){
auto itx=lmm.iterator_to(x);
auto ity=lmm.iterator_to(y);
return itx<ity;
};
r=mm.equal_range("C");
auto it=std::find_if(r.first,r.second,[](const auto& x){return x.second==4;});
mm.modify(it,[&](auto&x){x={"B",8,&subcmp};});
it->subcmp=nullptr;
std::cout<<lmm<<"\n";
// list values with key "B"
r=mm.equal_range("B");
while(r.first!=r.second)std::cout<<*(r.first)++<<" ";
std::cout<<"\n";
}
The key ideas are:
Use a random-access index instead of a sequenced one.
Let elements be subsorted (when the keys are equal) by a user-provided comparison function, stored in subcmp, which is optional (if subcmp is null).
When replacing values, use modify (so as to change the element in place) and provide a subcomparer that simply respects the order of the elements in the random-access index. After modification is done, set subcmp to nullptr as it is no longer needed.
Answer #3
My second answer can be further refined to place the subcomparer within the less<pair_<T,Q>> object itself:
Live On Coliru
#include <algorithm>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <functional>
using namespace boost::multi_index;
#include <iosfwd>
template<typename T,typename Q>
struct pair_
{
T first;
Q second;
};
namespace std{
template<typename T,typename Q>
struct less<pair_<T,Q>>
{
using subcompare=std::function<bool(const pair_<T,Q>&,const pair_<T,Q>&)>;
subcompare subcmp;
bool operator()(const pair_<T,Q>& x,const pair_<T,Q>& y)const
{
if(x.first<y.first)return true;
if(y.first<x.first)return false;
if(subcmp) return subcmp(x,y);
return false;
}
template<typename R>
bool operator()(const R& x,const pair_<T,Q>& y)const
{
return x<y.first;
}
template<typename R>
bool operator()(const pair_<T,Q>& x,const R& y)const
{
return x.first<y;
}
};
} // namespace std
template<typename T,typename Q>
std::ostream& operator<<(std::ostream& os,const pair_<T,Q>& p)
{
return os<<"("<<p.first<<","<<p.second<<")";
}
template<typename T,typename Q>
using list_multimap=multi_index_container<
pair_<T,Q>,
indexed_by<
random_access<>,
ordered_non_unique<
identity<pair_<T,Q>>,
std::reference_wrapper<const std::less<pair_<T,Q>>>>
>
>;
template<typename T,typename Q>
std::ostream& operator<<(std::ostream& os,const list_multimap<T,Q>& lmm)
{
for(const auto& p:lmm)os<<p<<" ";
return os;
}
#include <string>
#include <iostream>
int main()
{
std::less<pair_<std::string,int>> less;
list_multimap<std::string,int> lmm{boost::make_tuple(
boost::make_tuple(),
boost::make_tuple(
identity<pair_<std::string,int>>{},
std::cref(less)
)
)};
auto& mm=lmm.get<1>();
lmm={{"A",1},{"B",2},{"A",3},{"C",4},{"B",5},{"C",6},{"A",7}};
std::cout<<lmm<<"\n";
// list values with key "A"
auto r=mm.equal_range("A");
std::for_each(r.first,r.second,[](const auto& x){std::cout<<x<<" ";});
std::cout<<"\n";
// replace (C,4) with (B,8)
std::less<pair_<std::string,int>>::subcompare subcmp=
[&](const auto&x, const auto& y){
return lmm.iterator_to(x)<lmm.iterator_to(y);
};
r=mm.equal_range("C");
auto it=std::find_if(r.first,r.second,[](const auto& x){return x.second==4;});
less.subcmp=subcmp;
mm.modify(it,[](auto& x){x={"B",8};});
less.subcmp=nullptr;
std::cout<<lmm<<"\n";
// list values with key "B"
r=mm.equal_range("B");
std::for_each(r.first,r.second,[](const auto& x){std::cout<<x<<" ";});
std::cout<<"\n";
}
This gets us an important reduction in memory usage, as the elements themselves need not come with an additional pointer for subcmp. The general strategy remains exactly the same.
The following sample code works fine under linux using g++4.8.2, using boost1_56. However, I get a strange linker error under MacOS X (Yosemite) using clang:
ld: internal error: atom not found in symbolIndex(__ZNSt3__112__hash_tableINS_17__hash_value_typeIKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN15FRUIT_TUPLES4dataEEENS_22__unordered_map_hasherIS8_SB_NS9_8key_hashELb1EEENS_21__unordered_map_equalIS8_SB_NS9_9key_equalELb1EEENS5_ISB_EEE15__insert_uniqueIRKNS_4pairIS8_SA_EEEENSL_INS_15__hash_iteratorIPNS_11__hash_nodeISB_PvEEEEbEEOT_) for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Proces
The main.cpp file
#include "TupleFruits.hpp"
int main()
{
map_t fruitHash = InitializeFruitHash();
std::string fruit = "BANANA";
auto itr = fruitHash(fruit);
if (fruitHash.end() == itr)
{
std::cout << fruit << " not found in hash" << std::endl;
exit(1);
}
}
The FruitHash.cpp file:
#include "TupleFruits.hpp"
map_t InitializeFruitHash()
{
static map_t m;
data dBANANA = {0, 0, 6, false};
data dGRAPEFRUIT = {1, 1, 6, false};
data dSTRAWBERRY = {2, 2, 6, false};
m[BANANA] = dBANANA;
m[GRAPEFRUIT] = dGRAPEFRUIT;
m[STRAWBERRY] = dSTRAWBERRY;
return m;
}
The include file "HashData.hpp
#ifndef HASH_DATA_HPP
#define HASH_DATA_HPP
#include <string>
#include <unordered_map>
#include <cstring>
#include <iostream>
#include <tuple>
#include <boost/functional/hash.hpp>
typedef std::string fruit_key_t;
namespace HASH_TUPLES
{
struct key_hash : public std::unary_function<fruit_key_t, std::size_t>
{
std::size_t operator()(const fruit_key_t& k) const
{
std::hash<std::string> hash_fn;
return hash_fn(k);
}
};
struct key_equal : public std::binary_function<fruit_key_t, fruit_key_t, bool>
{
bool operator()(const fruit_key_t& v0, const fruit_key_t& v1) const
{
return (v0 == v1);
}
};
struct data
{
int row;
int column;
int precision;
bool isRipe;
inline bool operator ==(data d)
{
if (d.row == row && d.column == column)
return true;
else
return false;
}
friend std::ostream& operator << (std::ostream& os, const data& rhs) //Overloaded operator for '<<'
{ //for struct output
os << rhs.row << ", "
<< rhs.column;
return os;
}
};
typedef std::unordered_map<const fruit_key_t, data, key_hash, key_equal> map_t;
// ^ this is our custom hash
}
template<class T>
struct map_data_compare : public std::binary_function<typename T::value_type,
typename T::mapped_type,
bool>
{
public:
bool operator() (typename T::value_type &pair,
typename T::mapped_type i) const
{
return pair.second == i;
}
};
#endif
The include file "TupleFruits.hpp"
#ifndef TUPLESFRUITS_HPP
#define TUPLESFRUITS_HPP
#include <boost/interprocess/containers/string.hpp>
#include "HashData.hpp"
using namespace HASH_TUPLES;
map_t InitializeFruitHash();
static std::string BANANA = "banana";
static std::string GRAPEFRUIT = "grapefruit";
static std::string STRAWBERRY = "strawberry";
#endif
I figured it out. Somehow -s (strip all symbols from binary) snuck in my Makefile