Having trouble adding spaces between characters in a string being built via a for loop.

I'm adding characters from one string to another with the addition of spaces between the characters.

This doesn't work. I get a real crazy output.
1
2
3
4
5
6
7
8
  		//Print the character legend.
	for(Character_Legend_Pointer = Character_Legend.begin();
		Character_Legend_Pointer != Character_Legend.end();
		Character_Legend_Pointer++){

		Character_Legend_Output_String += *Character_Legend_Pointer + "   ";

	}



This does work. Why?
1
2
3
4
5
6
7
8
9
  	//Print the character legend.
	for(Character_Legend_Pointer = Character_Legend.begin();
		Character_Legend_Pointer != Character_Legend.end();
		Character_Legend_Pointer++){

		Character_Legend_Output_String += *Character_Legend_Pointer;
		Character_Legend_Output_String += "   ";

	}


In the first case you are trying to work out the RHS first, which is presumably trying to add a char to a c-string (or maybe a const char to a const char *). Either way it's not defined.

In the second case you are adding a char to a std::string (OK) followed by a c-string to a std::string (also OK).
Character_Legend_Output_String += *Character_Legend_Pointer + " ";
Looking at the types of the arguments here, it's presumably:
string += char + const char*
The right side is the += is a pointer plus an integral type. The char gets promoted to int:
int + const char *
which adds the int to the const char * to create a new const char *.

It's equivalent to this:
1
2
3
4
int index = *Character_Legend_Pointer;
const char *array = "   ";
const char *tmpPointer = &array[index];   // out of bounds for any index >3
Character_Legend_Pointer += tmpPointer.


Your second example works because string lets you add chars and const char*s.
Assuming that *Character_Legend_Pointer is of type char, then you can't concatenate a type char to a type char* (" ");

You could try:

 
Character_Legend_Output_String += *Character_Legend_pointer + "   "s;


or:

 
Character_Legend_Output_String += *Character_Legend_pointer + std::string(3, ' ');


ie the type of the 'spaces' is std:string to which you can concatenate with a type char.
Hi,

There is also std::string_view, this video describes how it works:

https://www.youtube.com/watch?v=ZO68JEgoPeg&list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb&index=80

https://en.cppreference.com/w/cpp/string/basic_string_view


Don't forget to compile with c++17, put this at the beginning of the main.cpp file, the compiler will print the error message, if you aren't using it.

1
2
3
#if __cplusplus < 201703L 
#error "C++17 or better required\n"
#endif 


As JLBorges mentioned in one of the other posts, you are better off with a range based for loop, not sure why you think iterators are easier ?
CppCon 2018: Victor Ciura “Enough string_view to Hang Ourselves”
https://www.youtube.com/watch?v=xwP4YCP_0q0
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>
using namespace std;

int main()
{
   string Character_Legend = "TheShire";
   string Character_Legend_Output_String( 4 * Character_Legend.size(), ' ' );
   for ( int i = 0; i < Character_Legend.size(); i++ ) Character_Legend_Output_String[4*i] = Character_Legend[i];
   cout << Character_Legend_Output_String << '\n';
}
> you are better off with a range based for loop, not sure why you think iterators are easier ?

For iterating through a single range, particularly without side-effects, range-based loops are almost always easier, cleaner, less error-prone. IMHO.

A version using range-based loop:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <string>
#include <string_view>

std::string insert_spaces( const std::string_view& str, std::size_t num_spaces = 3 )
{
    const std::string spaces( num_spaces, ' ' ) ;

    std::string result ;
    for( char c : str ) result += c + spaces ;

    // knock off trailing spaces (uncomment if required)
    // while( !result.empty() && result.back() == ' ' ) result.pop_back() ;

    return result ;
}


I guess iterators are used in the original code because there is another thread where seeplus (who had been helping CVRIV) made a fairly strong push for favouring iterator based classical for loops over range-based loops.
made a fairly strong push for favouring iterator based classical for loops over range-based loops


if I'm remembering the right post, I don't think I made a strong push. I just showed how to do it right using iterators. I favour range-based for loops. I can't remember ever posting my code that used an iterator loop when a range-for could be used.
Last edited on
Topic archived. No new replies allowed.