I am trying to split a string the fastest way possible in C++. I am getting an error here:
#include <bitset>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/timer.hpp>
using namespace std;
size_t const N = 10000000;
template<typename C>
void test_strpbrk(string const& s, char const* delims, C& ret)
{
C output;
char const* p = s.c_str();
char const* q = strpbrk(p + 1, delims);
for (; q != NULL; q = strpbrk(p, delims))
{
output.push_back(typename C::value_type(p, q));
p = q + 1;
}
output.swap(ret);
}
int main()
{
typedef string::const_iterator iter;
typedef boost::iterator_range<iter> string_view;
vector<string_view> vsv;
test_custom(text, delims, vsv);
}
The Visual Studio says: cannot convert from 'const char *' to 'const std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>'
Can you please help me, should I enable any option in visual studio for this to work?
It seems you are trying to convert a char const* to a std::string::const_iterator, e.g., when passing arguments to functions creating a range: although std::string::const_iterator may be a typedef for char const* there is no requirement that this is the case. I don't think your code give enough context to pin-point the exact problem, though. You might want to look for locations where you pass a string literal or take the address of a section of a std::string (i.e. something along the lines of &str[index] or &*it).
Based on you edit, what I suspected above actually got confirmed! You'll need to translate the char const*s your are playing with back to std::string::const_iterators, e.g., by adding suitable offsets:
typename C::value_type(s.begin() + (p - s.c_str()), s.begin() + (q - s.c_str()))
Related
I am having an issue receiving this error when compiling code similar to the below.
I am getting this error: invalid conversion from 'const char*' to 'char*' [-fpermissive].
I am unsure why as the strchr function accepts const char* ? maybe I am confused here. I have looked at other people having this same error on this site but I still don't see the solution clearly.
People had mentioned UNION? I have no clue how to use this keyword and was wondering if I could get clarification.
Could someone explain why this is happening or how is the safest/best method to resolving this error? I have other errors just like this in other spots in my code in the same situation.
#include <strings.h>
#include <cstring>
#include <string>
#include <stdio.h>
int main()
{
validURL ('www.why_CPP_hates_me.com');
return 0;
}
bool validURL (const char *url)
{
char *q = strchr (url, '?');
...
return true;
}
The right way to this is:
#include <cstring>
#include <string>
#include <stdio.h>
bool validURL(const char *url); // Must forward declare or prototype the
// function before calling
int main()
{
validURL("www.why_CPP_hates_me.com"); // Single quotes are for single chars
// Double quotes are for string
// literals, which create a const char*
return 0;
}
bool validURL(const char *url)
{
const char *q = strchr(url, '?'); // You have to assign to a const char*
// to maintain const correctness.
// strchr() has const char* and char*
// overloads. But you have to assign to
// the correct type.
return true;
}
Or if you wanted to you could do this:
bool validURL(const char *url)
{
char *q = strchr(const_cast<char*>(url), '?');
// Casting away const is not recommended generally. Should be careful.
return true;
}
In order to compare if two string contain a same char, I was trying to loop through a string a and put the chars into a map.
So this is what I did.
string a = "abc";
unordered_map<char,int> m;
for (auto i:a){
m.insert(i,1);
}
But then there is an error:
no matching function for call to ‘std::unordered_map<char, int>::insert(char&, int)’
I don't quite understand what can I do here. Hope someone can help!
The problem in your code is that you try to insert a which is a std::string into an std::unordered_map<char, int> - you should be inserting i which is a char (each char from std::string a).
Moreover, even if you correctly used
m.insert(a,1);
it wouldn't compile because std::unordered_map::insert accepts a std::pair not 2 arguments from the template type. So you would need:
std::unordered_map<char, int> char_map;
char_map.insert(std::make_pair(c, 1));
Want you want to achieve can be done with std::set (if you don't care about the order of objects - chars - stored inside it)
#include <iostream>
#include <string>
#include <unordered_set>
int main()
{
std::string a = "abc";
std::unordered_set<char> char_set;
for (auto c : a)
char_set.insert(c);
for (auto c : char_set)
std::cout << c << ' ';
}
http://cpp.sh/3zrgr
Unfortunately you need to call std::make_pair first:
#include <iostream>
#include <unordered_map>
int main()
{
std::string a = "abc";
std::unordered_map<char,int> m;
for (int i = 0; i < a.size(); ++i)
m.insert(std::make_pair(a[i],1));
}
I know the encoding and that the input string is 100% single byte, no fancy encodings like utf etc. And all I want is to convert it to wchar_t* or wstring basing on a known encoding. What functions to use ? btowc() and then loop ? Maybe string objects have something useful in them. There are lot of examples but all are for "multibyte" or fancy loops with btowc() that only show how to display output on screen that indeed this function is working, I haven't seen any serious example how to deal with buffers in such situation, is always wide char 2x larger than single char string ?
Try this template. It served me very well.
(author unknown)
/* string2wstring.h */
#pragma once
#include <string>
#include <vector>
#include <locale>
#include <functional>
#include <iostream>
// Put this class in your personal toolbox...
template<class E,
class T = std::char_traits<E>,
class A = std::allocator<E> >
class Widen : public std::unary_function<
const std::string&, std::basic_string<E, T, A> >
{
std::locale loc_;
const std::ctype<E>* pCType_;
// No copy-constructor, no assignment operator...
Widen(const Widen&);
Widen& operator= (const Widen&);
public:
// Constructor...
Widen(const std::locale& loc = std::locale()) : loc_(loc)
{
#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6.0...
using namespace std;
pCType_ = &_USE(loc, ctype<E> );
#else
pCType_ = &std::use_facet<std::ctype<E> >(loc);
#endif
}
// Conversion...
std::basic_string<E, T, A> operator() (const std::string& str) const
{
typename std::basic_string<E, T, A>::size_type srcLen =
str.length();
const char* pSrcBeg = str.c_str();
std::vector<E> tmp(srcLen);
pCType_->widen(pSrcBeg, pSrcBeg + srcLen, &tmp[0]);
return std::basic_string<E, T, A>(&tmp[0], srcLen);
}
};
// How to use it...
int main()
{
Widen<wchar_t> to_wstring;
std::string s = "my test string";
std::wstring w = to_wstring(s);
std::wcout << w << L"\n";
}
Is there any function in C++ which converts all data types (double, int, short, etc) to string?
Usually you'll use the << operator, in conjunction with (for example) a std::stringstream.
http://www.boost.org/doc/libs/1_43_0/libs/conversion/lexical_cast.htm
If boost is not an option (it should always be, but just in case):
#include <sstream>
#include <string>
template<class T1, class T2>
T1 lexical_cast(const T2& value)
{
std::stringstream stream;
T1 retval;
stream << value;
stream >> retval;
return retval;
}
template<class T>
std::string to_str(const T& value)
{
return lexical_cast<std::string>(value);
}
Boost has a similar idea, but the implementation is much more efficient.
There is no built-in universal function, but boost::lexical_cast<> will do this.
Why do you need this conversion? A lot of languages have variant types which auto-convert, and this can lead to wanting that behavior in C++ even though there may be a more canonical way of implementing it.
For example if you're trying to do output, using a (string)stream of some sort is probably the way to go. If you really need to generate and manipulate a string, you can use boost::lexical_cast http://www.boost.org/doc/libs/1_43_0/libs/conversion/lexical_cast.htm.
Here is the one I use from my utility library. This was condensed from other posts here on stackoverflow, I am not claiming this as my own original code.
#include <string>
#include <sstream>
using namespace std;
template <class T>
string ToString(const T& Value) {
stringstream ss;
ss << Value;
string s = ss.str();
return s;
}
also, another handy string formatting utility I use:
#include <string>
#include <stdarg.h> /* we need va_list */
// Usage: string myString = FormatString("%s %d", "My Number =", num);
string FormatString(const char *fmt, ...) {
string retStr;
if (NULL != fmt) {
va_list marker = NULL;
va_start(marker, fmt);
size_t len = 256 + 1; // hard size set to 256
vector <char> buffer(len, '\0');
if (vsnprintf(&buffer[0], buffer.size(), fmt, marker) > 0) {
retStr = &buffer[0]; // Copy vector contents to the string
}
va_end(marker);
}
return retStr;
}
For this use stringstream.
First include the header file as #include .
Then create an object of stringstream and using stream insertion operator (<<) pass the contents you want to convert as string.
Ex:
#include <iostream>
#include <sstream>
int main(){
std::string name = "Ram";
float salary = 400.56;
std::stringstream obj;
obj << name << " salary: " << salary;
std::string s = obj.str();
std::cout << s;
}
According to this site, I have done the following program which sorts strings.
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char list[5][4]={"dat","mai","lik","mar","ana"};
int main(int argc, char *argv[])
{
int x;
puts("sortirebamde:");
for (x=0;x>sizeof(list)/sizeof(char);x++)
printf("%s\n",list[x]);
qsort(&list,(sizeof(list)/sizeof(char)),sizeof(list[0]),strcmp);
system("PAUSE");
return EXIT_SUCCESS;
}
Here is the error I get
13 C:\Documents and Settings\LIBRARY\Desktop\string_sortireba.cpp invalid conversion from `int (*)(const char*, const char*)' to `int (*)(const void*, const void*)'
13 C:\Documents and Settings\LIBRARY\Desktop\string_sortireba.cpp initializing argument 4 of `void qsort(void*, size_t, size_t, int (*)(const void*, const void*))'
Please help
Please note: It is unusual to store C strings in two dimensional char arrays. It's more normal to have char *ary[], such as argv. That type cannot be sorted directly using qsort and strcmp, because qsort will pass char ** not char * to the comparison function. This is good for efficiency, the pointers can be swapped instead of the whole strings. The Linux manpage for qsort has some good example code with a correct comparison function.
You can't pass strcmp directly to qsort as its comparison function because qsort expects to pass pointers to void where strcmp expects pointers to const char. Given the required similarity between pointers to void and pointers to char, you could probably do it with a cast (for your code), but the cleaner way would be to write a function that takes the right types:
int cmpstr(void const *a, void const *b) {
char const *aa = (char const *)a;
char const *bb = (char const *)b;
return strcmp(aa, bb);
}
Note, however, that in C++ you'd normally want to use std::sort instead of qsort, and probably use std::string instead of char *, which case the sorting gets a lot simpler (and generally faster as well).
The fourth argument of qsort takes 2 void* pointers as args.So you need to define a compare function for yours.
refer to this link for more details.
You can pass strcmp directly to qsort
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char list[5][4]={"dat","mai","lik","mar","ana"};
int main(int argc, char *argv[]) {
int x;
puts("unsorted:");
for (x=0;x<sizeof(list)/sizeof(list[0]);x++)
printf("%s\n",list[x]);
qsort(list,sizeof(list)/sizeof(list[0]),sizeof(list[0]),strcmp);
puts("sorted:");
for (x=0;x<sizeof(list)/sizeof(list[0]);x++)
printf("%s\n",list[x]);
// system("PAUSE");
return EXIT_SUCCESS;
}
use C, not C++
Beyond why qsort fails, don't use it in C++.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
char const* const raw_data[5] = {"dat", "mai", "lik", "mar", "ana"};
std::vector<std::string> data (raw_data, raw_data + 5);
// would rarely be a global
// see below for code that needs to go here
int main() {
using namespace std;
cout << "before: " << data << "\n";
sort(data.begin(), data.end());
cout << "after: " << data << "\n";
return 0;
}
Boost has stream inserter overloads to output a vector directly, but here's one simple version. This goes into a header, rather than being copied and pasted continually:
template<class Stream, class Iter, class Ch>
void write_sequence(Stream& s, Iter begin, Iter end, Ch const* initial, Ch const* sep, Ch const* final) {
if (initial) {
s << initial;
}
if (begin != end) {
s << *begin;
++begin;
for (; begin != end; ++begin) {
if (sep) {
s << sep;
}
s << *begin;
}
}
if (final) {
s << final;
}
}
template<class T, class A>
std::ostream& operator<<(std::ostream& s, std::vector<T,A> const& value) {
write_sequence(s, value.begin(), value.end(), "[", ", ", "]");
return s;
}
More C++-Style - nowadays - with static_cast:
int scmp(const void * s1, const void * s2)
{
const char* _s1 = *static_cast<const char* const*>(s1);
const char* _s2 = *static_cast<const char* const*>(s2);
return strcmp(_s1, _s2);
}
And in main():
char *str_arr[] = { "one", "two", "three" };
qsort(str_arr, sizeof(str_array)/sizeof(char*), sizeof(char*), scmp);
Much easier is it with vector and std::sort.