Reputation: 1592
I am wondering how to convert iterator of characters __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >
to string in C++?
#include <iostream>
#include <string>
#include <algorithm>
using std::string;
#define TO_UPPER(s) (transform((s).begin(), (s).end(), (s).begin(), ::toupper))
#define TO_LOWER(s) (transform((s).begin(), (s).end(), (s).begin(), ::tolower))
int main() {
string str = "Hello world!";
string result = TO_LOWER(str);
std::cout << result << std::endl;
return 0;
}
Error:
[1/2] Building CXX object CMakeFiles/untitled.dir/main.cpp.o
FAILED: CMakeFiles/untitled.dir/main.cpp.o
/usr/bin/c++ -g -std=gnu++11 -MD -MT CMakeFiles/untitled.dir/main.cpp.o -MF CMakeFiles/untitled.dir/main.cpp.o.d -o CMakeFiles/untitled.dir/main.cpp.o -c /home/amir-pc/CLionProjects/untitled/main.cpp
/home/amir-pc/CLionProjects/untitled/main.cpp: In function ‘int main()’:
/home/amir-pc/CLionProjects/untitled/main.cpp:7:31: error: conversion from ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >’ to non-scalar type ‘std::string’ {aka ‘std::__cxx11::basic_string<char>’} requested
7 | #define TO_LOWER(s) (transform((s).begin(), (s).end(), (s).begin(), ::tolower))
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/amir-pc/CLionProjects/untitled/main.cpp:13:21: note: in expansion of macro ‘TO_LOWER’
13 | string result = TO_LOWER(str);
| ^~~~~~~~
ninja: build stopped: subcommand failed.
Upvotes: 1
Views: 412
Reputation: 311088
These macros change the string in place
#define TO_UPPER(s) (transform((s).begin(), (s).end(), (s).begin(), ::toupper))
#define TO_LOWER(s) (transform((s).begin(), (s).end(), (s).begin(), ::tolower))
So just write
TO_LOWER(str);
std::cout << str << std::endl;
Otherwise write
#include <iterator>
//...
string str = "Hello world!";
string result;
result.reserve( str.size() );
std::transform( str.begin(), str.end(), std::back_inserter( result ), ::tolower );
std::cout << result << std::endl;
Pay attention to that it is a bad idea to use such macros. At least you could declare inline functions.
Upvotes: 0
Reputation: 96886
std::transform
modifies the container in place. You don't need its return value, you can just read the original container.
Also avoid using macros if possible. Prefer functions.
Also note that std::toupper
causes undefined behavior if given a negative character code. You need to cast the parameter to unsigned char
first to avoid this.
Here's a good implementation from cppreference:
std::string str_toupper(std::string s) { std::transform(s.begin(), s.end(), s.begin(), // static_cast<int(*)(int)>(std::toupper) // wrong // [](int c){ return std::toupper(c); } // wrong // [](char c){ return std::toupper(c); } // wrong [](unsigned char c){ return std::toupper(c); } // correct ); return s; }
Upvotes: 7