User inputs a string in form of
length=10 width=15
The task is to find the length's and width's value in such a string(and assign them to variables). So, how can I find those two numbers? What functions/methods should I use? Can you guys just give me an idea?
Regular expressions are fun and are usually not acceptable as homework solutions for introductory classes.
match[1] and match[2] are the numerical portion of the string that you are interested in. You'll probably want to pass them to stoi() if you need to manipulate them as integers.
Code
#include <iostream>
#include <regex>
int main() {
std::string s("length=10 width=15");
std::regex re("length=([0-9]+) width=([0-9]+)");
std::smatch match;
if (regex_match(s, match, re)) {
std::cout << "length: " << match[1] << "\n";
std::cout << "width: " << match[2] << "\n";
}
}
Output
length: 10
width: 15
use stringstream:
#include <string>
#include <iostream>
#include <sstream>
#include <map>
using namespace std;
int main()
{
stringstream ss;
ss.str("length1=10 width=15 length2=43543545");
map<string, int> resMap;
string key;
int val;
while (ss.peek() != EOF) {
if (isalpha(ss.peek())) {
char tmp[256];
ss.get(tmp,streamsize(256),'=') ;
key = tmp;
} else if (isdigit(ss.peek())) {
ss >> val;
resMap.insert(pair<string, int>(key,val));
} else {
ss.get();
}
}
cout << "result:\n";
for (map<string, int>::iterator it = resMap.begin(); it != resMap.end(); ++it) {
cout << "resMap[" << it->first<< "]=" << it->second << endl;
}
getchar();
return 0;
}
Related
I'm writing a program that saves words from a .txt file in vector words, calculates how many words are there (num_elements) and prints these words randomly to the screen (no duplicates).
It all works fine up until rw.erase line, which just spits out the error "vector subscript out of range".
Why is my erase call throwing "vector subscript out of range"?
#include <iostream>
#include <string>
#include <fstream>
#include <Windows.h>
#include <direct.h>
#include <filesystem>
#include <time.h>
#include <random>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
void path_to_main_dir() {
string path = "C:/Randomizer/";
for (const auto& entry : experimental::filesystem::directory_iterator(path)) {
cout << entry.path() << endl;
}
}
int main() {
path_to_main_dir();
string dateread;
printf("Which file do you want to open? ");
cout << "---------------------------------------------------------------------------------------------------------" << endl;
path_to_main_dir();
cout << endl;
cout << "---------------------------------------------------------------------------------------------------------" << endl;
cout << "User: ";
getline(cin, dateread);
string path_to_file = "C:/Randomizer/" + dateread + ".txt";
ifstream readfile(path_to_file.c_str());
vector<string> words;
string word;
while (getline(readfile, word))
{
words.push_back(word);
}
readfile.close();
srand(time(NULL));
string randomword;
vector<string> rw = { words };
int num_elements = size(words);
cout << endl;
cout << "Number of words in the file: ";
cout << num_elements;
cout << endl;
for (unsigned int a = 0; a < num_elements; a = a + 1)
{
randomword = rw[rand() % num_elements];
cout << randomword << endl;
rw.erase(remove(rw.begin(), rw.end(), randomword), rw.end());
num_elements -= 1;
system("pause");
}
goto firstline;
return 0;
}
If the error only happens in the case where there are duplicates, it could be because the num_elements is wrong. The remove/erase call will have deleted as many duplicates as there are, but num_elements has only been reduced by one.
Fortunatly, vectors know their own size, so rather than trying to remember its internal information for it, you can just ask!
int main()
{
//...
//Code to read words from file
//...
cout << "Number of words in file: " << words.size() << endl;
while(!words.empty())
{
string randomWord = words[rand() % words.size()];
cout << randomWord << endl;
words.erase(remove(words.begin(), words.end(), randomWord), words.end());
}
return 0;
}
From what I can see, you only use words to create rw, so we could just use words directly instead.
Im working on a college project and it requires big number like 43,000,000 but everytime i launch the program it gives me something like this 43000,000. I already used std::fixed and precision but it doesnt add the second comma.
this is the code:
double PreEnCol() {
if (marca == 1)
return (105.000*562);
else if (marca == 2)
return (65.000*562);
else if (marca == 3)
return (54.000*562);
else if (marca == 4)
return (125.000*562);
else if (marca == 5)
return (129.000*562);
else if (marca == 6)
return (85.900*562);
}
string toString(){
stringstream s;
s << endl;
s << std::fixed << std::setprecision(1) << "Precio en colones: "<<PreEnCol() << endl;
return s.str();
}
Please i need help with this i've been dealing with this problem for hours.
Mostly your output depend on your default locale. You need to override you whole locale OR part of locale of you interest.
Below code helps you to override part of locale which is responsible for printing commas in number.
#include <iostream>
#include <sstream>
#include <iomanip>
#include <locale>
struct Sep3Digit : std::numpunct<char> {
std::string do_grouping() const { return "\003"; }
};
std::string FormatWithCommas(double d)
{
std::stringstream ss;
ss.imbue(std::locale(std::cout.getloc(), new Sep3Digit));
ss << std::fixed << d;
return ss.str();
}
int main()
{
std::cout<<FormatWithCommas(std::numeric_limits<double>::max())<<std::endl;
return 0;
}
You can usually do that with default system locale:
#include <locale>
string toString(){
stringstream s;
s << endl;
s.imbue(std::locale("")); // <-- set locale. OR: std::locale("en_US")
s << std::fixed << std::setprecision(1) << "Precio en colones: "<<PreEnCol() << endl;
return s.str();
}
Note that this will print 43000000 as 43,000,000 in some parts of the world, or as 43.000.000 in others where '.' is used as grouping separator.
Here's full example:
#include <locale>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
string toString(int n)
{
stringstream s;
s << endl;
s.imbue(std::locale("")); // <-- set locale
s << std::fixed << std::setprecision(1) << "Precio en colones: "<< n << endl;
return s.str();
}
int main()
{
int n = 43000000;
cout << "formatted " << n << ": " << toString(n) << endl;
}
It produces this output:
formatted 43000000:
Precio en colones: 43,000,000
I basically ask a user to input a string, let's say they input "ABC" or"DEF"
Then, I want to set a certain integer = 1 if ABC is entered and 2 if DEF is entered.
If anything else is entered, then I want it to say invalid value.
So at the end, I'll have the integer i assigned to 1 or 2 if a valid value was entered.
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main()
{
string input = "";
// How to get a string/sentence with spaces
cout << "Please enter a valid sentence (with spaces):\n>";
getline(cin, input);
cout << ".\n" << "You entered: " << input << endl << endl;
int m
if(input = ABC)
return 0;
}
Very easy:
#include <iostream>
#include <map>
#include <string>
int main()
{
std::map<std::string, int> const v { { "ABC", 1 }, { "DEF", 2 } };
for (std::string line; std::getline(std::cin, line); )
{
auto it = v.find(line);
if (it == v.end())
{
std::cout << "Input '" << line << "' is invalid.\n";
}
else
{
std::cout << "Your input value: " << it->second << "\n";
}
}
}
Your English spec:
” set a certain integer = 1 if ABC is entered and 2 if DEF is entered […] if anything else is entered, then I want it to say invalid value.
Expressed in C++:
if( s == "ABC" ) { x = 1; }
else if( s == "DEF" ) { x = 2; }
else { cout << "Invalid value." << endl; }
If neither of the specified possibilites is true, i.e. in the case of outputting "Invalid value.", then x keeps the value it had, which is how I interpret the word “set”.
At a higher level of abstraction, it seems like you want the user to specify one of two strings, namely “ABC” or “DEF”, which you want to have available as an integer id after the input operation.
Then there are two main possibilities:
you want the id to indicate also the case where the user specified some other string, e.g. a common value for this, or
you want the input operation to only return control when the user has inputted one of the two valid strings.
The last case effectively means that input operation must loop or logically fail. Logical failure can be expressed as an exception, or e.g. by calling std::terminate.
So as you see there is a range of possibilities here, i.e. above the simple “how do I translate this English to C++” the desired functionality is a bit under-specified.
#include <iostream>
#include <map>
#include <string>
#include <initializer_list>
using namespace std;
int main()
{
const std::map<std::string, int> lookupTable = { {"ABC", 1}, {"DEF", 2} };
string input = "";
int m;
while(true) {
cout << "Please enter a valid sentence (with spaces):\n>";
getline(cin, input);
std::map<std::string, int>::const_iterator it = lookupTable.find(input);
if (it != lookupTable.end()) {
m = it->second;
break;
}
}
cout << "You entered: " << input << endl << endl;
cout << "m = " << m << endl;
}
Second solution if you want your m const. This assumes your compiler supports lambda functions:
#include <iostream>
#include <map>
#include <string>
#include <initializer_list>
using namespace std;
int main()
{
const std::map<std::string, int> lookupTable = { {"ABC", 1}, {"DEF", 2} };
string input = "";
const int m = [&]() {
while(true) {
cout << "Please enter a valid sentence (with spaces):\n>";
getline(cin, input);
std::map<std::string, int>::const_iterator it = lookupTable.find(input);
if (it != lookupTable.end())
return it->second;
}
}();
cout << "You entered: " << input << endl << endl;
cout << "m = " << m << endl;
}
If your compiler does not support the above map initialization then you can use instead:
#include <iostream>
#include <map>
#include <string>
using namespace std;
std::map<std::string, int> initializeMap() {
std::map<std::string, int> map;
map["ABC"] = 1;
map["DEF"] = 2;
// add whatever else here
return map;
}
int main()
{
const std::map<std::string, int> lookupTable = initializeMap();
string input = "";
int m;
while(true) {
cout << "Please enter a valid sentence (with spaces):\n>";
getline(cin, input);
std::map<std::string, int>::const_iterator it = lookupTable.find(input);
if (it != lookupTable.end()) {
m = it->second;
break;
}
}
cout << "You entered: " << input << endl << endl;
cout << "m = " << m << endl;
}
My code has an if else statement which verifies whether an input is a string full of alpha characters.
The code works but the cout << original << "\n"; part prints out the result 5 times. I think the root of the issue lies within the for (std::string::iterator it=original.begin(); it!=original.end(); ++it) line, specifically the ++it bit.
Below is the code:
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <locale>
#include <iostream>
using namespace std;
int main(int nNumberofArgs, char* pszArgs[])
{
std::locale loc;
std::string original;
std::cout << "Welcome to the English to Pig Latin translator!\n";
std::cout << "Type a word you wish to translate:\n";
std::getline(std::cin, original);
std::cout << "Your word: " << original << "\n";
for (std::string::iterator it=original.begin(); it!=original.end(); ++it)
{
if (original.length() > 0 && std::isalpha(*it,loc) )
{
std::string word;
std::transform(original.begin(), original.end(), original.begin(), ::tolower);
cout << original << "\n";
}
else
{
std::cout << "Please enter a valid word." << std::endl;
}
}
system("PAUSE");
return 0;
}
This link is a screenshot of my CLI output:
http://gyazo.com/5b9cea385794fecc39ed578b539a84c3
It's printing five times because "hello" is five characters long. Your for loop is running once for each character in the string.
Your code is not correct. It checks for each character rather than the entire string.
Change it to:
bool alphaString = true;
for (std::string::iterator it=original.begin(); it!=original.end(); ++it)
{
if (! std::isalpha(*it,loc) )
{
std::cout << "Please enter a valid word." << std::endl;
alphaString = false;
break;
}
}
if ( alphaString ) {
std::transform(original.begin(), original.end(), original.begin(), ::tolower);
cout << original << "\n";
}
Is there any way to read a formatted string like this, for example :48754+7812=Abcs.
Let's say I have three stringz X,Y and Z, and I want
X = 48754
Y = 7812
Z = Abcs
The size of the two numbers and the length of the string may vary, so I dont want to use substring() or anything like that.
Is it possible to give C++ a parameter like this
":#####..+####..=SSS.."
so it knows directly what's going on?
#include <iostream>
#include <sstream>
int main(int argc, char **argv) {
std::string str = ":12341+414112=absca";
std::stringstream ss(str);
int v1, v2;
char col, op, eq;
std::string var;
ss >> col >> v1 >> op >> v2 >> eq >> var;
std::cout << v1 << " " << v2 << " " << var << std::endl;
return 0;
}
A possibility is boost::split(), which allows the specification of multiple delimiters and does not require prior knowledge of the size of the input:
#include <iostream>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
int main()
{
std::vector<std::string> tokens;
std::string s(":48754+7812=Abcs");
boost::split(tokens, s, boost::is_any_of(":+="));
// "48754" == tokens[0]
// "7812" == tokens[1]
// "Abcs" == tokens[2]
return 0;
}
Or, using sscanf():
#include <iostream>
#include <cstdio>
int main()
{
const char* s = ":48754+7812=Abcs";
int X, Y;
char Z[100];
if (3 == std::sscanf(s, ":%d+%d=%99s", &X, &Y, Z))
{
std::cout << "X=" << X << "\n";
std::cout << "Y=" << Y << "\n";
std::cout << "Z=" << Z << "\n";
}
return 0;
}
However, the limitiation here is that the maximum length of the string (Z) must be decided before parsing the input.
You can use scanf. It is not overly C++ - ish, but it does the trick with remarkably few lines of code:
char a[101], b[111], c[121];
sscanf(":48754+7812=Abcs", ":%100[^+]+%110[^=]=%120s", a, b, c);
string sa(a), sb(b), sc(c);
cout << sa << "-" << sb << "-" << sc << endl;
The idea is to specify the characters accepted by the strings that you read using a very limited regular expression syntax. In this case, the first string is read up to the plus, and the second string is read up to the equals sign.
for example.
#include <boost/regex.hpp>
#include <iostream>
int main()
{
boost::regex re("\":(\\d+)\\+(\\d+)=(.+)\"");
std::string example = "\":48754+7812=Abcs\"";
boost::smatch match;
if (boost::regex_match(example, match, re))
{
std::cout << "f number: " << match[1] << " s number: " << match[2] << " string: " << match[3]
<< std::endl;
}
else
{
std::cout << "not match" << std::endl;
}
}
and second variant, work only with string.
#include <string>
#include <iostream>
int main()
{
std::string s = "\":48754+7812=Abcs\"";
std::string::size_type idx = s.find(":");
std::string::size_type end_first = s.find("+", idx + 1);
std::string f_number = s.substr(idx + 1, end_first - (idx + 1));
std::cout << f_number << std::endl;
std::string::size_type end_second = s.find("=", end_first + 1);
std::string s_number = s.substr(end_first + 1, end_second - (end_first + 1));
std::cout << s_number << std::endl;
std::string::size_type string_end = s.find("\"", end_second);
std::string str = s.substr(end_second + 1, string_end - (end_second + 1));
std::cout << str << std::endl;
}