Home > Back-end >  Convert normal iterator of characters to string
Convert normal iterator of characters to string

Time:03-18

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.

CodePudding user response:

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;
}

CodePudding user response:

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.

CodePudding user response:

#include<bits/stdc .h> using namespace std;

int main() {

string su = "Hello world!";
transform(su.begin(), su.end(), su.begin(), ::toupper);
cout << su << endl;
string sl = "Hello world!";
transform(sl.begin(), sl.end(), sl.begin(), ::tolower);
cout << sl << endl;

return 0;

}

  • Related