#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
void elimdups(vector<string>& words) {
sort(words.begin(), words.end());
for(auto a : words)
{
cout << a << " ";
}
cout << endl;
auto end_unique = unique(words.begin(), words.end());
for (auto a : words)
{
cout << a << " ";
}
cout << endl;
words.erase(end_unique, words.end());
for (auto a : words)
{
cout << a << " ";
}
cout << endl;
}
int main()
{
vector<string> kim = { "love", "peace", "horrible", "love", "peace", "hi", "hi" };
elimdups(kim);
return 0;
}
--
result:
hi hi horrible love love peace peace
hi horrible love peace love peace
hi horrible love peace
end_unique algorithm do not delete elements.
but on the second cout operation, "hi" disappear.
why "hi" disappear on the second line?
auto end_unique = unique(words.begin(), words.end());
for (auto a : words)
//...
Any items from [end_unique, words.end()) have unspecified values after the call to std::unique. That's why the output in the "erased" range seems strange.
If you want to preserve the "erased" words and keep the relative order, std::stable_partition with the appropriate lambda that checks duplicates could have been done.
Related
I'm doing some rather simple code with set
#include <iostream>
#include <map>
#include <string>
#include <set>
using namespace std;
void printSol(map<string, string> parelles, const set<string>& sols) {
cout << "COUPLES:" << endl;
for (auto& x : parelles) {
cout << x.first << " " << x.second << endl;
parelles.erase(x.second);
}
cout << "ALONE:" << endl;
for (auto x : sols) {
cout << x << endl;
}
cout << "----------" << endl;
}
int main() {
map<string, string> parelles;
set<string> sols;
string inst, nom1, nom2;
while (cin >> inst) {
if (inst == "liats") {
cin >> nom1 >> nom2;
sols.erase(nom1);
sols.erase(nom2);
sols.insert(parelles[nom1]);
sols.insert(parelles[nom2]);
parelles.erase(parelles[nom1]);
parelles.erase(parelles[nom2]);
parelles[nom1] = nom2;
parelles[nom2] = nom1;
}
else if (inst == "info") {
printSol(parelles, sols);
}
}
}
For the input:
liats gerard shakira
liats sara iker
liats gerard sara
liats iker cristiano
info
It prints
COUPLES:
cristiano iker
gerard sara
ALONE:
shakira
----------
but should print
COUPLES:
cristiano iker
gerard sara
ALONE:
shakira
----------
But there is an extra endl after ALONE. I checked the size of the set and it's 2, and I don't really know what's going on. It seems like x has the null string.
Can someone point out in the right direction?
The map::operator[] strikes again. This operator inserts a value-initialized element if the key doesn't exist in the map. For string, this means it will insert an empty string. Here's a fix:
// sols.insert(parelles[nom1]);
// sols.insert(parelles[nom2]);
auto it = parelles.find(nom1);
if (it != parelles.end()) sols.insert(it->second);
it = parelles.find(nom2);
if (it != parelles.end()) sols.insert(it->second);
I was working on a problem which required me to sort vector of strings at certain point. It caused me a lot of problems so I decided to extract the problematic part and I can't figure out what seems to be the problem.
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
bool myComp(string a, string b){
return a<b;
}
int main(){
vector<string> students(50000);
int i = 0;
while(true){
string input;
getline(cin, students[i]);
if(!students[i].empty()){
i++;
}
else{
break;
}
}
cout << students[2] << endl << students[1] << endl;
sort(students.begin(), students.end());
cout << students[2] << endl << students[1];
return 0;
}
At first I thought that input was wrong (problem specifically requests to read until empty line), but it turned out that program works correctly up to moment of sorting. I would be very grateful if anyone was to clear this out for me I am banging my head for more than an hour.
The obvious issue with your code is that you have a vector of 50000 strings. You then try an sort that vector of 50000 strings. It seems obvious that you really want the size of the vector to equal the number of strings input. The easy way to do that is to grow the vector as you input strings. Use the push_back method for that.
Here's some code
vector<string> students; // initial size of vector is zero
int i = 0;
while(true){
string input;
getline(cin, input); // read into the input variable
if (input.empty()) // break if input is empty
break;
students.push_back(input); // add the input to the vector
}
Now with the vector sized correctly you should find sorting it to be no problem
cout << students[2] << endl << students[1] << endl;
sort(students.begin(), students.end());
cout << students[2] << endl << students[1];
The problem is using incorrect arguments in the call of std::sort.
sort(students.begin(), students.end());
The vector students contains 50000 elements
vector<string> students(50000);
It seems you mean
#include <iterator>
//...
sort(students.begin(), std::next( students.begin(), i ));
or
sort(students.begin(), std::next( students.begin(), i ), myComp );
where myComp should be defined at least like
bool myComp( const string &a, const string &b){
return a<b;
}
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> students;
students.reserve(50000); // want to avoid `students` reallocation for first
// 50'000 entries but size is still zero (`0`)
std::string line;
// read until end-of-input or empty line
while(std::getline(std::cin, line) && !line.empty())
students.push_back(line); // no reallocation for first 50'000 entries!
if(students.size() < 3)
{
std::cerr << "Need at least three students for example\n";
return EXIT_FAILURE;
}
std::cout << students[2] << '\n' << students[1] << '\n';
std::partial_sort( // Only pick out three "smallest" strings for example
students.begin(), // no need to sort more than necessary with 50'000 :-)
std::next(students.begin(), 3),
students.end());
std::cout << students[2] << '\n' << students[1] << std::endl;
return EXIT_SUCCESS;
}
You have written a comparator function myComp() but you haven't used it. I'd suggest using it as the third parameter for sort() and see if things get better. i.e.;
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
bool myComp(string a, string b){
return a<b;
}
int main(){
vector<string> students(50000);
int i = 0;
while(true){
string input;
getline(cin, students[i]);
if(!students[i].empty()){
i++;
}
else{
break;
}
}
cout << students[2] << endl << students[1] << endl;
sort(students.begin(), students.end(), myComp);
cout << students[2] << endl << students[1];
return 0;
}
string a = MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw;
Assume i have this data in my string . I want to record how many M , Z , X , D , J (including those capital letters i didn't mentions ) in in string how can do it ? My friends say use vector can do it but i does not really know how to use vector is there any alternative way to do it .
I tried using for loops to do and find the M , and reset the pointer to 0 to continue find the next capital value , but not sure is there any easier way to do it .
first I'll show you a 'easier' way to me.
#include <iostream>
#include <map>
using namespace std;
int main(int argc, const char * argv[]) {
string str = "MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw";
map<char,int> map;
for (int i=0; i<str.length(); i++) {
char ch = str[i];
if (isupper(ch)) {
map[ch] ++;
}
}
for (auto item : map) {
cout<<item.first<<':'<<item.second<<endl;
}
return 0;
}
you'll only need to use 1 loop to solve your problem.
the 'isupper(int _c)' is a function from the standard library, it can tell you wether a character is a capital letter.
the 'map' is a data structure from the standard library too, it can do key-value storage for you.
this program outputs this:
A:1
B:1
D:2
E:1
F:2
G:2
H:3
J:2
K:1
L:1
M:4
X:2
Z:8
is this what you want?
Use regex.
using namespace std;
// regex_search example
#include <iostream>
#include <string>
#include <regex>
int main ()
{
std::string s ("MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw;");
std::smatch m;
std::regex e ("[A-Z\s]+");
map<string,int> map;
std::cout << "Target sequence: " << s << std::endl;
std::cout << "Regular expression: [A-Z\s]+" << std::endl;
std::cout << "The following matches and submatches were found:" << std::endl;
while (std::regex_search (s,m,e)) {
for (auto x:m)
{
//cout << x << " ";
map[x.str()] ++;
}
//cout << std::endl;
s = m.suffix().str();
}
for (auto item : map) {
cout<<item.first<<':'<<item.second<<endl;
}
return 0;
}
The most direct translation of "loop through the string and count the uppercase letters" into C++ I can think of:
#include <iostream>
#include <map>
#include <cctype>
int main()
{
string a = "MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw";
std::map<char, int> count;
// Loop through the string...
for (auto c: a)
{
// ... and count the uppercase letters.
if (std::isupper(c))
{
count[c] += 1;
}
}
// Show the result.
for (auto it: count)
{
std::cout << it.first << ": " << it.second << std::endl;
}
}
I wrote this program which checks if words given in a list are anagrams of each other, and for some reason my program seems to only get about halfway through running until I get a runtime error that says "map/set iterator not dereferencable". Ive been staring at this for a while now and trying to debug it and I can't figure out the problem, so I was hoping someone here could? Below is the code:
// Anagrams.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
int main()
{
ifstream ifs("words.txt");// opens file
if (!ifs) {
cout << "no file";
exit(1);
}
set<string>anagrams;
map<string, string>words;
string word;
while (ifs >> word) {
string sortedWord = word;
sort(sortedWord.begin(), sortedWord.end());
words.insert(pair<string, string>(word, sortedWord));
}
for (map<string, string>::iterator i = words.begin(); i != words.end(); i++) {
//cout << "test i for loop" << endl;
for (map<string, string>::iterator j = words.begin(); j != words.end(); j++) {
//cout << "test j for loop" << endl;
if (i->first == j->first) {
j++;
}
if (i->second == j->second) {
anagrams.insert(i->first);
anagrams.insert(j->first);
for (set<string>::iterator i = anagrams.begin(); i != anagrams.end(); i++) {
cout << *i << " ";
}
cout << endl;
anagrams.clear();
//cout << i->first << " is an anagram of " << j->first << " and their sorted version is " << i->second << endl;
}
}
}
return 0;
}
And below is the word list:
monday
dynamo
abbot
acne
alert
alter
baby
Baby
BABY
best
bets
cane
later
Unix
UNIX
and the output is this before I get the runtime pop-up error:
acne cane
alert alter
alert later
alert alter
alert later
best bets
best bets
acne cane
dynamo monday
alert later
alert later
dynamo monday
then the error.
(Excuse the crappy output, I can fix that later. More concerned with the error at the moment)
Thanks
My plan is to store a couple dozen rows with 2 items per row and both items will have a different data type. Not sure if this is the right approach and have heard about using vectors but I can't find any samples that will take in 2 items with different types with many rows (an unknown amount of rows) similar to what I'm trying to do here. The following doesn't compile
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct movies_t {
string title;
int year;
} myRecNo[];
void printmovie (movies_t movie);
int main ()
{
string mystr;
for (int i=0; i < 2; i++)
{
switch (i)
{
case 1:
myRecNo[i].title = "2001 A Space Odyssey";
myRecNo[i].year = 1968;
cout << "Auto entry is:\n ";
printmovie (myRecNo[i]);
break;
case 2:
myRecNo[i].title = "2002 A Space Odyssey";
myRecNo[i].year = 1978;
cout << "Auto entry is:\n ";
printmovie (myRecNo[i]);
break;
}
}
return 0;
}
void printmovie (movies_t movie)
{
cout << movie.title;
cout << " (" << movie.year << ")\n";
}
This is the error I get:
Test1.obj||error LNK2019: unresolved external symbol "struct movies_t * myRecNo" (?myRecNo##3PAUmovies_t##A) referenced in function _main|
There are a couple of bad practices in your code, if you are just asking for a way to modify the program so that it will compile and work, see the following:
Declare struct and create struct variables in your main function.
struct movies_t
{
string title;
int year;
};
then, in your main function, movies_t myRecNo[2];
Arrays start at index 0, not 1. so your switch should be
switch (i)
{
case 0:
myRecNo[i].title = "2001 A Space Odyssey";
myRecNo[i].year = 1968;
cout << "Auto entry is:\n ";
printmovie(myRecNo[i]);
break;
case 1:
myRecNo[i].title = "2002 A Space Odyssey";
myRecNo[i].year = 1978;
cout << "Auto entry is:\n ";
printmovie(myRecNo[i]);
break;
}
// the rest of the code..
After you modify these, your code should work.
However, for a better data structure to save an array of paired values, you can use std::vector<std::pair<string, int>> myReg to save your data.
the following code should be much much better, remember to #include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
void printmovie(std::vector<std::pair<std::string, int>>);
int main()
{
std::vector<std::pair<std::string, int>> myReg;
myReg.push_back({ "2001 A Space Odyssey", 1968 });
myReg.push_back({ "2002 A Space Odyssey", 1978 }); // <- if your compiler is not using c++11 standard or above, please change this line to myReg.push_back(std::pair<std::string, int>("name of the movie", int)); to use to older version of Initializer
printmovie(myReg);
return 0;
}
void printmovie(std::vector<std::pair<std::string, int>> movie)
{
for (auto itor = movie.begin(); itor != movie.end(); ++itor)
{
//first is the first data in the pair, which is the title
//second is the second data in the pair, which is the year
std::cout << (*itor).first << " (" << (*itor).second << ")\n";
}
}
Thanks everyone & #Zhou.
Zhou's code above might work on a newer version of the compiler but I'm using Code::Blocks IDE with MS Visual C++ 2010 compiler.
Here is the vector method that worked:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
void printmovie(std::vector<std::pair<std::string, int>>);
int main()
{
std::vector<std::pair<std::string, int>> myReg;
myReg.push_back(std::pair<std::string, int>("title of the movie", 1968));
myReg.push_back(std::pair<std::string, int>("title of the movie2", 1978));
//myReg.push_back({ "2001 A Space Odyssey", 1968 });
//myReg.push_back({ "2002 A Space Odyssey", 1978 });
printmovie(myReg);
//or to print a single element (the 2nd row) thanks #zhou
std::cout << myReg[1].first << " " << myReg[1].second << std::endl;
return 0;
}
void printmovie(std::vector<std::pair<std::string, int>> movie)
{
for (auto itor = movie.begin(); itor != movie.end(); ++itor)
{
//first is the first data in the pair, which is the title
//second is the second data in the pair, which is the year
std::cout << (*itor).first << " (" << (*itor).second << ")\n";
}
}