Trying to add elements to a Vector classified with a Struct - c++

I'm making a program to basically show the statistics about words the user enters. The rest of the program is fine so far, but I'm having a hard time adding words to a vector of type WordCount.
I have looked around and found several answers, which I would've thought could solve my issue, but I either get a very weird compiler error or it just does not work. I have tried using emplace_back and push_back with calls I thought was right. In essence, my problem code is as follows:
#include <iostream>
#include <string>
#include <vector>
using namespace std; //for simplicity here
struct WordCount {
string word;
int count;
//I have tried using this too:
WordCount(string _word, int _count) : word{_word}, count{_count} {}
};
//...//
void wordToVector(/**...**/,string addStr, vector<WordCount>& wordStats){
/**... code that I've tested to work; basically determined if the
word was already said as I need to have unique words only...**/
wordStats.push_back(WordCount(addStr, 1));
/** also tried: (some had "#include <istream>" when using emplace_back
but that didn't seem to make a difference for me in any case)
wordStats.emplace_back(WordCount(addStr, 1));
wordStats.emplace_back({addStr, 1});
wordStats.push_back(addStr, 1)
wordStats.push_back(addStr).word; (and wordStats.push_back(1).count;)
**/
}
int main() {
vector<WordCount> wordStats(1); //"1" to initialize the size
wordStats.at(0).word = "";
wordStats.at(0).count = 0;
/**There's already a part to change the first values to what they should
be, and it worked last I tested it. Below is a part was for my
personal use to see if anything came out... if it worked**/
for (int i = 0; i < 3; i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
I must use a vector for this and cannot use pointers (as I've seen suggested) or #include <algorithm> per the instructions. If I typed in "Oh happy day!", it should be able to print (when fixed, with the current cout statements):
OH
1
HAPPY
1
DAY
1
(There's an earlier part that capitalizes every letter, which I tested to work).
This is my first post here because I'm lost. Please let me know if I provided too much or not enough. **Edited formatting

#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct WordCount {
string word;
int count;
};
void wordToVector(string addStr, vector<WordCount>& wordStats){
for (int i = 0; i < wordStats.size(); i++) {
if (wordStats[i].word == addStr) {
wordStats[i].count = wordStats[i].count + 1;
return;
}
}
struct WordCount wc;
wc.word = addStr;
wc.count = 1;
wordStats.push_back(wc);
}
int main() {
vector<WordCount> wordStats;
wordToVector("hehe", wordStats);
wordToVector("hehe", wordStats);
wordToVector("haha", wordStats);
for (int i = 0; i < wordStats.size(); i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
Using this code I get output:
hehe
2
haha
1
Is there anything else that needs to be added?
If you want to split the input by the spaces and check for occurrences of every word in the input it could be quite inefficient for longer texts to check for every word (Would be linear I think with M*N complexity), so if you are allowed I do suggest to use a map with word as key and value as the amount of occurrences - or something in that fashion.

Related

How to output a variable stored in another variable

So here's my code at the moment:
#include <iostream>
using namespace std;
int main() {
string x = "_one";
int sound_one = 7;
int sound_two = 8;
cout << ("sound") + x;
}
However when I run the code, it outputs 'sound_one' instead of '7'. How do I get it to output the variable sound_one instead of just 'sound_one'? Also, I need it so I can change x to different things (eg '_two') so it will then output sound_two instead. Any help would be greatly appreciated.
C++ is not a reflective language in the sense that you can acquire a variable name at runtime (variable names are normally compiled out of the program). You can use std::map though to achieve your immediate aim:
#include <iostream>
#include <string>
#include <map>
int main() {
using std::literals::string_literals::operator""s;
std::string x = "_one";
std::map<std::string, int> data;
data["sound_one"] = 7;
data["sound_two"] = 8;
std::cout << data["sound"s + x];
}
Note the notation "sound"s: the suffixed s denotes a std::string user defined literal.
You can't a variable from a string in this way. A work around is to use if/switch statements until the variable name is matched and then print it:
if(x == "_one") {
cout << sound_one;
}
else if(x == "_two") {
cout << sound_two;
}
else {
cout << "no match";
}
You can't do that in C++. You can use a map as shown in another answer, but I feel like what you really need is an array:
#include <format>
#include <iostream>
int main()
{
int data[] { 7, 8 };
std::cout << std::format("data[{}] = {}\n", 0, data[0]);
}
Arrays are usually better for such simple ordered sequences.

segmentation error depending on the order of my declarations in c++

I am new to c++. Doing it for the past 9 months or so and didn't learn it by the books. I always learnt whatever I just tried to accomplish. This might have ended in me doing some sloppy codes, so I am happy if you guys would suggest advices for a more proper code, but mainly solve the issue at hand.
What my code does: It's supposed to create a structure that makes it easy for me find and use radii in two dimensions x[-50;50] y[-50;50] but only for integers. My declared structure for this task is indexed by "sqared radius" (max: 5000) and filled with:
an index (for later use of the array "radidx")
the amount of positions with the same radius
its true radius (sqrt)
the x and y position of each coordinate
Just so you know what's going on in my code.
Now the problem goes like this: If I declare the array "radidx" before the structure declaration I end up with my solution. But if I declare it after the structure, I get a segmentation error because entries in the structure seem to go terribly wrong.
As far as I know and a friend confirmed this. The order of declarations on top of my code - long before any of these declarations is used - shouldn't make a difference, so this must be because some sloppy coding of myself. I would like to improve on this in order to avoid similar issues in future codes and when putting this code here into use. Neither of us could figure out where and what went wrong.
#include <cstdlib>
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <cmath>
#include <ctime>
#include <chrono>
#include <list>
#include <random>
using namespace std;
// int radidx[1030] = {0}; // Here it does work.
struct radii { int idx; int a=0; double r; int x[32]; int y[32]; };
radii radius[5000];
int radidx[1030] = {0}; // Here it doesn't work.
void rad_corr_init() {
int count [5001];
for (int i=0;i<5001;i++) count[i]=0;
/// Helper Function
/// count amount of positions with the same radius
for (int i=-50;i<51;i++)
for (int j=-50;j<51;j++)
count[i*i+j*j]++;
/// sort collected radii and exclude radii that don't exist so one can run a for-loop of an radius interval
int ik=0;
for (int i=1;i<5001;i++)
if(count[i]) {radidx[ik]=i; ik++;}
for (int i=-50;i<51;i++) // This is put here for testing
for (int j=-50;j<51;j++) { // This is put here for testing
int il = i*i+j*j; // This is put here for testing
radius[il].a=0; // This is put here for testing
} // This is put here for testing
/// Create Radius Structure
for (int i=-50;i<51;i++)
for (int j=-50;j<51;j++) {
int il = i*i+j*j;
int im = radius[il].a;
if (!radius[il].a) radius[il].r = sqrt(il);
radius[il].x[im] = i;
radius[il].y[im] = j;
radius[il].a++;
}
for (int i=0;i<1030;i++) {printf("%d\t%d\n",i,radidx[i]) /* This is put here for testing */ ;radius[radidx[i]].idx = i;}
}
int main() {
FILE * result = fopen( "result.txt", "w" );
rad_corr_init();
for (int i=0;i<1030;i++) {
int in = radidx[i];
int io = radius[in].a;
for (int j=0;j<io;j++) {
cout << i << '\t' << in << '\t' << radius[in].r << '\t' << j << '\t' << radius[in].x[j] << '\t' << radius[in].y[j] << endl;
fprintf(result, "%d\t%d\t%d\t%d\t%f\t%d\t%d\n", i, radius[in].idx, in, radius[in].r, j, radius[in].x[j], radius[in].y[j]);
}
}
// system("pause");
return 0;
}
I used the following commands for compiling (in case this is part of the issue):
g++ radius.cpp -std=c++11 -o ~[some name]/Desktop/run.out;time ~[some name]/Desktop/run.out
g++ -O4 radius.cpp -std=c++11 -o ~[some name]/Desktop/run.out;time ~[some name]/Desktop/run.out
Thank you guys for your help.
You have 5001 entries for count, but only 5000 for radius. When you access radius[50*50+50*50] (=radius[5000]) you exceed the bounds of the array and overwrite whatever is in memory after radius.
The solution is to change the declaration to radii radius[5001].

Adding a vector of multiple line numbers to my map with a key of words

So basically I'm working on a dictionary program that reads in a document and compares it to a list of words and if the words aren't found, I need to add the word to a map with its corresponding line numbers that that word appears on in the document. So I'm trying to do this, but I cannot get the desired results! Here's my code:
while (ss >> word)
{
wordCheck = d.findWord(word, words);
if(!wordCheck)
{
doc.missingMap(word, lineNum);
}
}
doc.displayMap();
//this just breaks up each line and checks for the words
void document::missingMap(string word, int lineNum)
{
vector<int> numbers;
numbers.push_back(lineNum);
misspelled[word] = numbers;
}
This is the function in the document calls that would put everything in the map. I don't know if I'm on the right track but if anyone could help me out that would be awesome.
Thanks!
more code in detail
Document class:
#pragma once
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <list>
using namespace std;
class document
{
private:
map<string, vector<int>> misspelled;
public:
document(void);
~document(void);
void missingMap(string word, int lineNum);
void displayMap();
};
document.cpp file
#include "document.h"
document::document(void)
{
map<string, vector<int> > misspelled;
}
document::~document(void){}
void document::missingMap(string word, int lineNum)
{
//if i declare it here it works but obviously i want to modify it everywhere in the class
misspelled[word].push_back(lineNum);
}
void document::displayMap()
{
for (map<string, vector<int>>::iterator i = misspelled.begin(); i != misspelled.end(); i++)
{
cout << i->first << ": ";
for (vector<int>::iterator j = i->second.begin(); j != i->second.end(); j++)
{
cout << *j << endl;
}
}
}
output:
debugging: 1
process: 2
removing: 2
programming: 3
process: 4
putting: 4
This is how i want it to output but don't know how:
debugging: 1
process: 2 4
programming: 3
putting: 4
removing: 2
hopefully this helps
Try misspelled[word].push_back(lineNum); instead.
Change your class declaration as follows:
class document
{
private:
std::map<std::string,std::vector<int> > misspelled;
// ^^^^^^^^^^^^^^^^ !!!
public:
document(void);
~document(void);
void missingMap(string word, int lineNum);
void displayMap();
};
in your document class, as you're doing now, you are replacing the vector stored in the misspelled map with a new one on every call of your missingMap() function, instead of adding more line numbers to the map entry (as you are intending I guess).
Note
You don't need to explicitly create a std::vector<int> instance as an initial entry for any access to misspelled[word], std::map handles that for you.

C++: How do you create a return function that returns a vector/array?

This is the motivation behind the code. There is a boy named Bob and its his birthday today. He invites 50 friends over but not all of his friends want to buy him gifts. Bob is presented with 50 presents, though some of them are empty. His good friends tell him to close every 2nd box. For every third box, he is supposed to change every closed to open and every open to closed. He continues to do this for every n-th box where n is less than 50. The open boxes in the end will have the presents.
This is supposed to assist me in figuring out a problem for my math class, but I am not aware of all the complicated aspects of C++ programming. I want my string getValue(vector &arr) to return an array/vector. This code doesn't compile but it shows what I'm trying to do.
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
string getValue(vector<string> &arr);
int main()
{
vector<string> myArr(2);
vector<string> newArr(2);
for(int i=2; i <= 50; i++)
{
if(i%2==0)
{
myArr.push_back("close");
}
else
{
myArr.push_back("open");
}
}
newArr = getValue(myArr);
for(int i=2; i <=50; i++)
{
cout << i << " " << newArr[i] << endl;
}
}
string getValue(vector<string> &arr)
{
for(int i=2; i <=50; i++)
{
if(arr[i]=="close")
{
arr[i]="open";
}
else if(arr[i]=="open")
{
arr[i]="close";
}
}
return arr;
}
You can't make your string getValue(vector<string> &arr) return an array/vector. It can only return a string. If you want a function to return an array/vector, then you have to say so in the function signature.
You're passing the vector into getValue() by reference, which means changes you make to it in that function will affect the original (in other words, you're not operating on a copy of the vector - you're actually operating on the vector).
So you don't need to return anything from getValue() - just make it void and it should do what you want.
string getValue(vector &arr) - the return type is string, not vector. You need to change its return type or set it to none.
PS:
newArr = getValue(myArr);
it's behind the SCOPE and it's wrongly positioned...
damn, third PS, wrong code rules are assigned
For the syntax part :-
The return type of the function is a string. Change it to vector for
your function to work properly.
You can simply declare the vectors globally. This will eliminate the
need to pass it to the function as well as return it.
For the logic part :-
Your question says that Bob toggles every third box but in your program Bob is changing every box to open if it is closed and every box to close if it is open. If what you wrote in the question is correct your code should be like this.
#include <iostream>
#include <vector>
using namespace std;
void getValue();
vector<string> myArr(2);
int main()
{
for(int i=2; i <= 50; i++)
{
if(i%2==0)
{
myArr.push_back("close");
}
else
{
myArr.push_back("open");
}
}
getValue();
for(int i=2; i <=50; i++)
{
cout << i << " " << myArr[i] << endl;
}
}
void getValue()
{
for(int i=3; i <=50; i+=3)
{
if(myArr[i]=="close")
{
myArr[i]="open";
}
else if(myArr[i]=="open")
{
myArr[i]="close";
}
}
}

Modifying a recursive string reverse function

I am doing some recursive exercises. The previous one was to make a reverse() function for a string which basically removes the first character and then combines the solution. I managed to do that, here is the source code (the entire source) The current task is to modify this function (the following exercise in the book) by adding a helper function which reverses a substring of the string. At this moment I am stuck at this. It is my understanding that you use helper functions when you need to pass additional arguments or something and this function takes none so I really have no idea how to approach this problem. Help appreciated.
#include <iostream>
#include <string>
using namespace std;
void reverse(string& text)
{
if (text.length() == 0)
{
return;
}
if (text.length() == 1)
{
return;
}
else
{
string firstLetter = text.substr(0,1);
text = text.substr(1, text.length()-1);
reverse(text);
text += firstLetter;
}
}
int main()
{
string a = "tyu";
reverse(a);
cout << a << endl;
return 0;
}
A guy suggested to use parameters, ect, this is my try with it:
#include <iostream>
#include <string>
using namespace std;
//is actually doing the hard work
void reverse1(string& input, int a, int b)
{
// base case
if( a >= b)
{
return;
}
//swap the characters
char tmp;
tmp = input[a];
input[a] = input[b];
input[b] = tmp;
//create the boundries for the new substring
a++;
b--;
//call the function again
reverse1(input, a, b);
}
// sets the parameters and calls the helper function
void strreverse(string& input)
{
reverse1(input, 0, input.length()-1);
}
int main()
{
cout << "Please enter the string which you want to be reversed:";
string a;
cin >> a;
strreverse(a);
cout << a << endl;
return 0;
}
The goal is probably to avoid creating all of the intermediate substrings. The helper function will take iterators, or a start and end index in addition to the string begin reversed.
Try to implement reversing so that there is only one instance of std::string (i.e. work with it as with an array). Then you will need a helper function with additional parameters (at least one parameter - which index to reverse now).
I would implement reverse here as series of exchanges: a[0] <-> a[n-1], a[1] <-> a[n-2] etc. where n is length of the string.
You can define a helper function that takes a start and an end index of the substring which it will reverse.
The function should exchange the element at the start index with that at the end index IFF the difference between the start and the end indices is 1. Otherwise, it places a recursive call to itself by decrementing the end index and incrementing the start index. You will need to keep check on the condition if the start and end index become same though.