How to change the contents of a std string ?

If I have a std:string that has say a number like "7877673421"
how do I go about turning this into "787-767-3421" ?
You can use the std::string::insert() or std::string::push_back() functions.


here's an example function that will format 10 character strings into the format you specified.

It's very simple and contains no error checks other than a basic sanity check on the input.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

std::string format_phone_number(const std::string& str)
{
   // return empty string if str is ill-formed
   if(str.size() != 10)
     return std::string();

  std::string outstr(str);
  outstr.insert(3, "-");
  outstr.insert(7, "-");
  return outstr;
  

}
Last edited on
Hello PolloLoco4645,

Look into these especially the "insert".

http://www.cplusplus.com/reference/string/string/
http://www.cplusplus.com/reference/string/string/insert/

Hope that helps,

Andy
If I have a std:string that has say a number like "7877673421"
how do I go about turning this into "787-767-3421"?

It is safer if you don't use std::string::insert when you insert (-) hyphens.
The better way to do it is this :
1
2
3
4
5
6
7
8
9
10
11
12
13
std::string format_phone_number(const std::string& str)
{
   // return empty string if str is ill-formed
   if(str.size() != 10)
     return std::string();

  std::string part1(str.substr(0, 3));
  std::string part2(str.substr(3).substr(0, 3));
  std::string part3(str.substr(3).substr(3).substr(0, 4));

  std::string outstr = part1 + '-' + part2 + '-' + part3;
  return outstr;
}


@Hydranix
Your example does not work. (7877-673-421)

Handy Andy wrote:
Hope that helps,

Andy

Yeah, you don't know how std::string::insert makes things harder for beginners.
Last edited on
Yeah, you don't know how std::string::insert makes things harder for beginners.

Bad habits are particularly bad for beginners. I would consider making 7 strings in addition to the original to insert two characters rather than reasoning about std::string::insert the beginnings of a bad habit. Avoiding what you don't know is not conducive to learning.

The better way to do it is this :

This way is considerably worse in terms of complexity and resources used. Clarity is subjective of course, but to my mind insert more clearly conveys what's going on than your overly complex substr chaining.
@cire
True, my example does use a consider amount of system resources. How about this one?

1
2
3
4
5
6
7
8
9
10
11
12
13
std::string format_phone_number(const std::string& str)
{
   // return empty string if str is ill-formed
   if(str.size() != 10)
     return std::string();

  std::string part1(str.substr(0, 3));
  std::string part2(str.substr(3, 3));
  std::string part3(str.substr(6, 4));

  std::string outstr = part1 + '-' + part2 + '-' + part3;
  return outstr;
}


I am against std::string::insert because this function may alter the original positions of the characters. And the next time you insert another character, you may fail. Many people may not even know where std::string::insert inserts a character before the iterator or after the iterator.
True, my example does use a consider amount of system resources. How about this one?
You are still creating 7 strings in addition to the original, albeit 3 of them are moved from (you actually created more in your original code, but I didn't bother with an accurate count.)


I am against std::string::insert because this function may alter the original positions of the characters.
The subject of this thread: "How to change the contents of a std string ?"
Seems like exactly what was asked for.


Many people may not even know where std::string::insert inserts a character before the iterator or after the iterator.
Many people are capable of reading documentation which is a habit one should seek to encourage.
> I am against std::string::insert because this function may alter the original positions of the characters.

In general, I tend to agree with this view.
"Pure" code is simpler to reason about that code that causes mutations to objects; the soul sister to "use const pro-actively".


> Avoiding what you don't know is not conducive to learning.

In general, I tend to agree with this too; particularly when something that is immensely useful like regular expressions is involved.

1
2
3
4
5
6
7
8
#include <string>
#include <regex>

std::string format_phone_number( const std::string& str )
{
    static const std::regex phone_re( "(\\d{3})(\\d{3})(\\d{4})" ) ;
    return std::regex_replace( str, phone_re, "$1-$2-$3" ) ;
}

http://coliru.stacked-crooked.com/a/49b455b3389cbc37
http://rextester.com/RVX88014
@Pattako
I am against std::string::insert because this function may alter the original positions of the characters.

In the general case, what are you against? Is it mutable containers? Design by contract? Not just insertion into strings, specifically?

It feels like I've been beating this point to death lately, but the assertion
"This API is not understood by most programmers so it should be avoided" is terrible for two main reasons:
1. You have no data regarding what "most programmers" understand, so your premise is a fabrication; and
2. If a particular programmer doesn't fully understand the semantics of the API, then they are welcome to go look it up before attempting to reason about a unit which they do not understand.

Iterator invalidation is a common topic which any C++ programmer familiar with the standard library should understand. Further, the iterator invalidation rules are expressed clearly as pre- and post- conditions in the reference documentation; as is usual, if you disregard the applicable design contract your code is wrong.

Last edited on
Whoops, fixed my post.

@mbozzi
I concur.
Last edited on
Probably would have been quicker to look up regex, but never mind:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

//================================

string fmtFone( string str, string fmt )
{
   int SIZE = count( fmt.begin(), fmt.end(), ' ' );
   if( str.size() != SIZE ) return "Invalid number";

   string result = fmt;
   int pos = 0;
   for ( int i = 0; i < SIZE; i++ )
   {
      while ( result[pos] != ' ') pos++;
      result[pos] = str[i];
   }
   return result;
}

//================================

int main()
{
   string phone = "7877673421";
   string fmt = "   -   -    ";
   cout << "Formatted phone number: " << fmtFone( phone, fmt );
}


Formatted phone number 787-767-3421
Last edited on
Topic archived. No new replies allowed.