It is possible to do next:
Let say I have a string "input" (that will be a input), I will cut this input in 2 parts, next, I will find if I entered first part only letters, and second part only digits? the code work only for letters but not for digits(remove comments, to see that all entered will be valid)
#include <iostream>
#include <string>
#include <iomanip>
#include <cctype>
using namespace std;
int main ()
{
while (true)
{
bool flag = false; // to check for numeric entry
string input; // not req to initialize
string input1;
cout << "Enter the string like ABC 123: ";
getline (cin, input);
if (input == "")
{
flag = true;
}
if (string::size_type pos = input.find (' '))//spliting the input in 2 if it will find a space
{
if (input.npos != pos)
{
input1 = input.substr (pos + 1);
input = input.substr (0, pos);
}
}
for (int i = 0; i < input.size (); i++)
{
// for (int n = 0; i < input1.size (); i++)
// {
int uppercaseCHar = toupper (input[i]);//checking if input(first part) contains only letters
if (!std::isalpha (uppercaseCHar))
{
// if(isdigit(input1[n]) == 0)//checing if input1(second part) contains only digits
// {
flag = true;
break;
// }
}
// }
}
if (input.compare ("1") == 0) break;//This will end program
{
flag = false;
}
if (flag)
{
cout << "Invalid!\n";
cout << endl;
} else
{
cout << "The string is valid! \n";
cout << endl;
}
}
}
Enter the string like ABC 123: QWE 123
The string is valid!
Enter the string like ABC 123: QW1 123
Invalid!
I don't have rights to comment yet, but if your first and second part of string don't have to be of same length, you can use the for loop two times for each sub string and then compare the values by one character at a time.
Also after checking for termination condition by
if (input.compare ("1") == 0) break;
you are adding a statement
{
flag = false;
}
this will set the result to false even if you have compared in your loop and found it TRUE,so take a look at following code below, i have commented that block of code out.
#include <iostream>
#include <string>
#include <iomanip>
#include <cctype>
using namespace std;
int main ()
{
while (true)
{
bool flag = false; // to check for numeric entry
string input; // not req to initialize
string input1;
cout << "Enter the string like ABC 123: ";
getline (cin, input);
if (input == "")
{
flag = true;
}
if (string::size_type pos = input.find (' '))//spliting the input in 2 if it will find a space
{
if (input.npos != pos)
{
input1 = input.substr (pos + 1);
input = input.substr (0, pos);
}
}
//cout<<"\n"<<input1;
//cout<<"\n"<<input;
//First check the letter part (first part) if it contains digits
for(int i=0;i<input.size();i++){
if(!std::isalpha(input[i])){
flag=true;
break;
}
}
//second check if the numeric part (second part) only contains digits
for(int i=0;i<input1.size();i++){
if(!std::isdigit(input1[i])){
flag=true;
break;
}
}
/*
for (int i = 0; i < input.size (); i++)
{
for (int n = 0; i < input1.size (); i++)
{
int uppercaseCHar = toupper (input[i]);//checking if input(first part) contains only letters
if (!std::isalpha (uppercaseCHar))
{
if(isdigit(input1[n]) == 0)//checing if input1(second part) contains only digits
{
flag = true;
break;
}
}
}
}
*/
if (input.compare ("1") == 0) break;//This will end program
//after checking for break, if you add flag=false, it will automatically ignore whatever flag you set, and you will always find FLAG=FALSE when compairing in upcoming lines
//{
// flag = false;
//}
if (flag)
{
cout << "Invalid!\n";
cout << endl;
} else
{
cout << "The string is valid! \n";
cout << endl;
}
}
}
Related
I am trying to make a program in which a user enters a string and i will print out the second word in the string with its size.
The delimiter's are space( ), comma(,) and tab( ).
I have used a character array and fgets to read from user and a character pointer that points to the first element of the array.
source code:
#include"iostream"
#include<stdio.h>
#include<string>
using namespace std;
// extract the 2nd word from a string and print it with its size(the number of characters in 2nd word)
int main()
{
char arr[30], arr1[30];
char *str = &arr1[0];
cout<<"Enter a string: ";
fgets(str, 30, stdin);
int i = 0, j, count = 1, p = 0; // count is used to find the second word
// j points to the next index where the first delimiter is found.
// p is used to store the second word found in character array 'arr'
while(*(str+i) != '\n')
{
if(*(str+i) == ' ' || *(str+i) == ',' || *(str+i) == ' ')
{
count++;
if(count == 2)
{
// stroing 2nd word in arr character array
j = i+1;
while(*(str+j) != ' ' || *(str+j) != ',' || *(str+j) != ' ')
{
arr[p] = *(str+j);
cout<<arr[p];
p++;
i++;
j++;
}
break;
}
}
i++;
}
arr[p+1] = '\0'; // insert NULL at end
i = 0;
while(arr[i] != '\0')
{
cout<<arr[i];
i++;
}
cout<<"("<<i<<")"<<endl;
return 0;
}
Help me out with this.
To start, don't use std::cin for testing. Just set a value in your code for consistency and ease of development. Use this page for a reference.
#include <iostream>
#include <string>
int main() {
std::string str("this and_that are the tests");
auto start = str.find_first_of(" ,\n", 0);
auto end = str.find_first_of(" ,\n", start + 1);
std::cout << str.substr(start, end - start);
return 0;
}
And this is still somewhat of a hack, it just depends where you are going. For instance the Boost library is rich with extended string manipulation. If you are going to parse out more than just one word it can still be done with string manipulations, but ad-hoc parsers can get out of hand. There are other tools like Boost Spirit to keep code under control.
The delimiters used when extracting from a stream depends on the locale currently in effect. One (cumbersome) way to change the extraction behaviour is to create a new locale with a special facet in which you specify your own delimiters. In the below example the new locale is used to imbue a std::stringstream instead of std::cin directly. The facet creation part is mostly copy/paste from other answers here on SO, so you'll find plenty of other examples.
#include <iostream>
#include <locale> // std::locale, std::ctype<char>
// https://en.cppreference.com/w/cpp/locale/ctype_char
#include <sstream> // std::stringstream
#include <algorithm> // std::copy_n
#include <vector> // a container to store stuff in
// facet to create our own delimiters
class my_facet : public std::ctype<char> {
mask my_table[table_size];
public:
my_facet(size_t refs = 0)
: std::ctype<char>(&my_table[0], false, refs)
{
// copy the "C" locales table to my_table
std::copy_n(classic_table(), table_size, my_table);
// and create our delimiter specification
my_table[' '] = (mask)space;
my_table['\t'] = (mask)space;
my_table[','] = (mask)space;
}
};
int main() {
std::stringstream ss;
// create a locale with our special facet
std::locale loc(std::locale(), new my_facet);
// imbue the new locale on the stringstream
ss.imbue(loc);
while(true) {
std::string line;
std::cout << "Enter sentence: ";
if(std::getline(std::cin, line)) {
ss.clear(); // clear the string stream from prior errors etc.
ss.str(line); // assign the line to the string stream
std::vector<std::string> words; // std::string container to store all words in
std::string word; // for extracting one word
while(ss>>word) { // extract one word at a time using the special facet
std::cout << " \"" << word << "\" is " << word.size() << " chars\n";
// put the word in our container
words.emplace_back(std::move(word));
}
if(words.size()>=2) {
std::cout << "The second word, \"" << words[1] << "\", is " << words[1].size() << " chars\n";
} else {
std::cout << "did not get 2 words or more...\n";
}
} else break;
}
}
#include"iostream"
#include<stdio.h>
#include<string>
#include <ctype.h>
using namespace std;
int main()
{
char c;
string str;
char emp = ' ';
cout<<"Enter a string: ";
getline (cin,str);
int j = 0, count = 1, counter = 0;
for (int i = 0; i < str.length() && count != 2; i++)
{
cout<< str[i] <<endl;
if( isspace(str[i]) || str[i] == ',' || str[i] == '\t' )
{
count++;
if(count == 2)
{
j = i+1;
while(j < str.length())
{
if (isspace(str[j]) || str[j] == ',' || str[j] == '\t')
{
break;
}
cout<<str[j];
counter++;
j++;
}
cout<<endl;
}
}
}
cout<<"size of the word: "<<counter<<endl;
return 0;
}
This is a simple answer to what you want, hope to help you.
// Paul Adrian P. Delos Santos - BS Electronics Engineering
// Exercise on Strings
#include <iostream>
#include <sstream>
using namespace std;
int main(){
// Opening Message
cout << "This program will display the second word and its length.\n\n";
// Ask for a string to the user.
string input;
cout << "Now, please enter a phrase or sentence: ";
getline(cin, input);
// Count the number of words to be used in making a string array.
int count = 0;
int i;
for (i=0; input[i] != '\0'; i++){
if (input[i] == ' ')
count++;
}
int finalCount = count + 1;
// Store each word in a string array.
string arr[finalCount];
int j = 0;
stringstream ssin(input);
while (ssin.good() && j < finalCount){
ssin >> arr[j];
j++;
}
// Display the second word and its length.
string secondWord = arr[1];
cout << "\nResult: " << arr[1] << " (" << secondWord.size() << ")";
return 0;
}
I'm in the process of writing the program and stumbled upon a few issues.
The code reads a text file, which contains a list of 20 string words. The function playHangman() is supposed to read the file and randomly picks one word, which is displayed as asterisks in the console. The code works fine with local words when the function is called. For example Playhangman("stackOverflow"), will show the exact number of characters and will loop through them until the word is guessed right. If you take a look at the code, I'm calling the random word into the function. That word is stored as array. I know that that's not the proper way to do randomize, but for now, even if it picks the same word over and over, that's Ok, I just need to make sure it actually reads the array. The other thing is, when all characters are revealed, all the words on that text file are displayed, looks like I'm calling the entire content of the array instead of just that random word that's supposed to be generated.
Any help would be appreciated, thank you!
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string word[20];
string randomWord = word[rand() % 20];
int playHangman(string randomWord) {
int misses = 0;
int revealedletters = 0;
string display = randomWord;
ifstream textFile;
// Open file
textFile.open("hangman.txt");
// Check if file exists
if (!textFile) {
cerr << "Unable to open text file\n";
exit(1); // Call system to stop
}
else {
cout << "File opened successfully. Program will continue...\n\n";
// Loop through the content of the file
while (textFile >> randomWord) {
for (int i = 0; i < display.length(); i++)
display[i] = '*';
while(revealedletters < randomWord.length()) {
cout << "Misses: " << misses << endl;
cout << "Enter a letter in word ";
cout << display << " : ";
char response;
cin >> response;
bool goodGuess = false;
bool duplicate = false;
for (int i = 0; i < randomWord.length(); i++)
if (response == randomWord[i]) {
if (display[i] == randomWord[i]) {
cout << response << " is already in the word." << endl;
duplicate = true;
break;
}
else {
display[i] = randomWord[i];
revealedletters++;
goodGuess = true;
}
}
if (duplicate)
continue;
if (!goodGuess) {
misses++;
cout << response << " is not in word\n";
}
}
cout << "You guessed right! The word is " << randomWord << ".\n";
}
return misses;
}
}
// TODO: Do you want to guess another word, Y/N?
int main () {
playHangman(randomWord);
// TODO: number of misses to guess the word.\n";
}
In your declaration and initialisation of your global variables:
string word[20];
string randomWord = word[rand() % 20];
word is an array of 20 empty strings and therefore randomWord will also always be empty.
In your playHangman function you have:
while (textFile >> randomWord) {
for (int i = 0; i < display.length(); i++)
display[i] = '*';
while(revealedletters < randomWord.length()) {
......
This reads a single word from the file into randomWord, plays the game with that word then loops round to read the next word and plays again with that word. As revealedletters doesn't get reset the game will finish immediately if the first word is longer than the next one.
I think the code you actually want looks something like this (remove your global variables too):
std::string word;
std::vector<std::string> words;
while (textFile >> word) {
words.push_back(word);
}
randomWord = words[rand() % words.size()];
std::string display = std::string(randomWord.size(), '*');
while(revealedletters < randomWord.length()) {
......
If you really must use arrays:
const size_t maxWords = 20;
std::string words[maxWords];
size_t wordCount = 0;
while (textFile >> word && wordCount < maxWords) {
words[wordCount++] = word;
}
randomWord = words[rand() % wordCount];
std::string display = std::string(randomWord.size(), '*');
while(revealedletters < randomWord.length()) {
......
I am trying to allow only integrers to be inputted
Should Reject:
5h
3.4
3.gh
3.0
htr
Should Accept:
-5
0
78
Current Code
int getIntInput() {
int userInput;
while (true) {
std::cout << "> ";
std::cin >> userInput;
std::cout << std::flush;
if (std::cin.fail()) {
std::string cinBuffer;
std::cin.clear();
std::getline(std::cin, cinBuffer);
continue;
}
break;
}
return userInput;
}
Updated Code
Issues:
Accepts all rejections excluding "htr" (No numerals)
int getIntInput() {
std::string rawInput;
int parsedinput;
while (true) {
std::cout << "> ";
std::getline(std::cin, rawInput);
std::cout << std::flush;
try {
parsedinput = std::stoi(rawInput);
} catch (std::invalid_argument & e) {
continue;
} catch (std::out_of_range & e) {
continue;
}
break;
}
return parsedinput;
}
Finished Code
Accepts only integers with an optional parameter which will allow
negative numbers to be accepted or rejected.
int getIntInput(bool allowNegatives = true) {
bool validIntInput;
std::string rawInput;
int parsedinput;
while (true) {
validIntInput = true;
// Grabs the entire input line
std::cout << "> ";
std::getline(std::cin, rawInput);
std::cout << std::flush;
for (int i = 0; i < rawInput.length(); i++) {
// Checks to see if all digits are a number as well as to see if the number is a negative number
if (!isdigit(rawInput[i]) && !(allowNegatives && i == 0 && rawInput[i] == '-')) {
validIntInput = false;
break;
}
}
if (!validIntInput) {
continue;
} else {
try {
// Try parse the string to an int
parsedinput = std::stoi(rawInput);
// Catch all possible exceptions, another input will be required
} catch (...) {
continue;
}
// If the code reaches here then the string has been parsed to an int
break;
}
}
return parsedinput;}
The way cin works when having to read an int, is that it starts parsing the integer and stops when it finds a non-int character, storing the parsed int in the variable. That's why on float numbers it stops on the dot and in input '5g' it will stop on g.
What you can do instead if you only want integer input, is to read the whole line and then check if every character in your string is numeric, with the following piece of code:
bool onlyNums = true;
for (int i=0;i<rawInput.size();i++) {
if (!isdigit(rawInput[i]))
onlyNums = false;
}
if (!onlyNums)
continue;
(You have to include ctype.h library for the above code)
If you don't mind the overhead, I would grab the input from cin with cin.getline() and save it into a string. Then loop through the string and call isdigit on each char. You can discard the chars that aren't digits by useing the str.erase function.
You will need to #include cctype for isdigit().
Note: this will have at least O(N) runtime based on the length of your string.
template<class T>
T findInStreamLineWith(std::istream &input) {
std::string line;
while (std::getline(input, line)) {
std::istringstream stream(line);
T x;
if (stream >> x >> std::ws && stream.eof()) {
return x;
}
// reenter value
// cout << "Enter value again: ";
}
throw std::invalid_argument("can't find value in stream");
}
…
auto x = findInStreamLineWith<int>(std::cin);
I want to view the word after it been confirm as palindrome. But the output ended up in different way than what I expected. Pls help me Configure what is my error from my codes
Output I want to achieved:
Enter a word Madam
Word is Palendrome: madam
#include <iostream>
#include <stack>
#include <string.h>
using namespace std;
int main ()
{
string words;
cout<<"Enter a word ";
cin>>words;
int wordSize = words.size();
stack<char> mystack;
for (int i=0; i<wordSize/2; ++i) {
mystack.push(tolower(words[0]));
words.erase(0,1);
}
if(words.size() > mystack.size()) {
words.erase(0, 1);
}
if(mystack.size() == 0) {
return true;
}
cout << "Popping out elements...";
while(!mystack.empty()) {
if(mystack.top() == words[0]) {
mystack.pop();
words.erase(0, 1);
if (mystack.size() == 0 || words.size() == 0) {
cout<<"Word is Palindrome: "<<<words<<endl;
return true;
}
}
else {
cout<<"Word is not Palindrome"<<endl;
return false;
}
}
}
I have a program that does three things. Asks you how many variables you wan't, ask you to input each variable, then stores it in a vector. I have put some code that checks if your input is correct, and if it isn't, re-loops the code asking for your variable. The problem I am having is that when you type anything in around the second variable, it asks you to try again infinitely.
For instance, if I typed these values into the input:
Variable amount: 5
Please input variable 1: 8
Please input variable 2: 8
ERROR, PLEASE ENTER ONLY VALID SYMBOLS
---------------------
Please input variable 2:
It would keep outputting ERROR, PLEASE ENTER ONLY VALID SYMBOLS over and over again no matter what you typed. The code is down below, and if you have a better name for this question please let me know. (I'm not really sure what to call this)
#include <iostream>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <sstream>
using namespace std;
int inputErrorMessage()
{
cout << "\n ERROR, PLEASE ENTER ONLY VALID SYMBOLS \n";
cout << "--------------------- \n";
return 0;
}
int main()
{
// Declare the variables, vectors, etc.
int varNum = 1;
int totVar = 0;
int choice = 0;
vector<int> userNums;
double input = 0;
string checktotVar = "";
string checkInput = "";
string sym = "";
bool valid = false;
stringstream sstotVar;
stringstream ssinput;
if (choice != 6) {
while (!valid) {
valid = true;
// Ask user for how many variables they want then record it
cout << "Variable amount: ";
getline(cin, checktotVar);
sstotVar << checktotVar;
sstotVar >> totVar;
if (sstotVar.fail() || totVar <= 0) {
inputErrorMessage();
valid = false;
sstotVar.clear();
sstotVar.ignore();
}
}
valid = false;
while (!valid) {
valid = true;
// Ask the user for each variable, then record it into the array
for (int i = 0; i < totVar; ++i) {
cout << "Please input variable " << varNum << ": ";
getline(cin, checkInput);
ssinput << checkInput;
ssinput >> input;
if (ssinput.fail()) {
inputErrorMessage();
valid = false;
ssinput.clear();
ssinput.ignore();
}
if (valid == true) {
userNums.push_back(input);
varNum++;
}
}
}
}
}
ssinput >> input;
reads the one thing in ssinput right to the end of the stream while leaving the read valid. The next time around
ssinput << checkInput;
can't write into the stream because the stream hit the stream's end. That means the read also fails and
if (ssinput.fail()) {
enters the body of the if where the program clears the error
ssinput.clear();
and then promptly reads off the end of the stream with
ssinput.ignore();
causing the error all over again.
Quickest solution:
Recreate
stringstream ssinput;
on each loop iteration. So
stringstream sstotVar;
//stringstream ssinput; gone from here
and
getline(cin, checkInput);
stringstream ssinput(checkInput); // and now tighter scope recreated each loop.
ssinput >> input;
Also by keeping the stream around without emptying it out it can get very., very big.
You can also simplify your logic around
while (!valid) {
and eliminate some repeated code by moving the read validation into it's own function
int getMeANumber(const std::string & message, int min)
that loops until it gets a number and then returns that number. For example:
int getMeANumber(const std::string & message, int min)
{
while (true)
{
cout << message;
string checktotVar;
getline(cin, checktotVar);
stringstream sstotVar(checktotVar);
int totVar;
sstotVar >> totVar;
if (!sstotVar || totVar <= min)
{
inputErrorMessage();
}
else
{
return totVar;
}
}
}
Now main is this itty-bitty tiny lil' thing.
int main()
{
int choice = 0;
vector<int> userNums;
if (choice != 6)
{
int totVar = getMeANumber("Variable amount: ", 0);
for (int i = 0; i < totVar; ++i)
{
stringstream varname;
varname << "Please input variable " << i+1 << ": ";
userNums.push_back(getMeANumber(varname.str(), numeric_limits<int>::min()));
// numeric_limits<int>::min requires #include <limits>
}
}
}
Here are the issues with this code.
In this part:
if (valid == true) {
userNums.push_back(input);
varNum++;
}
you forgot to add an ssinput.clear(). This will reset the stream state (clear the error flags), otherwise you cannot use it again. That is why it stops working at the second input.
In addition, even though this works, you are pushing back a variable that you declared as double into a vector of ints. That is bound to cause issues if this was intended to store double variables, instead of truncating them and storing them as ints.
It should be:
#include <iostream>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <sstream>
using namespace std;
int inputErrorMessage()
{
cout << "\n ERROR, PLEASE ENTER ONLY VALID SYMBOLS \n";
cout << "--------------------- \n";
return 0;
}
int main()
{
// Declare the variables, vectors, etc.
int varNum = 1;
int totVar = 0;
int choice = 0;
vector<int> userNums;
double input = 0;
string checktotVar = "";
string checkInput = "";
string sym = "";
bool valid = false;
stringstream sstotVar;
stringstream ssinput;
if (choice != 6) {
while (!valid) {
valid = true;
// Ask user for how many variables they want then record it
cout << "Variable amount: ";
getline(cin, checktotVar);
sstotVar << checktotVar;
sstotVar >> totVar;
if (sstotVar.fail() || totVar <= 0) {
inputErrorMessage();
valid = false;
sstotVar.clear();
sstotVar.ignore();
}
}
valid = false;
while (!valid) {
valid = true;
// Ask the user for each variable, then record it into the array
for (int i = 0; i < totVar; ++i) {
cout << "Please input variable " << varNum << ": ";
getline(cin, checkInput);
ssinput << checkInput;
ssinput >> input;
if (ssinput.fail()) {
inputErrorMessage();
valid = false;
}
if (valid == true) {
userNums.push_back(input);
varNum++;
}
ssinput.clear();
}
}
}
}
EDIT: You need to clear the stringstream on each iteration of the loop, otherwise you're not writing to an empty stream when you grab the next input from the user, which is what's causing the .fail() method to return true after the first iteration of the loop.