My for loop keeps looping and causes the program to crash - c++

I'm trying to make a program that will receive a string and output an uppercase version of that. My code works, however once it loops through the string and changes it, it immediately crashes and I'm not completely sure why. Here are my two pieces of code.
/*This program is to intended to receive a string and return a version of it in all upper case*/
#include <iostream>
#include <string>
#include <locale>
using namespace std;
string toUpper ( string str)
{
cout <<"\n"; //Puts spaces between the input and output
for (int i=0; i<str.length(); i++;)
std::cout << std::toupper(str[i]); //A loop which goes through each digit of the string
break;
cout <<"\n\n"; //Creates spaces after the output
return str;
}
/*This program calls a function to make a string in upper case*/
#include <iostream>
#include <string>
#include <sstream>
#include <locale>
#include "toUpper1.h" //Calls the header file which contains the loop
using namespace std;
int main ()
{
cout<<"\nPlease type in a word\n\n";
string input; //Creates a variable of cin that can be used in the toUpper command
cin>>input; //Makes a user input command part of the declared variable
cout<<toUpper(input); //The command that causes the user input string to be transformed into upper case
return 0;
}

You can make string to uppercase using code bellow
Boost string algorithms:
#include <boost/algorithm/string.hpp>
#include <string>
std::string str = "Hello World";
boost::to_upper(str);
std::string newstr = boost::to_upper_copy("Hello World");
Or use like this
#include <algorithm>
#include <string>
std::string str = "Hello World";
std::transform(str.begin(), str.end(),str.begin(), ::toupper);

You are breaking the function without returning anything. Use {} to close for loops if you want to use break
prog.cpp:16:5: error: break statement not within loop or switch
break;
Also your for loop has an extra ; at the end.

std::cout and std::toupper are useless as you are already including namespace std;
and why are you using break;? there is no need of it.
just write
for (int i=0; i<str.length(); i++)
cout << toupper(str[i]);
Remove break;

You are not transforming the string, you are outputting its transformation in the function.
instead of
std::cout << std::toupper(str[i]);
use
str[i]=std::toupper(str[i]);
And move all printing out of the function. Changing the string doesn't include printing!
Notice the #bbdude95 answer, too.
edit
Instead of
cout<<"\nPlease type in a word\n\n";
string input; //Creates a variable of cin that can be used in the toUpper command
cin>>input;
use
char input[256];
cout << "Please type in a word:\n>";
cin.getline( input, 256, '\n' );

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
string toUpper ( string str)
{
cout <<"\n"; //Puts spaces between the input and output
for (int i=0; i<str.length(); i++)
str[i] = std::toupper(str[i]); //A loop which goes through each digit of the string
//break;
cout <<"\n\n"; //Creates spaces after the output
return str;
}
int main ()
{
cout<<"\nPlease type in a word\n\n";
string input; //Creates a variable of cin that can be used in the toUpper command
cin>>input; //Makes a user input command part of the declared variable
//The command that causes the user input string to be transformed into uppe case
cout << toUpper(input);
cout << std::endl << "The original string is" << input << std::endl;
return 0;
}
EDIT: Note that keeping the function signature as above (string toUpper ( string str), as were required), we are making some extra string copies, and, most important: we are NOT modifying the original string (excute the code and see the result of last cout.

Related

How would I split up user input into a char and an integer?

I am working on a project where I have to parse data from user input.
#include <iostream> // for cin and cout
#include <iomanip> // for setw()
#include <cctype> // for toupper()
using namespace std;
int main(){
string playerInput;
cin >> playerInput;
//Player would input strings like C13,C 6, I1, Z 16, etc...
}
return 0;
I've tried something like this, which kinda works but only if the letter proceeds the number in the string.
int myNr = std::stoi(playerInput);
What my end goal is to grab the letter and number from the string, and place them in a char variable and a integer variable respectively. I am stuck on how to proceed from here and could use some help, thanks!
This is the simplest and the shortest way to achieve that (it also ignores spaces and tabs):
int main() {
char ch;
int n;
cin >> ch >> n;
cout << "ch = " << ch << ", n = " << n << endl;
}
I think that other answers are a bit overcomplicated.
You could do like what you had:
char letter = playerInput.front();
playerInput.erase(0);
int number = std::stoi(playerInput);
Of course, that doesn't allow for spaces. Removing spaces can be quite tedious, but it could be done like:
playerInput.erase(
std::remove_if(
begin(playerInput), end(playerInput),
[](uint8_t ch) { return std::isspace(ch); }),
end(playerInput));
Full Demo
Live On Coliru
#include <cctype> // for toupper()
#include <iomanip> // for setw()
#include <iostream> // for cin and cout
#include <algorithm> // for remove_if
static bool ignorable(uint8_t ch) {
return std::isspace(ch)
|| std::ispunct(ch);
}
int main() {
std::string playerInput;
while (getline(std::cin, playerInput)) {
playerInput.erase(
std::remove_if(
begin(playerInput), end(playerInput),
ignorable),
end(playerInput));
if (playerInput.empty())
continue;
char letter = playerInput.front();
playerInput.erase(begin(playerInput));
int number = std::stoi(playerInput);
std::cout << "Got: " << letter << " with " << number << "\n";
}
}
Prints
Got: C with 13
Got: C with 6
Got: I with 1
Got: Z with 16
You have the right idea in using std::stoi. My code expands your approach:
string playerInput;
getline(cin, playerInput);
char c1 = playerInput[0];
int num = stoi(playerInput.substr(1));
The above code receives an input string, then takes out the first character and uses std::stoi on the rest of the string.
Note that I use std::getline to account for the possibility of there being spaces in the input. If you are doing this repeatedly, you will need to add cin.ignore() after each getline() statement. See this link for more info.
std::cin stops reading input when it encounters a space. You can use std::getline() if your input has spaces. To parse your string, you should check out std::stringstream. It allows you to read from a string as if it were a stream like std::cin.
#include <iostream> // for cin and cout
#include <iomanip> // for setw()
#include <cctype> // for toupper()
#include <sstream>
int main(){
std::string playerInput;
int i;
char c;
std::getline(std::cin, playerInput); // Remove trailing newline
std::getline(std::cin, playerInput);
//Player would input strings like C13,C 6, I1, Z 16, etc...
//String Stream
std::stringstream playerInputStream(playerInput);
//Read as if you were reading through cin
playerInputStream >> c; //
playerInputStream >> i;
}
return 0;

Can we use vector in c++ to take user input of unknown size only till we hit enter?

I was trying to take user input in a vector in c++, as vector is a dynamic data structure i wanted it to take input as long as user wants and when the user hit enter key it should stop taking the input (just as a string) only difference i want to do it in an integer vector, but i am unable to do so let me know if it is possible or not to take user input in a vector like the way i described.
I have searched the web for various ways but still my code isn't running the way i want, I have tried breaking the loop of input by using EOF symbols but it is not stopping the loop of input.
I have tried using cin.ignore() function but it also takes spacebar in count
i only want to stop input when enter key is pressed.
below is the most recent code i made:
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int> v;
char c;
for(int i=0;;i++){
cin>>c;
if(c=='\n'){
break;
}
int x = c - '0';// typecasting char into integer.
v.push_back(x);
}
cout<<v.size()<<endl;// just to check if it is done taking input and what is the size of vector now.
}
You can use std::getline() to get the entire line and then std::istreamstream to get the integers into a vector:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
int main() {
std::string input;
std::getline( std::cin, input );
std::istringstream is( input );
std::vector<int> v( ( std::istream_iterator<int>( is ) ), std::istream_iterator<int>() );
std::cout << v.size() << "\n";
return 0;
}
Read the entire line as string and build each number. Something like that:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string s; getline(cin, s);
int num = 0;
vector<int> v;
for(int i = 0; i < s.size(); ++i)
if(s[i] == ' ')
v.push_back(num), num = 0;
else
num = num*10 + (s[i]-'0');
v.push_back(num);
cout << v.size() << endl;
return 0;
}
You just have to input Vector elements as a single string and use Stringstream function to assign elements in increasing order of vector's indices respectively.
Here's the code :
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> v;
string buffer;
int data;
getline(cin,buffer);
istringstream iss(buffer);
while(iss>>data){
v.push_back(data);
}
cout<<v.size()<<" ";
cout<<"Vector Elements"<<endl;
for(int k=0;k<v.size();k++){
cout<<v[k]<<" ";
}
return 0;
}
When you read from std::cin, it will accept an entire line from the console. Your cin>>c will retrieve the first character of the line and put that character into the variable c.
This means your if(c=='\n') is pretty much pointless since the line will be consumed and you won't see an explicit '\n' as the first character...EVER.
c - '0' will convert a single ASCII character that is a digit (i.e. 0123456789) to a number you can use, but that is NOT typecasting a char into an integer. That's converting an ASCII character that happens to be a number into a numeric value. A type cast is when you change the TYPE of a value to another TYPE.
I think you want to do something like the following...
#include <iostream>
#include <vector>
#include <stdio.h>
#include <conio.h>
int main( int cArguments, const char** apszArguments ) {
std::vector<char> vchars;
char c;
do {
c = getche();
vchars.push_back( c );
} while( c != '\n' );
std::cout << vchars.size() << " characters received" << std::endl;
return 0;
}
Note that on macOS and some Linux variants, getch/getche are not defined and you'll need to use termios or ncurses functions instead.

String to Integer Conversion

Program 1: Program 1 takes a line of input from the console and divides the input string into sub strings separated by space and then converts into integer value.
#include <cstring>
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
char *input;
cin.getline(input,100);
char *token = strtok(input, " ");
while (token != NULL)
{
cout << token << '\n';
token = strtok(NULL, " ");
}
return 0;
}
Program 2:
#include <cstring>
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
char *input;
cin.getline(input,100);
int a[7];
char *token = strtok(input, " ");
while (token != NULL)
{
cout << token << '\n';
token = strtok(NULL, " ");
}
return 0;
}
Program 1 works fine but programs does not work. The only difference between two program is that, an additional array a[7] variable. How does this variable leads to crashing of program 2.
Because undefined behaviour.
You never allocate memory for input, so using it with getline is undefined behaviour.
It looks like you just want to read in some text and print it out, split on whitespace. You could just use std::string and operator>> on std::cin for this.
As mentioned by others, you get an undefined behavior because you didn't allocate memory for input.
You could fix the problem by declaring a char array or by doing things in a more "C++ way". Here's an example:
[run it online]
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main()
{
std::vector<int> a;
cout << "Enter a sequence of numbers: ";
std::copy(std::istream_iterator<int>(cin),
std::istream_iterator<int>(),
std::back_inserter(a));
cout << "You've entered: ";
for (auto& num : a)
{
cout << num << " ";
}
cout << endl;
return 0;
}
If you still want to limit the input till 100 (i.e. 'd'), you can getline() from cin to a std::string that you use to initialize a std::istringstream iss for instance. Then the std::copy() code is the same, just replace cin with iss.
// #include <sstream>
std::string input;
cin.getline(input, 100);
std::istringstream iss(input);
You have not allocated any memory for input to point to, and calling getline with an uninitialized pointer is undefined behavior.
That means that anything can happen, including your program working as you expected, or not working as expected. Adding the int a[7] just changed the memory layout of your program and consequently the behavior of the undefined behavior.
To fix it, you could simply make input a static array of the desired length:
char input[100];

Issue with substr C++

I am trying to make a program that reads a line from tst.txt using getline function. However when I try to get the substrings from it, I get an error that says method substr could not be resolved.
My code is the following.
#include <iostream>
#include <fstream>
#include <string>
#include <istream>
#include <sstream>
#include <stdlib.h>
using namespace std;
int main () {
string line;
string substr(int a, int b);
string name[15];
int a[15];
int b[15];
ifstream myfile ("tst.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
int i;
getline (myfile,line);
a[i]= myfile.substr(4,2);
name[i]= myfile.substr(18,15);
b[i]= myfile.substr(36,1);
i=i+1;
cout << a[i] <<" "<< b[i] << " "<< name[i] << endl;
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
As mentioned you can't call substr() with a std::ifstream. What you probably meant was to take the parts from the line string read in
a[i]= stoi(line.substr(4,2));
name[i]= line.substr(18,15);
b[i]= stoi(line.substr(36,1));
Also note you'll need to convert the substrings extracted to a number (instead of assigning them directly), hence I have added the stoi().
As also mentioned in the comments on your question, you should do better error checks, and initialize all of your variables properly.
Your while() loop can simply be rewritten as
while (getline (myfile,line)) {
// ...
}
The surrounding if() block
if (myfile.is_open()) {
// ...
}
can be omitted.
You actually prototype a function at line :
string substr(int a, int b);
But never implement it.
What is the point of this line anyways ?
Just remove it, you never call this substr function. The only substr function you call is
std::ifstream::substr
http://www.cplusplus.com/reference/string/string/substr/

Updating a string through iteration in C++

OK, so I'm trying to make a string thing, so that the string is updated. Sort of like you have a string "hello" and I want it to update itself somewhat like "h" "he" "hel" "hell" "hello"
So, I have:
#include <iostream>
#include <string>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
using namespace std;
int main()
{
system("title game");
system("color 0a");
string sentence = "super string ";
for(int i=1; i<sentence.size(); i++){
cout << sentence.substr(0, i) <<endl;
}
return 0;
}
The code returns out like:
"s
"su"
"sup"
"supe"
"super"
Obviously on different lines, but when I remove the end line, the sentence builder just goes berserk. It displays something like "spupsppuepr sttrrtrsubstringsubstring"
Is there anyway I can update the string on THE SAME LINE? (and not have it completely destroyed)
You could print a carriage return character '\r' at each iteration, returning the cursor to the beginning of the line:
for(int i=1; i<sentence.size(); i++){
cout << '\r' << sentence.substr(0, i);
}
Or just output each character in sequence:
for(int i=0; i<sentence.size(); i++){
cout << sentence[i];
}
You probably also want to insert a short delay for each loop iteration to achieve a typewriter effect.
Running your code produces this:
./a.out
ssusupsupesupersuper super ssuper stsuper strsuper strisuper strinsuper string
This is exactly what you tell it to do. It's the same as with the endl but without the newlines. If you don't want it to repeat all the letters, you need to iterate through the string itself, not through the substrings.
using namespace std;
int main()
{
system("title game");
system("color 0a");
string sentence = "super string ";
for(int i=0; i<sentence.size(); i++){
cout << sentence[i];
}
return 0;
}
My advice: use While loop.
#include <stdio.h>
#include <iostream>
int main() {
system("title game");
system("color 0a");
char* sentence = "super string";
while( *sentence ) std::cout << *sentence++;
return 0;
}