Using regex for input validation - c++

I know the following isn't the most efficient implementation (I could, after all, run regex_match() right in main() ) but it should still work, at least from my limited understanding.
I'm trying to use in C++11 to validate some input for dicerolls. I used expresso to build the regular expressions, and it validates it within expresso just fine. Why would it fail within this code?
#include <iostream>
#include <string>
#include <regex>
bool regexValidate (string expr, string teststring)
{
regex ex(expr);
if (regex_match(teststring,ex)) {
return true;
cout << "true";
} else if (regex_match (teststring,regex("^\s*\d*d\d*\s*$"))) {
return true;
cout << "true";
}
return false;
}
int main()
{
char choice; // menu option selected by user
bool isExit = false; // Is the user ready to exit?
// test code
string diceexpr = "^\s*\d{1,}d\d{1,}\s*$";
string teststr = "10d10";
string teststr1 = "1d10";
string teststr2 = " 10d10 ";
cout << teststr << " is ";
if (regexValidate(diceexpr,teststr)) {
cout << " valid!" << endl;
} else {
cout << " invalid!" << endl;
}
cout << teststr1 << " is ";
if (regexValidate(diceexpr,teststr1)) {
cout << " valid!" << endl;
} else {
cout << " invalid!" << endl;
}
cout << teststr2 << " is ";
if (regexValidate(diceexpr,teststr2)) {
cout << " valid!" << endl;
} else {
cout << " invalid!" << endl;
}
return 0;
}
Sample output:
10d10 is invalid!
1d10 is invalid!
10d10 is invalid!
RUN SUCCESSFUL (total time: 291ms)
UPDATE
Corrected my code and changed it to use the boost library for regular expressions.
#include <iostream>
#include <string>
#include <boost/regex.hpp>
using namespace std;
bool regexValidate (string expr, string teststring)
{
boost::regex ex(expr);
if ( boost::regex_match (teststring,ex) ) {
cout << "true";
return true;
//} else if (regex_match (teststring,regex("^\s*\d*d\d*\s*$"))) {
// cout << "true";
// return true;
}
return false;
}
int main()
{
string diceexpr = "^\\s*\\d{1,}d\\d{1,}\\s*$";
string teststr = "10d10";
string teststr1 = "1d10";
string teststr2 = " 10d10 ";
cout << teststr << " is ";
if (regexValidate(diceexpr,teststr)) {
cout << " valid!" << endl;
} else {
cout << " invalid!" << endl;
}
cout << teststr1 << " is ";
if (regexValidate(diceexpr,teststr1)) {
cout << " valid!" << endl;
} else {
cout << " invalid!" << endl;
}
cout << teststr2 << " is ";
if (regexValidate(diceexpr,teststr2)) {
cout << " valid!" << endl;
} else {
cout << " invalid!" << endl;
}
return 0;
}
Given the following output:
terminate called after throwing an instance of 'std::regex_error'
what(): regex_error
RUN FAILED (exit value 1, total time: 1s)

string diceexpr = "^\s*\d{1,}d\d{1,}\s*$";
This doesn't do what you think it does. In a string literal, "\s" is the same as "s" (you should be seeing compiler warnings about unrecognized escape sequences), while "\\s" represents two characters, backslash and 's'.
Double up all backslashes, or else use a raw string literal for your regular expression, as in
string diceexpr = R"(^\s*\d{1,}d\d{1,}\s*$)";

Related

c++ variable output unexpected

Im writing a wordle game and am trying to get the output to work, but i have no clue as to what im doing wrong here. The basic version of the code is 5 letter words are taken from a word file and stored in an array, then a random word is picked from there to be the answer to the wordle. Then the user is prompted for input and once they input a word, it verifies the length, as well as if it is in the array of words. then another function takes the guessed word and compares it against the winning word and outputs the guessed word with colors to show what letters are in the right spot, like real wordle. The issue arises when i try to print everything out, i tried to use a while loop to ask for input but i couldnt get it to work so i decided to test it by making a function that asks for the input, then i called it six times, each time giving it a different variable to store the result in, then print out the first one on the first guess, the first and second on the second guess, and so on. But it only prints out the current guess. It might be something very obvious but i have spent so much time coding i have no idea. any help is greatly appreciated.
#include <iostream>
#include <string>
#include <fstream>
#include <ctime>
using namespace std;
const string CORRECT = "\033[7;32m";
const string CLOSE = "\033[7;33m";
const string INCORRECT = "\033[7;37m";
const string END = "\033[0m";
int verifyExists(string word, string verifyArr[2315]) {
if (word.size() == 5)
{
for (int i = 0; i < 2315; i++)
{
if (word == verifyArr[i])
{
return 1;
}
}
return 2;
} else {
return 3;
}
}
string buildResult(string plyrGuess, string word)
{
string result[5];
string color;
for (int i = 0; i < 5; i++){
if (plyrGuess[i] != word[i])
{
color = INCORRECT + plyrGuess[i] + END;
result[i] = color;
}
if ((plyrGuess[i] != word[i]) && (plyrGuess[i] == word[0] || plyrGuess[i] == word[1] || plyrGuess[i] == w\
ord[2] || plyrGuess[i] == word[3] || plyrGuess[i] == word[4]))
{
color = CLOSE + plyrGuess[i] + END;
result[i] = color;
}
if (plyrGuess[i] == word[i])
{
color = CORRECT + plyrGuess[i] + END;
result[i] = color;
}
}
string done;
for (int i = 0; i < 5; i++)
{
cout << result[i];
}
getline(cin, done);
return done;
}
string askInput(string array[2315])
{
string guessWord;
cout << "What word would you like to guess?" << endl;
getline(cin, guessWord);
while (verifyExists(guessWord, array) == 2)
{
cout << "The word: " << guessWord << " is not in the word list" << endl;
getline(cin, guessWord);
}
while (verifyExists(guessWord, array) == 3)
{
cout << "You must enter a word that is 5 letters in length: " << endl;
getline(cin, guessWord);
}
return guessWord;
}
void playGame(string winWord, string arr[2315]) {
cout << "Ok. I am thinking of a word with 5 letters." << endl;
string guess1 = askInput(arr);
string done1 = buildResult(guess1, winWord);
cout << done1 << "\n" << endl;
cout << "_____" << endl;
cout << "_____" << endl;
cout << "_____" << endl;
cout << "_____" << endl;
cout << "_____" << endl;
string guess2 = askInput(arr);
string done2 = buildResult(guess2, winWord);
cout << done1 << endl;
cout << done2 << endl;
cout << "_____" << endl;
cout << "_____" << endl;
cout << "_____" << endl;
cout << "_____" << endl;
string guess3 = askInput(arr);
string done3 = buildResult(guess3, winWord);
cout << done1 << endl;
cout << done2 << endl;
cout << done3 << endl;
cout << "_____" << endl;
cout << "_____" << endl;
cout << "_____" << endl;
string guess4 = askInput(arr);
string done4 = buildResult(guess4, winWord);
cout << done1 << endl;
cout << done2 << endl;
cout << done3 << endl;
cout << done4 << endl;
cout << "_____" << endl;
cout << "_____" << endl;
string guess5 = askInput(arr);
string done5 = buildResult(guess5, winWord);
cout << done1 << endl;
cout << done2 << endl;
cout << done3 << endl;
cout << done4 << endl;
cout << "_____" << endl;
string guess6 = askInput(arr);
string done6 = buildResult(guess6, winWord);
cout << done1 << endl;
cout << done2 << endl;
cout << done3 << endl;
cout << done4 << endl;
cout << done5 << endl;
cout << done6 << endl;
}
int main() {
string wordArray[2315];
ifstream myfile ("proj1_data.txt");
cout << " Welcome to UMBC Wordle" << endl;
if (myfile.is_open())
{
string word;
int loop = 0;
while (getline(myfile, word))
{
wordArray[loop++] = word;
}
cout << " " << endl;
cout << " Your file was imported!" << endl;
cout << " 2315 Words imported" << endl;
cout << " " << endl;
myfile.close();
}
srand(time(0));
string chosenWord = wordArray[rand() % 2315];
playGame(chosenWord, wordArray);
return 0;
}
I dont get any errors when i compile it so i know that nothings "wrong" with the code, the problem is in the playGame function, i included the whole code in case that helps

Is there a way to use bools with strings? I want to search for a word in a string, and if it's there, output the meaning

I am very new to coding and this is my first language, C++. I have an assignment that is really confusing.
The assignment wants me to search the user input of one line for slang words. Ex: TMI or BFF. However, I don't know how to use conditional expressions to do this, and I have tried if-else statements but they end up reading all the statements instead of each one that applies. The code always comes up with a problem for the conditional expression because I honestly have no clue how to use them for strings in this manner. Any help is appreciated!
(Slang terms are required to be capitalized to be read.)
#include <iostream>
#include <cctype>
#include <iomanip>
#include <string>
using namespace std;
int main() {
string userInput;
int textSlang = '0';
cout << "Welcome to the Text Message Decoder!" << endl;
cout << "WARNING! Slang is case-sensitive. Please make sure all slang is fully capitalized!" << endl;
cout << "Enter a single line text message: " << endl;
getline(cin, userInput);
cout << "You entered: " << userInput << endl;
if (textSlang == string::npos) {
cout << "Error" << endl;
}
else if ((textSlang = userInput.find("IDK" ))) {
cout << "IDK: I don't know" << endl;
}
else if ((textSlang = userInput.find("TTYL" ))) {
cout << "TTYL: Talk to you later" << endl;
}
else if ((textSlang = userInput.find("TMI" ))) {
cout << "TMI: Too much information" << endl;
}
else if ((textSlang = userInput.find("JK" ))) {
cout << "JK: Just kidding" << endl;
}
else if ((textSlang = userInput.find("BFF" ))) {
cout << "BFF: Best friends forever" << endl;
}
else if ((textSlang = userInput.find("LOL" ))) {
cout << "LOL: Laugh out loud" << endl;
}
else if ((textSlang = userInput.find("TYSM" ))) {
cout << "TYSM: Thank you so much" << endl;
}
else if ((textSlang = userInput.find("OMG" ))) {
cout << "OMG: Oh my god" << endl;
}
cout << "END." << endl;
//textSlang = userInput.find("TTYL");
//textSlang = userInput.find("TMI");
//textSlang = userInput.find("JK");
//textSlang = userInput.find("BFF");
//textSlang = userInput.find("LOL");
//textSlang = userInput.find("TYSM");
//textSlang = userInput.find("OMG");
}
This code:
else if ((textSlang = userInput.find("IDK" ))) {
cout << "IDK: I don't know" << endl;
}
assigns textSlang to 0 IFF userInput begins with IDK. In all other cases it assigns some value other than 0.
And all int values other that 0 evaluate to true.
You want:
else if ((textSlang = userInput.find("IDK" )) != string::npos) {
cout << "IDK: I don't know" << endl;
}

memory leaks in c++

#pragma once
#ifndef SDDS_GIFT_H
#define SDDS_GIFT_H
#include <iostream>
namespace sdds
{
const int MAX_DESC = 15;
const double MAX_PRICE = 999.999;
const int MAX_WRAP = 20;
struct Gift
{
char m_description[MAX_DESC];
double m_price;
int m_units;
int m_wrapLayers;
struct Wrapping* m_wrap;
};
struct Wrapping
{
char* m_pattern;
};
void gifting(char*);
void gifting(double&);
void gifting(int&);
bool wrap(Gift& theGift);
bool unwrap(Gift& theGift);
void gifting(Gift& theGift);
void display(const Gift& theGift);
}
#endif
<pre><code>
#include <iostream>
#include "Gift.h"
using namespace std;
namespace sdds
{
void gifting(char* m_description) // sending info
{
cout << "Enter gift description: ";
cin.width(MAX_DESC + 1);
cin >> m_description;
}
void gifting(double& m_price)
{
cout << "Enter gift price: ";
cin >> m_price;
while (m_price > MAX_PRICE || m_price < 0)
{
cout << "Gift price must be between 0 and " << MAX_PRICE << std::endl;
cout << "Enter gift price: ";
cin >> m_price;
}
}
void gifting(int& m_units)// gifting function
{
cout << "Enter gift units: ";
cin >> m_units;
while (m_units < 1)
{
cout << "Gift units must be at least 1" << std::endl;
cout << "Enter gift units: ";
cin >> m_units;
};
}
bool wrap(Gift& m_wrap) {
if (m_wrap.m_wrapLayers > 0) {
cout << "Gift is already wrapped!" << endl;
return false;
}
else {
cout << "Wrapping gifts..." << endl;
cout << "Enter the number of wrapping layers for the Gift: ";
cin >> m_wrap.m_wrapLayers;
while (m_wrap.m_wrapLayers < 1) {
cout << "Layers at minimum must be 1, try again." << endl;
cout << "Enter the number of wrapping layers for the Gift: ";
cin >> m_wrap.m_wrapLayers;
}
int i = 0;
m_wrap.m_wrap = new Wrapping[MAX_WRAP + 1];
for (i = 0; i < m_wrap.m_wrapLayers; i++) {
m_wrap.m_wrap->m_pattern = new char[MAX_WRAP + 1];
cout << "Enter wrapping pattern #" << i + 1 << ": ";
cin >> m_wrap.m_wrap->m_pattern;
} // I put struct in a structure
return true;
}
delete[]m_wrap.m_wrap;
m_wrap.m_wrap = nullptr;
}
bool unwrap(Gift& g_unwrap) // unwrap function
{
if (g_unwrap.m_wrapLayers > 0) {
cout << "Gift being unwrapped." << endl;
g_unwrap.m_wrapLayers = 0;
g_unwrap.m_wrap->m_pattern = nullptr;
return true;
}
else
{
cout << "Gift isn't wrapped! Can't unwrap." << endl;
return false;
}
}
void display(const Gift& theGift)
{
cout << "Gift Details:" << endl;
cout << " Description: " << theGift.m_description << endl;
cout << " Price: " << theGift.m_price << endl;
cout << " Units: " << theGift.m_units << endl;
if (theGift.m_wrap == nullptr) // this part seems like a problem
{
cout << "Unwrapped" << endl;
}
else
{
int i = 0;
cout << "Wrap Layers: " << theGift.m_wrapLayers << endl;
for (i = 0; i < theGift.m_wrapLayers; i++) {
cout << "Wrap #" << i + 1 << ": " << theGift.m_wrap[i].m_pattern << endl;
}
}
}
void gifting(Gift& gift) //last function
{
cout << "Preparing a gift..." << endl;
gifting(gift.m_description);
gifting(gift.m_price);
gifting(gift.m_units);
wrap(gift);
}
}
</code></pre>
/***********************************************************************
// Workshop 2: Dynamic Memory & Function Overloading
// Version 2.0
// Date 2020/05/05
// Author Michael Huang
// Description
// Tests Gift module and provides a set of TODOs to complete
// which the main focuses are dynamic memory allocation
//
/////////////////////////////////////////////////////////////////
***********************************************************************/
#include <iostream>
#include "Gift.h"
#include "Gift.h" // intentional
using namespace std;
using namespace sdds;
void printHeader(const char* title)
{
char oldFill = cout.fill('-');
cout.width(40);
cout << "" << endl;
cout << "|> " << title << endl;
cout.fill('-');
cout.width(40);
cout << "" << endl;
cout.fill(oldFill);
}
<pre><code>
int main() {
Gift g1; // Unwrapped Gift
{
printHeader("T1: Checking Constants");
cout << "MAX_DESC: " << sdds::MAX_DESC << endl;
cout << "MAX_PRICE: " << sdds::MAX_PRICE << endl;
cout << "MAX_WRAP: " << sdds::MAX_WRAP << endl;
cout << endl;
}
{
printHeader("T2: Display Wrapped Gift");
gifting(g1.m_description);
gifting(g1.m_price);
gifting(g1.m_units);
cout << endl;
g1.m_wrap = nullptr;
g1.m_wrapLayers = 0;
display(g1);
cout << endl;
}
{
printHeader("T3: Wrap a gift");
if (wrap(g1))
cout << "Test succeeded!";
else
cout << "Test failed: wrapping didn't happen!" << endl;
cout << endl << endl;
}
{
printHeader("T4: Re-wrap a gift");
cout << "Attempting to rewrap the previous Gift: "
<< g1.m_description << endl;
if (wrap(g1) == false)
cout << "Test succeeded!";
else
cout << "Test failed: gift it's already wrapped, cannot wrap again!";
cout << endl << endl;
}
{
printHeader("T5: Unwrap a gift");
cout << "Attempting to unwrap the previous gift: "
<< g1.m_description << endl;
if (unwrap(g1))
cout << "Test succeeded!";
else
cout << "Test failed: you should be able to unwrap!";
cout << endl << endl;
}
{
printHeader("T6: Unwrap again");
cout << "Attempting to un-unwrap the previous gift: "
<< g1.m_description << endl;
if (!unwrap(g1))
cout << "Test succeeded!";
else
cout << "Test failed: you should not be able to unwrap again!";
cout << endl << endl;
}
Gift g2; // Unwrapped Gift
{
printHeader("T7: Prepare another gift");
g2.m_wrap = nullptr;
g2.m_wrapLayers = 0;
gifting(g2);
cout << endl;
display(g2);
cout << endl;
}
{
printHeader("T8: Unwrap the second gift");
unwrap(g2);
}
return 0;
}
Output matches perfectly but I don't know why memory leaks.. please help me. I am doubting my wrap part but I think there must be something else since deallocation seems fine.
I tried my best but I still cannot see which part is wrong.
I cannot see why my deallocation does not work I tried changing it so many times but nothing works.
On this line:
m_wrap.m_wrap->m_pattern = new char[MAX_WRAP + 1];
You allocate memory, but later you only:
delete[]m_wrap.m_wrap;
Also in your for loop you allocate memory, then get some input and store that inside the pointer, as a memory address. Should you ever dereference that, you will invoke undefined behavior, in practice that may likely will a segfault. You should consider rewriting at least that part from scratch.

Why does program complain of too many commas?

Here is my code, I have attached the screenshot of what output Zybooks expects, and what my output is. I am trying to get it to output exactly what Zybooks is asking, however something seams to be wrong. It is compiling though. Or maybe Zybooks is just being stupid?
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cstring>
using namespace std;
int main() {
string title;
string col1;
string col2;
string val;
int numCommas = 0;
vector<string> stringData;
vector<int> intData;
cout << "Enter a title for the data:" << endl;
getline(cin, title);
cout << "You entered: " << title << endl << endl;
cout << "Enter the column 1 header:" << endl;
getline(cin, col1);
cout << "You entered: " << col1 << endl << endl;
cout << "Enter the column 2 header:" << endl;
getline(cin, col2);
cout << "You entered: " << col2 << endl << endl;
while (1) {
cout << "Enter a data point (-1 to stop input):" << endl;
getline(cin, val);
if (val == "-1") {
break;
}
if (val.find(',') == -1) {
cout << "Error: No comma in string." << endl << endl;
}
else {
for (int i = 0; i < val.length(); i++) {
if (val.at(i) == ',') {
numCommas++;
if (numCommas > 1){
break;
}
}
}
if (numCommas == 1) {
stringData.push_back(val.substr(0, val.find(',')));
intData.push_back(stoi(val.substr(val.find(',') + 1, val.length() - 1)));
cout << "Data string: " << val.substr(0, val.find(',')) << endl;
cout << "Data integer: " << stoi(val.substr(val.find(',') + 1, val.length() - 1)) << endl;
}
else {
cout << "Error: Too many commas in input." << endl << endl;
}
}
}
return 0;
}
Thanks.
Thanks.
Your problem is that you initialise numCommas to zero at the start of the program rather than at the start of each author input. That means, once it exceeds one, it will stay that high at least(a), meaning future inputs will always be seen as having too many commas.
You just need to set it to zero immediately before checking each input.
(a) Well, until it wraps around (if it wraps around). But that will be an awful lot of commas you need to input :-)

Empty string position to return as *

Very new to programming.
This bit of my program accepts two strand of DNA as input and output them in a double helix drawing. The problem is, if one of the two input strand is longer than the other, i will receive error.
So I thought, is it possible that if strand[add] is non-existent anymore, replace it with *?
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
void helix(string &strand1, string &strand2)
{
int nucleo;
int length;
if (strand1.length() >= strand2.length())
{
length = strand1.length();
}
else
{
length = strand2.length();
}
int add;
for (int add = 0; add <= length - 1; add++)
{
if (add > 7)
{
nucleo = add % 8;
}
else
{
nucleo = add;
}
if (nucleo == 0)
{
cout << " " << strand1[add] << "---"<<strand2[add] << endl;
}
else if (nucleo == 1)
{
cout << " " << strand1[add] << "------" << strand2[add] << endl;
}
else if (nucleo == 2)
{
cout << " " << strand1[add] << "------" << strand2[add] << endl;
}
else if (nucleo == 3)
{
cout << " " << strand1[add] << "---" << strand2[add] << endl;
cout << " *" << endl;
}
else if (nucleo == 4)
{
cout << " " << strand2[add]<<"---" << strand1[add] << endl;
}
else if (nucleo == 5)
{
cout << " " << strand2[add]<<"------" << strand1[add] << endl;
}
else if (nucleo == 6)
{
cout << " " << strand2[add]<<"------" << strand1[add] << endl;
}
else if (nucleo == 7)
{
cout << " " << strand2[add]<<"-----" << strand1[add] << endl;
cout << " *" << endl;
}
}
}
int main()
{
string strand1,strand2;
cout << "ENTER STRAND:" << endl;
cin >> strand1;
cout << "ENTER STRAND:" << endl;
cin >> strand2;
helix(strand1,strand2);
_getch();
return 0;
}
I was hoping I could still show the longer strand even if the other side of the strand is empty(want to put *) like this :imgur.com/t7riVrS
I think you inverted the legnth test, it should be:
//if (strand1.length() >= strand2.length())
if (strand1.length() < strand2.length())
{
length = strand1.length();
}
else
{
length = strand2.length();
}
Edit:
If you want it fill one the string with '*', replace the code above with:
while (strand1.length() < strand2.length())
{
strand1 += "*";
}
while (strand1.length() > strand2.length())
{
strand2 += "*";
}