Get only similar data within a c++ vector - c++

I'm trying to get all the data from a .txt file that have a similar last value, as in the image.
for example, I go through and create a vector where I save in a file only the lines that have the same last value "1565514F" then when I find a different final value "1678721F" I create another file and so on infinitely, the first file would have the name "1565514F.txt" and would save in the same, or in another vector, data like
1001;2021-03-01;False;0;0;1565514F
1001;2021-03-02;False;0;0;1565514F
1002;2021-03-03;False;0;0;1565514F
1002;2021-03-04;False;0;0;1565514F
1003;2021-03-05;False;0;0;1565514F
1003;2021-03-06;False;0;0;1565514F
1004;2021-03-07;False;0;0;1565514F
another file would be called "1678721F.txt" and would have data like this
1006;2021-03-03;False;0;0;1678721F
1006;2021-03-04;False;0;0;1678721F
1001;2021-03-05;False;0;0;1678721F
1001;2021-03-06;False;0;0;1678721F
1004;2021-03-07;False;0;0;1678721F
1004;2021-03-08;False;0;0;1678721F
1003;2021-03-09;False;0;0;1678721F
the code that I have done is the following
// read file
ifstream archivoPlanificacion;
archivoPlanificacion.open("entrada/Planificacion.txt");
string linea;
vector<string> planificacionVector;
while(getline(archivoPlanificacion, linea))
{
planificacionVector.push_back(linea);
}
archivoPlanificacion.close();
for (int i = 0; i < planificacionVector.size(); i++) {
vector<string> planificacionSplitted = splits(planificacionVector[i], ';');
string planificacionFecha = planificacionSplitted[1];
string planificacionRut = planificacionSplitted[5];
cout << "Planificacion Rut: " << planificacionRut << endl;
if (planificacionRut == planificacionSplitted[5]){
vector<string> soloRutMismoUser;
soloRutMismoUser.push_back(planificacionSplitted[5]);
//imprimir vector soloRutMismoUser
for (int i = 0; i < soloRutMismoUser.size(); i++) {
cout << "soloRutMismoUser: " << soloRutMismoUser[i] << endl;
}
} else {
cout << "nuevo rut" << endl;
string aux = planificacionRut;
//crear archivo de salida
}
cout << "Planificacion Fechas: " << planificacionFecha << endl;
}
I don't know if there is a better way, but I asked because I was nesting many for, I would appreciate any help, I still can't separate the data with the "if", thanks

Modifying your loop
string currentCol5; // current 'rut'
vector<string> sameCol5; // collection of same 'rut' col5
for (int i = 0; i < planificacionVector.size(); i++) {
vector<string> planificacionSplitted = splits(planificacionVector[i], ';');
string planificacionFecha = planificacionSplitted[1];
string planificacionRut = planificacionSplitted[5];
cout << "Planificacion Rut: " << planificacionRut << endl;
if (currentCol5 == planificacionSplitted[5] || currentCol5.length() == 0){
sameCol5.push_back(planificacionSplitted[5]);
} else {
// write file here
for (int i = 0; i < sameCol5.size(); i++) {
cout << "soloRutMismoUser: " << sameCol5[i] << endl;
}
// start next set
currentCol5 = planificacionSplitted[5];
sameCol5.clear();
}
cout << "Planificacion Fechas: " << planificacionFecha << endl;
}
I have not tested any of this because I don't have the data structures or the file.

Related

Output does not produce using method and struct

I try this code using a method, array, and struct, but it doesn't produce output at all.
I also use most types of include, but it still doesn't produce any output.
#include<conio.h>
#include<iostream>
#include<stream>
#include<string>
#include<stream>
using namespace std;
struct PetLabel {
string petname;
string pettype;
int petprice;
string petowner;
string phoneno;
};
PetLabel pet [10];
stringstream ss;
void DataPet();
void petPrice();
void findOwner();
int main(){
DataPet();
findOwner();
petPrice();
return 0;
}
void DataPet(){
ifstream infile;
infile.open("petSold.txt");
string cnvt[10];
for(int i = 0; i < 10; i++){
getline(infile, pet[i].petname, ',');
getline(infile, pet[i].pettype, ',');
getline(infile, cnvt[i], ',');
ss << cnvt[i];
ss >> pet[i].petprice;
getline(infile, pet[i].petowner, ',');
getline(infile, pet[i].phoneno);
ss.clear();
}
infile.close();
}
void findOwner(){
int chosen;
for (int i = 0; i < 10; i++){
if (pet[i].petname == "Uyasolu"){
i = chosen;
}
}
cout << "Owner name : " << pet[chosen].petowner << " Phone no : " << pet[chosen].phoneno << endl;
}
void petPrice(){
ofstream outfile("catSold.txt");
outfile << "The cat sold with price greater than RM1000" << endl;
for (int i = 0; i < 10; i++){
if (pet[i].petprice > 1000){
cout << pet[i].petname << "," << pet[i].pettype << "," << pet[i].petprice << "," << pet[i].petowner << "," << pet[i].phoneno << endl;
}
}
outfile.close();
}
the output that I get is:
Owner name : Phone no :
but I can't understand, because there is no syntax error at all.
Is there anything I can add, so I can get the right output?
This method is weird:
void findOwner(){
int chosen;
for (int i=0;i<10;i++){
if (pet[i].petname == "Uyasolu"){
i = chosen;
}
}
cout<<"Owner name : "<<pet[chosen].petowner<<" Phone no : "<<pet[chosen].phoneno<<endl;
}
I think you mean chosen = i instead.
findOwner() is coded wrong.
int chosen; is uninitialized before the loop is entered. Inside the loop, chosen is never updated (i is updated instead, which affects the looping). After the loop is done, chosen has an indeterminate value, so accessing pet[chosen] is undefined behavior.
It should look more like this instead:
void findOwner(){
int chosen = -1;
for (int i = 0; i < 10; i++){
if (pet[i].petname == "Uyasolu"){
chosen = i;
break;
}
}
if (chosen != -1)
cout << "Owner name : " << pet[chosen].petowner << " Phone no : " << pet[chosen].phoneno << endl;
else
cout << "Pet not found" << endl;
}
Alternatively:
void findOwner(){
for (int i = 0; i < 10; i++){
if (pet[i].petname == "Uyasolu"){
cout << "Owner name : " << pet[i].petowner << " Phone no : " << pet[i].phoneno << endl;
return;
}
}
cout << "Pet not found" << endl;
}
There are some other issues in your code, too:
don't use <conio.h>, its old, and you are not using anything from it anyway.
you have #include<stream> twice, and also <stream> should be <sstream>
string cnvt[10]; should be string cnvt; and then cnvt[i] should be cnvt. You don't need a whole array when you are converting only 1 string at a time.
ss.clear(); does not do what you think it does. You need to use ss.str("") instead. Or, simply move the declaration of ss inside the loop as a local variable so it is destroyed and recreated on each loop iteration.
petPrice() is creating an output catSold.txt file, but is not writing anything to it.

Why does it give me an error no "operator=="?

This line is an error and I don't know why. The compiler is telling me that the string array can't be converted to a string variable. The search is a string variable the user types in to look for names. And the names[count] is checking through an array of names.
string search;
string names[5]={};
for(int count=0; count<5; count++)
{
cout<<"Enter a name"<<endl;
cin>>names[count];
}
cout<<"Names entered"<<endl;
for(int count=0; count<5; count++)
{
cout<<names[count]<<endl;
cout<<"What name would you like to search for"<<endl;
cin>>search;
for(int count=0; count<5; count++)
{
if(names[count]=search)
{
cout<<search<<"is on array "<<count<<endl;
}
else
{
cout<<search<<"is not on the list"<<endl;
}
}
Is giving you this error because you are using the = assignment operator instead of the == comparison operator. Only use the former when assigning values to variables and the second for comparing variables in a condition.
I hope this helps:
https://www.geeksforgeeks.org/what-is-the-difference-between-assignment-and-equal-to-operators/
Have a good one and happy hacking!
Your question title mentions operator==, but there is no use of operator== anywhere in the code you have shown.
Your search logic is all wrong, though. First off, it is in the wrong place, it should not be inside the 2nd for loop at all, it needs to be moved up 1 level. And second, it is using the assignment operator= when it should be using the comparison operator== instead. And third, it is handling its output incorrectly.
Try something more like this instead:
string search;
string names[5];
for(int count = 0; count < 5; ++count)
{
cout << "Enter a name" << endl;
cin >> names[count];
}
cout << "Names entered" << endl;
for(int count = 0; count < 5; ++count)
{
cout << names[count] << endl;
}
cout << "What name would you like to search for" << endl;
cin >> search;
int found = -1;
for(int count = 0; count < 5; ++count)
{
if (names[count] == search)
{
found = count;
break;
}
}
if (found != -1)
{
cout << search << " is on array " << found << endl;
}
else
{
cout << search << " is not on the list" << endl;
}
/* alternatively:
#include <algorithm>
#include <iterator>
string *namesEnd = &names[5];
if (std::find(names, namesEnd, search) != namesEnd)
{
cout << search << " is on array " << std::distance(names, found) << endl;
}
else
{
cout << search << " is not on the list" << endl;
}
*/

C++ How to Check what words aren't in 2 similar files

i was trying to find a way to check two different files and get, from the second, all lines that aren't in the first.. but does all the opposite.
I tried the possible to solve this but nothing...
This is the code:
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
stringstream buffer;
buffer << "C:\\Users\\" << username << "\\Desktop\\";
stringstream buffer2;
buffer2 << "C:\\Users\\" << username << "\\Desktop\\Legit.txt";
stringstream buffer3;
buffer3 << "C:\\Users\\" << username << "\\Desktop\\Unlegit.txt";
stringstream buffer4;
buffer4 << "C:\\Users\\" << username << "\\Desktop\\result.txt";
string results = buffer4.str();
int offset;
int num;
num = 1;
string search;
string linea;
string legit;
string unlegit;
string line;
cout << "Is the Legit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> legit;
if (legit == "Y" || legit == "y"){
}else if(legit == "N" || legit == "n"){
return 0;
}else{
cout << "\n.";
return 0;
}
string legitfile = buffer2.str();
cout << "\nIs the Unlegit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> unlegit;
if (unlegit == "Y" || unlegit == "y"){
}else if(unlegit == "N" || unlegit == "n"){
return 0;
}else{
cout << "\n";
return 0;
}
string unlegitfile = buffer3.str();
ifstream file(legitfile.c_str());
if(file.is_open()){
while(getline(file, line)){
ifstream MyFile(unlegitfile.c_str());
if(MyFile.is_open()){
while(!MyFile.eof()){
getline(MyFile,linea);
if((offset = linea.find(line, 0)) != string::npos) {
cout << "\n[" << num << "]" << " Word Found: " << line << "\n";
num++;
fstream result(results.c_str());
result << line << "\n";
result.close();
}
}
MyFile.close();
}
}
file.close();
return 0;
}else{
cout << "\nThe file '" << legitfile << "' does not exist.";
cout << "\nThe file '" << unlegitfile << "' does not exist.";
}
}
As i said, This code checks which words are equals in both (first & second) files and, once found, writes them to a third file, there is a way to do the opposite (check the two files and get the words that aren't equals)? Thank you so much!
I'm new, both in the forum and in C++, sorry if I make any mistakes. (sorry for my bad english too).
The classic solution to this sort of problem is to use a hash table collection to represent all the words in the first file. Then while iterating items from the second file, consult the set constructed of the first file. In C++, the std::unordered_set will do fine.
#include <unordered_set>
using namespace std;
unordered_set<string> firstFileSet;
unordered_set<string> missingFromSecondFileSet;
string line;
while(!firstfile.eof())
{
getline(firstfile,line);
firstFileSet.insert(line);
}
Then for each word in the second file, use a second set collection to keep track of what words are missing.
while(!secondfile.eof())
{
getline(secondfile,line);
if (firstFileSet.find(line) != firstFileSet.end())
{
missingFromSecondFileSet.insert(line);
}
else
{
firstFileSet.erase(line);
}
}
After the above runs, firstFileSet contains all the lines in the first file that were not present in the second. missingFromSecondFileSet contains all the lines in the second file that were not in the first:
for (auto &s : firstFileSet)
{
cout << s << " was in the first file, but not the second" << endl;
}
for (auto &s : missingFromSecondFileSet)
{
cout << s << " was in the second file, but not the first" << endl;
}
There is a program called diff on linux which does just what you are looking to do in C++.
It is written in C so you can just copy its source code =P
for (;; cmp->file[0].buffered = cmp->file[1].buffered = 0)
{
/* Read a buffer's worth from both files. */
for (f = 0; f < 2; f++)
if (0 <= cmp->file[f].desc)
file_block_read (&cmp->file[f],
buffer_size - cmp->file[f].buffered);
/* If the buffers differ, the files differ. */
if (cmp->file[0].buffered != cmp->file[1].buffered
|| memcmp (cmp->file[0].buffer,
cmp->file[1].buffer,
cmp->file[0].buffered))
{
changes = 1;
break;
}
/* If we reach end of file, the files are the same. */
if (cmp->file[0].buffered != buffer_size)
{
changes = 0;
break;
}
}
Taken from ftp://mirrors.kernel.org/gnu/diffutils/diffutils-3.0.tar.gz > src/analyze.c

Stream not reading string properly

I am a university student and recently started programming on C++, I am currently having an issue reading in a string using a stringstream.
I am reading information from a .csv file and storing the information in a class, what is puzzling me the most is that my code works perfectly for the first line of my .csv file but not for the second.
This is my class:
class Player {
public:
string name;
int points = 0;
int gamesPlayed = 0;
int todaysPoints = 0;
int timesPresident = 0;
int timesScum = 0;
char playing = 'n';
};
This is how my .csv file is formatted:
Name;Points;Games Played;Times President;Times Scum
Grace;0;0;0;0
Gabriel;0;0;0;0
And this is how I am reading it:
int readInPlayersList(Player playersList[], string filename) {
listIn.open(filename);
string line;
istringstream fixedLine;
int i = 0;
int j;
getline(listIn, line); //first line doesn't matter
while (getline(listIn, line)) {
if (listIn.eof()) { break; }
j = 0;
while (line[j]) {
if (line[j] == ';') { //swapping ; by space to read in easily
line[j] = ' ';
}
++j;
}
fixedLine.str(line);
cout << "Before reading, line = " << line << endl;
fixedLine >> playersList[i].name >> playersList[i].points >> playersList[i].gamesPlayed >> playersList[i].timesPresident >> playersList[i].timesScum;
cout << "After readng -> " << playersList[i].name << " " << playersList[i].points << " " << playersList[i].gamesPlayed << " " << playersList[i].timesPresident << " " << playersList[i].timesScum << endl; //testing output
++i;
}
return i;
listIn.close();
}
As you can see, in order to find out what's wrong, I output what's in the line before reading into the class, and then I output the class members, for the first line, it reads it perfectly but not for the second and any other thereafter... See output below:
I really want to know what I am doing wrong here, appreciate any help, cheers!
Gabriel Groff

Strings and unordered_map running slow

Here is 2 functions in my code that are running REALLY SLOW.
Basically i read in a document name, open the document, then process it one word at a time. I need to split up the document into sentences, and give each sentence a hash table that represents the number of times the word appears in the sentence. I also need to keep track of all the new words, and a hash table for the total document.
When i run my code now on 10 documents, that have a total of 8000word, and 2100 uniq words it takes about 8000+ seconds to run... almost 1 second per word.
can you tell me how long if(istream.good()) should take?
Or, if you can tell when what is delaying my code. Please let me know if a section is not clear, i will help.
P.S. You can see in the code where i have a start = clock() and end = clock() commented it constantly returns < 1ms. And that is mind-boggleing
void DocProcess::indexString(string sentenceString, hash * sent){
stringstream iss;
string word;
iss.clear();
iss << sentenceString;
while(iss.good())
{
iss >> word;
word = formatWord(word);
std::unordered_map<std::string,int>::const_iterator IsNewWord = words.find(word);
if(IsNewWord == words.end())
{
std::pair<std::string,int> newWordPair (word,0);
std::pair<std::string,int> newWordPairPlusOne (word,1);
words.insert(newWordPair);
sent->insert(newWordPairPlusOne);
}
else
{
std::pair<std::string,int> newWordPairPlusOne (word,1);
sent->insert(newWordPairPlusOne);
}
}
}
void DocProcess::indexFile(string iFileName){
hash newDocHash;
hash newSentHash;
scoreAndInfo sentenceScore;
scoreAndInfo dummy;
fstream iFile;
fstream dFile;
string word;
string newDoc;
string fullDoc;
int minSentenceLength = 5;
int docNumber = 1;
int runningLength = 0;
int ProcessedWords = 0;
stringstream iss;
iFile.open(iFileName.c_str());
if(iFile.is_open())
{
while(iFile.good())
{
iFile >> newDoc;
dFile.open(newDoc.c_str());
DocNames.push_back(newDoc);
if(dFile.is_open())
{
scoreAndInfo documentScore;
//iss << dFile.rdbuf();
while(dFile.good())
{
//start = clock();
dFile >> word;
++ProcessedWords;
std::unordered_map<std::string,int>::const_iterator IsStopWord = stopWords.find(word);
if(runningLength >= minSentenceLength && IsStopWord != stopWords.end() || word[word.length()-1] == '.')
{
/* word is in the stop list, process the string*/
documentScore.second.second.append(" "+word);
sentenceScore.second.second.append(" "+word);
indexString(sentenceScore.second.second, &sentenceScore.second.first);
sentenceScore.first=0.0;
SentList.push_back(sentenceScore);
sentenceScore.second.first.clear(); //Clear hash
sentenceScore.second.second.clear(); // clear string
//sentenceScore = dummy;
runningLength = 0;
}
else
{
++runningLength;
sentenceScore.second.second.append(" "+word);
documentScore.second.second.append(" "+word);
}
//end = clock();
system("cls");
cout << "Processing doc number: " << docNumber << endl
<< "New Word count: " << words.size() << endl
<< "Total words: " << ProcessedWords << endl;
//<< "Last process time****: " << double(diffclock(end,start)) << " ms"<< endl;
}
indexString(documentScore.second.second, &documentScore.second.first);
documentScore.first=0.0;
DocList.push_back(documentScore);
dFile.close();
//iss.clear();
//documentScore = dummy;
++docNumber;
//end = clock();
system("cls");
cout << "Processing doc number: " << docNumber << endl
<< "Word count: " << words.size();
//<< "Last process time: " << double(diffclock(end,start)) << " ms"<< endl;
}
}
iFile.close();
}
else{ cout << "Unable to open index file: "<<endl <<iFileName << endl;}
}
`
Can you try it without
system("cls");
in any of the loops? That surely isn't helping, it's an expensive call.
To clear the screen quickly, instead of system("cls");, try cout << '\f';.