Convert vector of uint8 to string - c++

I have a pointer to a vector of type uint8.
How would I take this pointer and convert the data in the vector into a full string representative of its content?

You could just initialize the std::string with the sequence obtained from the std::vector<uint8_t>:
std::string str(v->begin(), v->end());
There is no need to play any tricks checking whether the std::vector<uint8_t> is empty: if it is, the range will be empty. However, you might want to check if the pointer is v is null. The above requires that it points to a valid object.

For those who wants the conversion be done after a string is declared, you may use std::string::assign(), e.g.:
std::string str;
std::vector<uint8_t> v;
str.assign(v.begin(), v.end());

vector<uint8_t> *p;
string str(
p && !p->empty() ? &*p->begin() : NULL,
p && !p->empty() ? &*p->begin() + p->size() : NULL);

Related

How am I able to iterate through a string vector in c++?

I want to iterate through a string vector in c++. I want to open each item in the list with fopen.
const char *filep //fopen needs a constant char pointer.
for (vector<string>::iterator it = filelist.begin(); it != filelist.end(); it++)
{
filep = (const char *)it; //This isn't working. How can I fix this
fopen(filep, "rb");
}
You should have used it->c_str() as it is essentially a pointer to the element in the std::vector. But for an easier life use
for (const auto& s : filelist){
// s is a const reference to an element in filelist
// use s.c_str() if you need the character buffer
}
This is valid from C++11 onwards. Using const auto& rather than auto obviates a std::string copy.
Change this:
filep = (const char *)it;
to this:
filep = it->c_str();
However, you do extra, unnecessary steps, since you could just do this instead:
for (vector<string>::iterator it = filelist.begin(); it != filelist.end(); it++)
fopen(it->c_str(), "rb");
which reduces the number of lines of your code to just two, and doesn't use an extra pointer.
PS: A more modern approach can be found in Bathsheba's answer, or use the auto&& approach.
create a method getstring in which you will return the string.
for(unsigned int i=0; i<iterator.size();i++){
cout << iterator[i]->getstring()<<endl;
}
A std::string is a type which is completely different from const char *. Hence, you need to get underlying character buffer stored in string. For that You must use method std::string::c_str() or std::string::data() whatever you like.
Do it like below (Inspired from other answers now using range-based for-loop),
const char *filep //fopen needs a constant char pointer.
for (auto & str : filelist)
{
filep = str.c_str();
fopen(filep, "rb");
}

Character pointer access

I wanted to access character pointer ith element. Below is the sample code
string a_value = "abcd";
char *char_p=const_cast<char *>(a_value.c_str());
if(char_p[2] == 'b') //Is this safe to use across all platform?
{
//do soemthing
}
Thanks in advance
Array accessors [] are allowed for pointer types, and result in defined and predictable behaviors if the offset inside [] refers to valid memory.
const char* ptr = str.c_str();
if (ptr[2] == '2') {
...
}
Is correct on all platforms if the length of str is 3 characters or more.
In general, if you are not mutating the char* you are looking at, it best to avoid a const_cast and work with a const char*. Also note that std::string provides operator[] which means that you do not need to call .c_str() on str to be able to index into it and look at a char. This will similarly be correct on all platforms if the length of str is 3 characters or more. If you do not know the length of the string in advance, use std::string::at(size_t pos), which performs bound checking and throws an out_of_range exception if the check fails.
You can access the ith element in a std::string using its operator[]() like this:
std::string a_value = "abcd";
if (a_value[2] == 'b')
{
// do stuff
}
If you use a C++11 conformant std::string implementation you can also use:
std::string a_value = "abcd";
char const * p = &a_value[0];
// or char const * p = a_value.data();
// or char const * p = a_value.c_str();
// or char * p = &a_value[0];
21.4.1/5
The char-like objects in a basic_string object shall be stored contiguously.
21.4.7.1/1: c_str() / data()
Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
The question is essentially about querying characters in a string safely.
const char* a = a_value.c_str();
is safe unless some other operation modifies the string after it. If you can guarantee that no other code performs a modification prior to using a, then you have safely retrieved a pointer to a null-terminated string of characters.
char* a = const_cast<char *>(a_value.c_str());
is never safe. You have yielded a pointer to memory that is writeable. However, that memory was never designed to be written to. There is no guarantee that writing to that memory will actually modify the string (and actually no guarantee that it won't cause a core dump). It's undefined behaviour - absolutely unsafe.
reference here: http://en.cppreference.com/w/cpp/string/basic_string/c_str
addressing a[2] is safe provided you can prove that all possible code paths ensure that a represents a pointer to memory longer than 2 chars.
If you want safety, use either:
auto ch = a_string.at(2); // will throw an exception if a_string is too short.
or
if (a_string.length() > 2) {
auto ch = a_string[2];
}
else {
// do something else
}
Everyone explained very well for most how it's safe, but i'd like to extend a bit if that's ok.
Since you're in C++, and you're using a string, you can simply do the following to access a caracter (and you won't have any trouble, and you still won't have to deal with cstrings in cpp :
std::string a_value = "abcd";
std::cout << a_value.at(2);
Which is in my opinion a better option rather than going out of the way.
string::at will return a char & or a const char& depending on your string object. (In this case, a const char &)
In this case you can treat char* as an array of chars (C-string). Parenthesis is allowed.

access first letter of a string in a set c++

I have a set of strings and I need to access each one and compare the first letter of the string to a char and stop if they are the same. How do I go through that? I tried with
char* p;
for (std::set<string>::iterator iter=myset.begin(); iter!=myset.end();iter++)
{p = *iter;
if (p==characterForComparison) return 0;
}
but that does not pass the compiler, it says
error C2440: '=' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'char *'
How do I solve this? What I need is fairly simple, so I need as simple a solution as I can get, just go through all the strings, compare the first letter, and if they are the same, return 0;
To compare first character of std::string just do:
if (!(*iter).empty() &&
(*iter)[0] == characterForComparison)
{
}
To access first element in a string, string provides operator[], front(), or use begin to get reference to first element. see std::string page.
Since your set contains std::strings, dereferencing the iterator gives you a string, not its first character. Use operator [] instead:
p = (*iter)[0];
*iter is a string, try
char p;
//...
p = (*iter)[0]
You have two problems. The first is that you try to assign a std::string object to a char*. The second is if you want the first character, then p should be declared as a character and not a pointer to a character.
And of course, there's really no need to store the character in a temporary variable like p, at least not in such a simple case such as yours. Use it directly from the string like
if ((*iter)[0] == characterForComparison) { /* do something */ }
if you can use C++11:
for(auto s : myset)
{
if(s[0] == characterForComparison)
{
return 0;
}
}
A C++ string is not convertible to a C-style string. *iter gives you a C++ string.
If you want to actually compare the first character of a string, then.
if ((*iter)[0] == 'a')
would do the trick.
If you actually need a const char *, you can use:
p = iter->c_str();
Note however that this is a CONSTANT string, you shouldn't modify it.
You can also use the STL algorithms.
If you can use C++11:
bool set_condition(const char c, const set<string>& s)
{
auto position =
find_if(s.cbegin(), s.cend(), [c](const string& s) { return s[0] == c; } );
return (position != s.cend() );
}
try to wrap the char in an instance of std:string:
std:string comp(characterForComparison);
and
retrieve the first character with [0]

Get first char from std::string

I need to get the first character of an std::string with a minimum amount of code.
It would be great if it would be possible to get the first char in one line of code, from an STL std::map<std::string, std::string> map_of_strings. Is the following code correct:
map_of_strings["type"][0]
EDIT
Currently, I am trying to use this piece of code. Is this code correct?
if ( !map_of_strings["type"].empty() )
ptr->set_type_nomutex( map_of_strings["type"][0] );
The prototype of the set_type function is:
void set_type_nomutex(const char type);
That should work if you've put a non-empty string into map_of_strings["type"]. Otherwise, you'll get an empty string back, and accessing its contents will probably cause a crash.
If you can't be sure whether the string exists, you can test:
std::string const & type = map["type"];
if (!type.empty()) {
// do something with type[0]
}
Or, if you want to avoid adding an empty string to the map:
std::map<std::string,std::string>::const_iterator found = map.find("type");
if (found != map.end()) {
std::string const & type = found->second;
if (!type.empty()) {
// do something with type[0]
}
}
Or you could use at to do a range check and throw an exception if the string is empty:
char type = map["type"].at(0);
Or in C++11, the map also has a similar at which you can use to avoid inserting an empty string:
char type = map.at("type").at(0);
The c_str() method will return a pointer to the internal data. If the string is empty, then a pointer to a NULL-termination is returned, so a simple one-liner is safe and easy:
std::string s = "Hello";
char c = *s.c_str();
It's not exactly clear from your question what your problem is, but the thing likely to go wrong with map_settings["type"][0] is that the returned string may be empty, resulting in undefined behavior when you do [0]. You have to decide what you want to do if there is no first character. Here's a possibility that works in a single line.
ptr->set_type_nomutex( map_settings["type"].empty() ? '\0' : map_settings["type"][0]);
It gets the first character or a default character.
string s("type");
char c = s.at(0);

Printing out a map, cannot convert const string to const char array

I need to loop through the map, and send a const char array to the function to print it, I tried to use string cpy but the result is the same, it cannot convert a const string to a char. What am i doint wrong?
std::map <std::string, int>::const_iterator end = scores.end();
std::map<std::string, int>::const_iterator it;
for (it = scores.begin(); it != end; ++it)
{
char initials[4];
strcpy(initials,it->first);
//std::string s = "";
DrawString(screen, widthscreen/2 - (14*16)/4, heightscreen/2, initials,charsetsmall, 8);
You need to use string member function string::c_str
it->first returns std::string not underlying character data. To extract that you need to use the above member function.
You should use:
strcpy(initials,it->first.c_str());
Use the c_str() member of std::string.
DrawString(..., it->first.c_str(), ...);
strcpy(initials,it->first); //error
It should be this:
strcpy(initials,it->first.c_str()); //ok
Because first is std::string. You need to get the const char* which std::string stores by calling c_str().
By the way, are you sure the maxium size of the string would be 4 including the null-character? Better use strncpy instead of strcpy as:
strncpy(initials,it->first.c_str(), 4); //better
The third argument is the number of characters to be copied from source to destination.
you have to convert string to char. Try
it->first.c_str();
strcpy(initials,it->first);
change it to
strcpy(initials, it->first.c_str());
But this may generate some security issues.