# [C++] Printing a string character by character.

This topic is 2415 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi everyone, first time poster here.

Just wanted to say that it seems like you have a great community going here. I'm a complete rookie in C++, and I've been trying to find some good tutorials to practice with. So far, I'm in way over my head, but day by day it gets less confusing, and that's a good thing. I decided, though, that the best way to go about learning is to try my hand at making a text-based game from scratch, using only reference sites.

I recently stumbled across this forum post describing how to print out a string, character by character, using iterators. Full disclosure: I haven't reached iterators in my tutorials yet.

Code follows:

// builder.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <cstdlib> #include <iostream> #include <string> #include <windows.h> int main() { typedef std::string::const_iterator iter; std::string msg ( "This is a message" ); iter begin = msg.begin(); iter end = msg.end(); for ( iter it = begin; it != end; ++it ) { std::cout.put ( *it ); Sleep (75); } std::cout<<std::endl; }

This is perfect. Exactly the right speed, exactly what I wanted it to do. The only problem is that it uses a static value for the string ("This is a message"), whereas I'd like my entire (text-based) game to be displayed with this scrolling effect. The idea is that I include the above code in a separate header file, and call to the function whenever text needs to be displayed, thereby creating the desired effect for all the text in the game (except menus, which will have their own header file).

I'm having a really hard time trying to convert the function from static input to dynamic input; any ideas how I might get this done?

Thanks in advance for the patience, I still don't quite know my elbow from my ass.

##### Share on other sites
Well you're 90% of the way there, just move your existing code into a separate function and pass the msg as a parameter.
 void slow_type(const std::string & msg) { typedef std::string::const_iterator iter; iter begin = msg.begin(); iter end = msg.end(); for ( iter it = begin; it != end; ++it ) { std::cout.put ( *it ); Sleep (75); } std::cout<<std::endl; } 

##### Share on other sites
Ahh, that must be the 'thinking outside the box' people keep raving on and on about.

Worked perfectly with a forward declaration. Thanks so very much. And if it's alright with your community, I might periodically show the work on my game for suggestions on optimization. ^^

##### Share on other sites
Hi guys, quick bump on this, here's the code for my main menu, with custom commands:

commands.h

#include "stdafx.h" #include <string> #include "statUI.h" string Command; void CmdPrompt(); void NewGame(); void Credits(); int Menu; void CmdPrompt() { if (Command=="/r") Menu = 0; if (Command=="N"||"n") Menu = 1; if (Command=="C"||"c") Menu = 3; switch(Menu){ case 0: statUI(); break; case 1: NewGame(); break; case 3: Credits(); break; } _getch(); }

And here are the contents of StatUI, #included above:

#include <iostream> #include <conio.h> using namespace std; int Gold; void statUI() { system("cls"); cout << "\n\tGold: " << Gold << "\t\t\t\t\tWinter, Year 1" << endl; cout << "\t-------------------------------------------------------" << endl; _getch(); }

And finally, the main .cpp file with all the #includes:

// builder.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "commands.h" #include <dos.h> #include <stdio.h> #include <conio.h> #include <cstdlib> #include <iostream> #include <string> #include <Windows.h> #include "sType.h" #include "intro.h" #include "NewGame.h" #include "Credits.h" void Splash(); int main() { Splash(); _getch(); return 0; }

I know the code is messy, I'm sorry. It's basically all patchwork. I'm more concerned with actually building something, and figuring it out as I go.

So the problem here is, when I run the program, everything launches fine, except no matter what I choose, it always executes the Credits(); function. This happened after implementing the switch(Main) function in commands.h. Previously, I had been using an if/else statement, but it also had the problem of only executing the NewGame(); function.

Any assistance would be greatly appreciated.

##### Share on other sites
You can't do something like (a == 'a' || 'b'), you need to do (a == 'a' || a == 'b').

##### Share on other sites
Heh, the devil's in the details. Thanks again for your help.

##### Share on other sites
[color="#000088"]for [color="#666600"]( iter it [color="#666600"]= [color="#000088"]begin[color="#666600"]; it [color="#666600"]!= [color="#000088"]end[color="#666600"]; [color="#666600"]++it [color="#666600"])

Why are you starting on the second character?

##### Share on other sites
What are you talking about? That doesn't start at the second character.

##### Share on other sites

[color="#000088"]for [color="#666600"]( iter it [color="#666600"]= [color="#000088"]begin[color="#666600"]; it [color="#666600"]!= [color="#000088"]end[color="#666600"]; [color="#666600"]++it [color="#666600"])

Why are you starting on the second character?

Why do you think it would start on the second character?

begin seems to be initialized as .begin(), which should point to the first character.

##### Share on other sites

[quote name='Serapth' timestamp='1310579365' post='4834922']
[color="#000088"]for [color="#666600"]( iter it [color="#666600"]= [color="#000088"]begin[color="#666600"]; it [color="#666600"]!= [color="#000088"]end[color="#666600"]; [color="#666600"]++it [color="#666600"])

Why are you starting on the second character?

Why do you think it would start on the second character?

begin seems to be initialized as .begin(), which should point to the first character.
[/quote]

Brain fart, ignore me.

##### Share on other sites
I'm going to jump in and suggest that you might want to create a second function that also lets you specify the sleep duration, in case you ever want to do it a lot faster or slower. Something like this:

void slow_type(const std::string & msg) { variable_type(msg, 75); }

void variable_type(const std::string & msg, long sleepDuration) { typedef std::string::const_iterator iter; iter begin = msg.begin(); iter end = msg.end(); for ( iter it = begin; it != end; ++it ) { std::cout.put ( *it ); Sleep (sleepDuration); } std::cout<<std::endl; }

That way game over could frustratingly type out across the screen as slow as possible, while effects or whatever could flash out relatively fast (but not so fast as to appear instant). Or not.

##### Share on other sites

I'm going to jump in and suggest that you might want to create a second function that also lets you specify the sleep duration, in case you ever want to do it a lot faster or slower.

Much obliged, I actually have something similar running now.

Another update: work is coming along splendidly, and my interest/motivation for completing this project are quite high. I'm currently stuck on this problem however:

I'm trying to pass the value of the int Profile to the function NewGame(). The idea is that while Profile = 0 (new savegame), the NewGame() function will open up a Savegame menu, and as soon as it's done, will return a value of Profile = 1, allowing the function to progress.

void Intro() { int Profile; Profile = 0; system("cls"); cout << "\n\t\t\t\t\t\t"; Sleep(3500); sType("...Where the fuck am I?"); Sleep(5000); system("cls"); cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t"; sType("Does it really matter?"); Sleep(3500); sType("\n\n\tThis place can be whatever you want it to be."); Sleep(6000); system("cls"); cout << "\n\n\n\n\n\n\n\n\n\n\t\t\t\t"; Sleep(3500); Gears(); NewGame(Profile); }

void NewGame(int Profile) { while (Profile = 0) { void NewSaveScreen(); NewSaveScreen(); } system("cls"); cout << "\n\n\t"; Sleep(3500); sType("> Welcome to Gears. Would you like to read the tutorial?"); cin >> TutReq; if (TutReq=="Y"||TutReq=="y") { Tutorial(); } else Beginning(); }

You might see something I don't here; for some reason, the program will jump over the "while" statement (tried using if/else as well) and go straight to system("cls") in the NewGame() function. I tried using cout to determine the value of Profile both before and after being passed off from the first function to the second, and both values are 0 as they should be.

Any ideas?

##### Share on other sites

[quote name='SkoobyD00' timestamp='1310608489' post='4835087']
I'm going to jump in and suggest that you might want to create a second function that also lets you specify the sleep duration, in case you ever want to do it a lot faster or slower.

Much obliged, I actually have something similar running now.

Another update: work is coming along splendidly, and my interest/motivation for completing this project are quite high. I'm currently stuck on this problem however:

I'm trying to pass the value of the int Profile to the function NewGame(). The idea is that while Profile = 0 (new savegame), the NewGame() function will open up a Savegame menu, and as soon as it's done, will return a value of Profile = 1, allowing the function to progress.

void Intro() { int Profile; Profile = 0; system("cls"); cout << "\n\t\t\t\t\t\t"; Sleep(3500); sType("...Where the fuck am I?"); Sleep(5000); system("cls"); cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t"; sType("Does it really matter?"); Sleep(3500); sType("\n\n\tThis place can be whatever you want it to be."); Sleep(6000); system("cls"); cout << "\n\n\n\n\n\n\n\n\n\n\t\t\t\t"; Sleep(3500); Gears(); NewGame(Profile); }

void NewGame(int Profile) { while (Profile = 0) { void NewSaveScreen(); NewSaveScreen(); } system("cls"); cout << "\n\n\t"; Sleep(3500); sType("> Welcome to Gears. Would you like to read the tutorial?"); cin >> TutReq; if (TutReq=="Y"||TutReq=="y") { Tutorial(); } else Beginning(); }

You might see something I don't here; for some reason, the program will jump over the "while" statement (tried using if/else as well) and go straight to system("cls") in the NewGame() function. I tried using cout to determine the value of Profile both before and after being passed off from the first function to the second, and both values are 0 as they should be.

Any ideas?
[/quote]

Your problem in in the line while (Profile = 0) what this does is it assigns the value of 0 to profile. What you need to do is change it to while( Profile == 0 ). == is used to compare values in c++

Good Luck
Taliesin

##### Share on other sites
I seem to have a big problem with operators, huh? Thanks for the quick response, it's always frustrating to struggle with something for a whole day and find out it has such a simple solution.

##### Share on other sites
Turn your compiler warning levels up. The compiler should warn you about assignment within conditional expresion in this case.

##### Share on other sites
Hello again, O masters of all things code-y.

Ran into another problem. I've essentially got my menu system up and running, with a slight error. My program will take input from the user, convert the input to a number which is then assigned to a Menu integer. The Menu header reads this integer, and writes the menu to the screen when called.

However, for some reason, the menu is stuck on "Command List". I've tried switching the sent integer value to Menu = 7; and doing MenuDisplay(Menu), but that doesn't seem to work either.

commands.h:

void CmdSel() { if (Command=="M"||Command=="m") Menu = 0; else if (Command=="N"||Command=="n") Menu = 1; else if (Command=="L"||Command=="l") Menu = 2; else if (Command=="C"||Command=="c") Menu = 3; else if (Command=="/i") Menu = 7; else if (Command=="/c") Menu = 8; else { sType("\tInvalid key selection. Please choose again.\n"); CmdPrompt(); } switch(Menu){ case 0: Splash(); break; case 1: Beginning(); break; case 2: LoadGame(); break; case 3: Credits(); break; case 7: Inventory(); case 8: CmdMenu(); break; } _getch(); } void CmdPrompt() { cout << "\tFor help with commands, type /c" << endl; sType("\n\t> "); cin >> Command; CmdSel(); } void CmdMenu() { MenuDisplay(8); sType("\n\t\t(M)\t\t\tMain Menu"); sType("\n\n\t\t(/c)\t\t\tCommand List"); sType("\n\n\t\t(/r)\t\t\tResource Menu"); sType("\n\n\t\t(/i)\t\t\tInventory Menu"); sType("\n\n\t\t(/b)\t\t\tBuilding Menu"); sType("\n\n\t\t(/m)\t\t\tMining Actions"); sType("\n\n\t\t(N)\t\t\tNew Game (Main Menu only)"); sType("\n\n\t\t(L)\t\t\tLoad Game"); sType("\n\n\t\t(S)\t\t\tSave Game"); cout << "\n\t-------------------------------------------------------" << endl; sType("\n\t Please select a command:"); sType("\n\t> "); cin >> Command; CmdSel(); }

 string MenuHead; void MenuDisplay(int Menu) { switch(Menu) { case 1: MenuHead = "Menu - New Game"; case 7: MenuHead = "Menu - Inventory"; case 8: MenuHead = "Menu - Command list"; } system("cls"); cout << "\n\t " << MenuHead << endl; cout << "\t-------------------------------------------------------" << endl; }

And finally, the call to menu printing function:

void Inventory() { MenuDisplay(7); sType("\n\n\t\tPickaxe:\t\t[") ; if (HavePickaxe==1) sType("x]"); else sType(" ]"); _getch(); }

So, as mentioned above, when the user gets to the Splash() page, they can input "/i" to access the Inventory screen. The command does indeed lead to the right screen, but the menu Header is stuck on "Menu - Command List".

Any idea why this is happening?

##### Share on other sites
You need to put a break; after each chunk of code in a switch/case. Otherwise, once the code matches a case, it just keeps on running until it hits the end of the switch. A break informs the compiler that you want each case to be isolated without what is known as "falling through" to subsequent cases.

##### Share on other sites
Works perfectly... live and learn.

By the by, is it bothersome that I keep posting in the same thread? I figure it'd be bad etiquette to make a new one for every little problem I run into.

Thanks again for being so helpful, guys. I definitely feel the love.

##### Share on other sites
It's cool either way :-) The benefit to starting new threads is that it helps people jump in since they don't have to wade through the history to see what's already working - they can go straight to the latest problem.

Up to you, though, really. Just use common sense :-)