Replace any space ' ' by '_' in 2-character string passCode. Sample output for the given program:

I'm stuck on a problem in Zybooks, the goal is to take a 2-character string input and replace any white space with an underscore. I'm pretty sure I'm on the right track but something is obviously wrong because I'm getting a run-time error

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
string passCode;

passCode = "1 ";

if(isspace(passCode.at(0))){
passCode.replace(passCode.at(0),1,"_");
}
if(isspace(passCode.at(1))){
passCode.replace(passCode.at(1),1,"_");
}
cout << passCode << endl;
return 0;
}
note: Zybooks changes the passcode string when testing
1
2
3
for (int i = 0; i < passCode.length(); i++)
    if (passCode[i] == ' ')
        passCode[i] = '_';


std::string::replace taks a pos as an argumant you are giving it a character

try this if you are using replace
1
2
3
    passCode.replace(0, 1, '_') 
//                   ^
//       first character index 
Last edited on
thank you!
you're welcome bro!
Last edited on
PLEASE learn to use code tags, they make reading and commenting on source code MUCH easier.

http://www.cplusplus.com/articles/jEywvCM9/

HINT: you can edit your post and add the code tags.

With that said, an alternative for loop is, a range-base for loop:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>

int main()
{
   std::string passCode { "1 2  a   4" };

   for (auto& itr : passCode)
   {
      if (itr == ' ')
      {
         itr = '_';
      }
   }

   std::cout << passCode << '\n';
}

1_2__a___4
Last edited on
You could replace the if statement block with the ternary conditional statement:
8
9
10
11
   for (auto& itr : passCode)
   {
      itr == ' ' ? itr = '_' : itr;
   }
awesome, thanks for the information. I will read up on code tags as well. Just getting into programming so have to learn the ropes!
@Furry Guy, I don't know why you guys complicate things for beginners, range based loops and auto keyword and conditional expressions are not needed in this very trivial case, just saying...
A trivial case is one of the best times to be exposed to different ways of doing the same logical process. Why not see in isolation what they can do.

There is a lot of features C++ has to offer for writing simple and clean code. Ways that are more robust than older standard features.

Range based for loops are by design not likely to go out of bounds with a container such as a std::string.

Modern C++ is not stone knives and bear claws.

Why is your use of std::replace acceptable for a beginner when using range-based for loops, auto, etc. is not?
Last edited on
I don't know why you guys complicate things for beginners, range based loops and auto keyword and conditional expressions are not needed in this very trivial case, just saying...

Range-based loops are simpler than their bounded counterparts!
mbozzi wrote:
Range-based loops are simpler than their bounded counterparts!

I did offer the range based loop as an ALTERNATE way to do the same task as originally written.

Now the OP has been shown there is not one and only one way to construct a for loop.

Or do logical checking with if blocks.

I could have added a for loop snippet that used std::string::iterator, but I decided that might be a bit too much to digest all in one serving.

...complicate things for beginners

Of course, let's do things the way they've always been taught, writing code that is years and decades out of date. Prone to errors and possible code rot.

When should beginners be exposed to "advanced" language features? Long after doing things the C++98 way has become so ingrained learning C++11 or later is harder if not impossible?

C++ is evolving into a safer language, why not take advantage of what it has to offer?
Last edited on
so iterating through a sequence of characters using an index is out of date, don't be silly, apart from that what you said makes sens but please don't forget that we are helping a novice, not building a commercial application LOL
Last edited on
so iterating through a sequence of characters using an index is out of date, don't be silly

According to the experts we should never write loops.
If there is no STL algorithm we should write our own.
In this topic using std::replace_if would be the way to go.
fewdiefie wrote:
I don't know why you guys complicate things for beginners, range based loops and auto keyword and conditional expressions are not needed in this very trivial case, just saying...


I think you may be battling against the stream and modern programming style, @fewdiefie.

If you are iterating through an entire array then a range-based loop is simpler, safer and possibly open to multi-processor or multi-thread optimisation. If you compare with python, there the standard loop is a range-based loop ("for x in A:"). In cases where the actual index isn't being used as a number ... there is little point in having that index. (An "array operation" would be even better, but valarrays are the only things in c++ that do that.) Some collections are tree-based and don't have an index - e.g. sets or maps; range-based loops are very useful there.

The "auto" is also useful. Again, think of python - types exist, but if the compiler/interpreter is perfectly capable of working them out, why state those types explicitly? Also, if there is going to be any difficulty over character types (signed char, unsigned char, wchar, ...) then this removes the worry of thinking which they are; similarly with numerical types.

Conditional expressions (I assume you meant "ternary operator") are easy enough. I mean, they have existed in Excel spreadsheets for a very long time!
Last edited on
so iterating through a sequence of characters using an index is out of date

A range-based for loop DOES iterate through a container sequentially, just not in your "this is how I was taught so everyone must learn it this way" manner.

Since you are so allergic to the concept of auto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>

int main()
{
   std::string passCode { "1 2  a   4" };

   for (char& itr : passCode)
   {
      if (itr == ' ')
      {
         itr = '_';
      }
   }

   std::cout << passCode << '\n';
}


we are helping a novice, not building a commercial application

Too many commercial apps suffer from legacy code that has to be coddled and cajoled just to survive should a bug need to be fixed or a capability requires modification.

Why accept without comment instructing beginners about std::string? Clearly that is a high level construct unsuitable except for experts, right? C strings should be the only allowed method for dealing with character sequences for noobs.

I don't believe there is One True Way To Do Code.

A very common and yet mythical idea is "to learn C++ one must first learn C." That is the 1st of 5 popular myths about C++.

Let Bjarne Stroustup explain:
https://isocpp.org/blog/2014/12/myths-1

For someone who complained about range-based for loops, auto, etc, it is a bit strange you would show std::replace to a beginner.

In this topic using std::replace_if would be the way to go.
std::replace doesn't need a predicate function when the replacement is as simple as '_' for ' '.
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <string>
#include <algorithm>

int main()
{
   std::string passCode { "1 2  a   4" };

   std::replace(passCode.begin(), passCode.end(), ' ', '_');

   std::cout << passCode << '\n';
}

According to the experts we should never write loops.
If there is no STL algorithm we should write our own.

Writing an algorithm that iterates through a container, especially when done sequentially, kinda requires some form of a loop. Look at the possible implementations of std::replace & std::replace_if:
https://en.cppreference.com/w/cpp/algorithm/replace
Last edited on
Writing an algorithm that iterates through a container, especially when done sequentially, kinda requires some form of a loop

Of course you will have to write loops in your algorithms, I am not sure if using std::for_each would be a solution.
Modern C++ is also about expressing intention.
Calling std::replace makes it more obvious than just a loop.
Calling std::replace makes it more obvious than just a loop.

But it isn't the One True Way To Teach C++ that most course outlines and instructors insist on using. Which is a shame since students are exposed to writing "modern" C++ concepts far too late IMO to really be beneficial in using all of what C++ has to offer.
Yes, it's a shame what many students learn nowadays. It seems many teachers still live in the 90s and don't know how C++ has changed.
5 Popular Myths about C++ continue to be believed:
https://isocpp.org/blog/2014/12/five-popular-myths-about-c-bjarne-stroustrup

5 and a half years later nothing has changed.
iterating through a sequence of characters using an index is out of date
There are at least two major advantages to using the standard algorithms over roll-your-own loops:
1. Correctness: the standard library contains code that is highly likely to be correct.
2. Recognizability: standard algorithms have known post-conditions, handle corner cases gracefully, and have known (good) asymptotic complexity.

There are other advantages (genericity, e.g.), but those are the most important. Hand-rolled loops are not assuredly correct, nor are they recognizable by name. They might introduce subtle performance issues, fail to address corner cases, and it can be tricky to guarantee their post-conditions.

conditional expressions
Unless we're planning to deep dive into the properties of the expression c? x: y, the conditional operator can be taught to a noob who understands if in about five minutes + some exercises.

I am not sure if using std::for_each would be a solution.
WRT std::for_each specifically, it's been subsumed by range-based loops (IMO) unless we're interested in its parallel versions or are already working with iterator pairs.

Last edited on
Topic archived. No new replies allowed.