Referenced vector does not pass through functions - c++

The referenced vector to functions does not hold the information in memory. Do I have to use pointers?
Thanks.
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;
void menu();
void addvector(vector<string>& vec);
void subvector(vector<string>& vec);
void vectorsize(const vector<string>& vec);
void printvec(const vector<string>& vec);
void printvec_bw(const vector<string>& vec);
int main()
{
vector<string> svector;
menu();
return 0;
}
//functions definitions
void menu()
{
vector<string> svector;
int choice = 0;
cout << "Thanks for using this program! \n"
<< "Enter 1 to add a string to the vector \n"
<< "Enter 2 to remove the last string from the vector \n"
<< "Enter 3 to print the vector size \n"
<< "Enter 4 to print the contents of the vector \n"
<< "Enter 5 ----------------------------------- backwards \n"
<< "Enter 6 to end the program \n";
cin >> choice;
switch(choice)
{
case 1:
addvector(svector);
menu();
break;
case 2:
subvector(svector);
menu();
break;
case 3:
vectorsize(svector);
menu();
break;
case 4:
printvec(svector);
menu();
break;
case 5:
printvec_bw(svector);
menu();
break;
case 6:
exit(1);
default:
cout << "not a valid choice \n";
// menu is structured so that all other functions are called from it.
}
}
void addvector(vector<string>& vec)
{
//string line;
//int i = 0;
//cin.ignore(1, '\n');
//cout << "Enter the string please \n";
//getline(cin, line);
vec.push_back("the police man's beard is half-constructed");
}
void subvector(vector<string>& vec)
{
vec.pop_back();
return;
}
void vectorsize(const vector<string>& vec)
{
if (vec.empty())
{
cout << "vector is empty";
}
else
{
cout << vec.size() << endl;
}
return;
}
void printvec(const vector<string>& vec)
{
for(int i = 0; i < vec.size(); i++)
{
cout << vec[i] << endl;
}
return;
}
void printvec_bw(const vector<string>& vec)
{
for(int i = vec.size(); i > 0; i--)
{
cout << vec[i] << endl;
}
return;
}

Your problem is that each call to menu() creates a new vector that hides the previous one, this is why it seems to you like they're empty. If you really want to be calling menu recursively, pass it the vector reference that you created in main.
All that being said, menu systems are rarely ever recursive. You probably want a loop around your call to menu() in main that loops until the user has chosen to quit.

Your menu function is recursive.
That means that every new call of menu will create it's own vector, and throw it away when it's done.
If you want to reuse the svector, you need to either use a plain loop for the menu, or pass the original svector, created in the main, to the menu using a pass-by-reference argument.

Problem is that you call another menu() which allocates new svector on stack (in some part of memory).
Probably original code was void menu(vector<string>&svector)

You need to either have svector be a global (declared outside any function) or pass it as a parameter to menu. C++ does not have dynamic scope for functions.
EDIT: You can also wrap all this up in a class and repeatedly call menu().

svector is shared (is that what s stands for?), and variables which are shared between different scopes in C++ must be declared extern, or you get two separate local variables.
int main()
{
extern vector<string> svector;
…
void menu()
{
extern vector<string> svector;
…
Just kidding. svector should be an argument. Or a global would suffice. But don't use globals like this.

Related

C++ Vector of Objects, are they all named temp?

New to C++ OOP, I recently learned about classes and objects. I created a straightforward class and menu-driven program that adds a temp object to a vector of movies. I have a quick question that I can't quite understand.
Am I just pushing multiple "temp" objects into the vector?
In my head i'm visualizing this as vector my_movies = {temp, temp, temp}; and continously adding 'temp' objects until the user is done. Is this the right way to picture it?
#include <iostream>
#include <vector>
using namespace std;
class Movie
{
private:
string name;
public:
string get_name() { return name; }
void set_name(string n) { name = n; }
};
void menu() {
cout << "1. Add movie" << endl;
cout << "2. Show Movies" << endl;
cout << "3. Quit" << endl;
}
int getChoice(int &choice) {
cout << "Enter you choice: ";
cin >> choice;
return choice;
}
int main() {
vector<Movie> my_movies;
int choice = 0;
string name;
do {
menu();
getChoice(choice);
switch (choice) {
case 1: {
Movie temp;
cout << "Set user name: ";
cin >> name;
temp.set_name(name);
my_movies.push_back(temp);
break;
}
case 2: {
for (auto &mv : my_movies)
cout << mv << endl;
break;
}
}
} while (choice != 3);
return 0;
}
In your case, when you are calling push_back it will copy your "temp" object, which is a local object on the stack. It will be copied into a new object which is stored on the heap, held by the vector object. The vector will store these as an array internally (the default vector with the default allocator etc).
It's also possible to "move" the object (under C++11 and later), if you understand the difference, but doing push_back(std::move(temp)), which generally gives better performance. In your case it would avoid copying the string member "name", and move it instead, avoiding a new allocation for the string inside the Movie in the vector.
See here for more details on push_back
Appends the given element value to the end of the container.
The new element is initialized as a copy of value.
https://en.cppreference.com/w/cpp/container/vector/push_back
If you are just talking about the name of the movie, it will be what ever is entered from cin. Objects don't have names themselves. The local variable name "temp" is just what you see when you write the code, but is just used to tell the compiler which object is being used - the object itself doesn't have a name form the compilers perspective.

Having problem in working with insert, delete and search in an string array at the same time

I was trying to implement insert, delete and linear search in an string type array in the same code. Delete and Linear search works fine here, but insertion is not running perfectly.
Here is the main function of my code.
#include<iostream>
#include <stdlib.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
int main(int argc, char ** argv)
{
int siz;
cout<<"How many elements:";
cin>>siz;
string student[siz];
for(int i=0; i<siz; i++)
{
cin>>student[i];
}
cout<<"Array:";
for(int i=0; i<siz; i++)
cout<<student[i]<<endl;
int choice;
cout <<"Enter your choice :";
cin>>choice;
switch(choice)
{
case 0:
exit(0);
break;
case 1:
st_insert(student,siz);
break;
case 2:
st_delete(student,siz);
break;
case 3:
st_search(student,siz);
break;
case 4:
cout<<"All elements\n:";
for(int i=0; i<siz; i++)
cout<<student[i]<<endl;
break;
default:
cout<<"Wrong choice please try again !!!";
}
return 0;
}
The insert function is
void st_insert(string demo[], int siz)
{
int pos;
cout<<"Enter a position number to insert:";
cin>>pos;
string item;
cout<<"Enter a new Element :";
cin>>item;
cout<<"After Inserting "<<item<<", the updated list is: "<<endl;
for (int i=siz-1; i>=pos; i--)
{
demo[i+1] = demo[i];
}
demo[pos] = item;
for (int i=0; i<siz+1; i++)
cout<<"\t"<<demo[i]<<endl;
}
Sample Output if I want to insert an item
Yes, there is a solution. Don't use non-standard VLAs and don't use Plain-Old Arrays that provide no bounds checking. The solution is to use a vector of strings, e.g. std::vector<std::string>. That way you can add or replace any element you like and the memory is handled automatically.
For example, let's just take a vector of strings initialized with four strings:
std::vector<std::string> student { "my", "dog", "has", "fleas" };
Now student.size() will tell you how many strings are contained in the vector and you can replace (with bounds checking) with student.at(pos) = "new string";
You can list all elements in your vector using a range-based for loop, e.g.
std::cout << "Array:\n\n";
for (const auto& s : student)
std::cout << s << '\n';
Since the vector of strings student contains all the information you will need to either replace an existing element or add a new element at the end, your function (which must be of a type to indicate success/failure of the operation) could be written to take a single parameter -- a reference to your vector of strings, e.g.:
bool st_insert(std::vector<std::string>& demo)
{
size_t pos;
std::string item {};
std::cout << "Enter a position number to insert: ";
if (!(std::cin >> pos))
return false;
std::cout << "Enter a new Element: ";
if (!(std::cin >> item))
return false;
if (pos >= demo.size())
demo.push_back(item);
else
demo.at(pos) = item;
std::cout << "\nAfter Inserting \""<< item <<"\", the updated list is:\n\n";
for (const auto& s : demo)
std::cout << s << '\n';
return true;
}
If you want a compilable example, with 0-exit or 1-st_insert as your menu choices, you could do:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
bool st_insert(std::vector<std::string>& demo)
{
size_t pos;
std::string item {};
std::cout << "Enter a position number to insert: ";
if (!(std::cin >> pos))
return false;
std::cout << "Enter a new Element: ";
if (!(std::cin >> item))
return false;
if (pos >= demo.size())
demo.push_back(item);
else
demo.at(pos) = item;
std::cout << "\nAfter Inserting \""<< item <<"\", the updated list is:\n\n";
for (const auto& s : demo)
std::cout << s << '\n';
return true;
}
int main (void)
{
int choice;
std::string tmp;
std::vector<std::string> student { "my", "dog", "has", "fleas" };
std::cout << "Array:\n\n";
for (const auto& s : student)
std::cout << s << '\n';
std:: cout << "\nEnter menu choice: ";
if (!(std::cin >> choice)) {
std::cerr << "error: invalid integer value - choice.\n";
return 1;
}
switch(choice)
{
case 0:
exit(0);
break;
case 1:
if (!st_insert (student))
std::cerr << "error: unable to insert element.\n";
break;
default:
std::cout << "Wrong choice please try again !!!\n";
}
return 0;
}
Example Use/Output
Replace Exmaple:
$ ./bin/insert_str_item
Array:
my
dog
has
fleas
Enter menu choice: 1
Enter a position number to insert: 1
Enter a new Element: cat
After Inserting "cat", the updated list is:
my
cat
has
fleas
Add Example:
$ ./bin/insert_str_item
Array:
my
dog
has
fleas
Enter menu choice: 1
Enter a position number to insert: 40
Enter a new Element: now
After Inserting "now", the updated list is:
my
dog
has
fleas
now
(note: the st_insert() function was written so if the requested pos for the new string exceeds what the next string in the vector would be, it is simply added as the next string and the invalid position is discarded)
Now when you go to take input for your vector of strings, it is quite simple. just read your input into a temporary string and use the .push_back() member function to add the string to your vector of strings, e.g.
std::string tmp {};
std::cout << "enter a string: ";
if (std::cin >> tmp)
student.push_back(tmp);
(note: you must validate every user input before you use the value)
Adding Taking siz New Elements
From your example, if you did want to specify the number of new strings to enter, you could adjust the program as follows:
int main (void)
{
int choice;
size_t siz;
std::string tmp;
std::vector<std::string> student { "my", "dog", "has", "fleas" };
std::cout << "There are currently " << student.size() << " elements:\n\n";
for (const auto& s : student)
std::cout << s << '\n';
std::cout << "\nHow many elements would you like to add? ";
if (!(std::cin >> siz)) {
std::cerr << "error: invalid size-type input.\n";
return 1;
}
for (size_t i = 0; i < siz; i++) {
std::cout << "student[" << student.size() << "]: ";
if (std::cin >> tmp)
student.push_back(tmp);
}
std::cout << "\nCurrent strings:\n\n";
for (const auto& s : student)
std::cout << s << '\n';
std:: cout << "\nEnter menu choice: ";
if (!(std::cin >> choice)) {
std::cerr << "error: invalid integer value - choice.\n";
return 1;
}
switch(choice)
{
case 0:
exit(0);
break;
case 1:
if (!st_insert (student))
std::cerr << "error: unable to insert element.\n";
break;
default:
std::cout << "Wrong choice please try again !!!\n";
}
return 0;
}
Example Use/Output
$ ./bin/insert_str_item
There are currently 4 elements:
my
dog
has
fleas
How many elements would you like to add? 4
student[4]: my
student[5]: cat
student[6]: has
student[7]: none
Current strings:
my
dog
has
fleas
my
cat
has
none
Enter menu choice: 1
Enter a position number to insert: 5
Enter a new Element: frog
After Inserting "frog", the updated list is:
my
dog
has
fleas
my
frog
has
none
You will want to see std::vector and std::basic::string for full details of the use of std::vector and std::string. Also see: Why is “using namespace std;” considered bad practice? and C++: “std::endl” vs “\n”.
Look things over and let me know if you have further questions.
As rightly said by some authors , what is required by you should not be done by fixed memory allocation , instead dynamic memory allocation (example : vectors in c++) should be used. However since you wanted to try the fixed one still, you can do the following :
Declare a string array of a larger size, instead of the user input (siz). Let's say it to be of predefined size 1000. (You can notify user to have a array of size to be less).
Declare the siz variable as global and not local. Because when you come after doing any insertion / deletion operation your size should be more / less than it previously was.But if you are using it as local then the changes would not be reflected because of call by value.
EDITED code:
#include<iostream>
#include <stdlib.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int siz=0;
void st_insert(string demo[])
{
int pos;
cout<<"Enter a position number to insert:";
cin>>pos;
string item;
cout<<"Enter a new Element :";
cin>>item;
cout<<"After Inserting "<<item<<", the updated list is: "<<endl;
for (int i=siz-1; i>=pos; i--)
{
demo[i+1] = demo[i];
}
demo[pos] = item;
siz++;
for (int i=0; i<siz; i++)
cout<<"\t"<<demo[i]<<endl;
}
int main(int argc, char ** argv)
{
cout<<"How many elements:";
cin>>siz;
string student[1005];
for(int i=0; i<siz; i++)
{
cin>>student[i];
}
cout<<"Array:";
for(int i=0; i<siz; i++)
cout<<student[i]<<endl;
int choice;
cout <<"Enter your choice :";
cin>>choice;
switch(choice)
{
case 0:
exit(0);
break;
case 1:
st_insert(student);
break;
case 4:
cout<<"All elements\n:";
for(int i=0; i<siz; i++)
cout<<student[i]<<endl;
break;
default:
cout<<"Wrong choice please try again !!!";
}
return 0;
}
Rest all seems fine to me.
Hope you got it. :)
In C++, arrays have a fixed sized and when passed as parameters what you are actually getting is a pointer to the first element in the array. In you code, you are trying to access demo[i+1] when size equals size-1; this generates an error because you are trying to access a memory location that isn't part of the array (demo[size]). When inserting an element in an array, you need to first allocate a new chunk of memory with the new size, then you copy each element over(including the new value), and finally delete the old chunk of memory which is now unused.

Calling Main replaces vector object and overwrites data

I am learning c++ and I can't wrap my head around this problem. I have created a class object which hold information of a vehicle. And the class name is vehicle. Here is the class:
class vehicle {
private:
string vehicleNumber;
int vehicleType;
public:
//Default Constructor
vehicle();
//Overload Constructor - #params<vehicleNumber, vehicleType>
vehicle(string vehicleNo, int type){
vehicleNumber = vehicleNo;
vehicleType = type;
}
//Some stuff to test
string getNo(){
return vehicleNumber;
}
int getType(){
return vehicleType;
}
};
And now in my main I have a void method which then takes in user input and puts the object in a vector. So in my main:
//Ref
void storeVehicle(vector<vehicle>&);
void storeVehicle(vector<vehicle>& createNewVehicle){
string number;
int type;
cout << "Enter Vehicle Number: ";
cin >> number;
cout << "Enter the vehicle type: ";
cin >> type;
vehicle newV(number, type);
createNewVehicle.push_back(newV);
cout << endl;
}
//
Now here is the problem I am facing. Inside of my main method, I am creating the object. And this works perfectly find except if I call the main method again, it initializes the object again and I loose my previous data. I am not sure how to tackle this.
Here is the main method:
int main(){
vector<vehicle> newVehicle;
storeVehicle(newVehicle);
return main();
}
So here I am returning main() again so that it reruns. But when it does, i loose my previous vector which held the data. Now how can I keep the data and keep calling the storeVehicle method?
Edit
I also have a switch case which I am using to determine what the user chooses as an option. It may be to display the vehicle information or it maybe to add a new vehicle. In this case too, how can I add the vehicle without loosing previous data. Here is my switch which is inside another method:
void mainMenu(){
int option;
cin >> option;
switch(option){
case 1: {
vector<vehicle> newVehicle;
storeVehicle(newVehicle);
break;
}
default:
cout << "Wrong option";
}
}
So now in my main method, I am simply calling this switch method. Either way, I loose the data yes?
EDIT
I don't understand why people keep downvoting. Aren't we all here to learn? And yet I get a downvote. Sooner or later, stackoverflow decides to block me from asking questions.
Main isn't intended to be used like that, it's just an entry point for your application.
For what you're looking to do, you would be interested in looping. This way a certain section of your code can be ran repeatedly until a condition is met.
int main(){
vector<vehicle> newVehicle;
while(true)
{
storeVehicle(newVehicle);
}
return 0;
}
Take a look at how different loop types work. https://www.tutorialspoint.com/cplusplus/cpp_loop_types.htm
Also, the one in my example is an infinite loop, since the condition is always true.
EDIT The question was changed.
The problem is that each time you call the mainMenu function that the vector is recreated. Create the vector in your Main function and then pass it by ref into the mainMenu function, so that it can then be passed into your storeVehicle function.
int main()
{
vector<vehicle> newVehicle;
while (true)
{
mainMenu(newVehicle);
}
return 0;
}
void mainMenu(vector<vehicle>& createNewVehicle) {
int option;
cin >> option;
switch (option) {
case 1: {
storeVehicle(createNewVehicle);
break;
}
default:
cout << "Wrong option";
}
}
You'd have to add a header for this function to work.
#include <limits>
void storeVehicle(vector<vehicle>& createNewVehicle) {
string number;
int type;
cout << "Enter Vehicle Number: ";
cin >> number;
cout << "Enter the vehicle type: ";
cin >> type;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
vehicle newV(number, type);
createNewVehicle.push_back(newV);
cout << endl;
}

Sorting string array alphabetically in a 2D array (C++)

I have coded thus far and I am not sure how to sort using the 2-dimensional array. Basically, one function is for sorting an array of strings, another function is for swapping two strings. Any help would be appreciated. (Also I am not allowed to use c++ 11 :/)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void input_name(string&);
void sort_names(string&);
void repeat_pro(int&);
void sortArray(string, int);
int main() {
string b_list[100][2];
string name;
int choice;
int count=0;
cout << "Welcome to the Business Sorting Program!" << endl;
do{
input_name(name);
b_list[count][1] = name;
count++;
repeat_pro(choice);
cout<<"\n \n Your Businesses are:"<<endl;
for(int j=0; j<count; j++){
cout<<b_list[j][1]<<endl;
}
cout << "\n\n";
}while(choice == 0);
cout << "Thanks for using this program"<<endl;
return 0;
}
void input_name(string &name){
cout << "Enter in the name of the business: ";
getline(cin, name);
}
void sort_names(string &name){
}
void repeat_pro(int &choice){
cout << "Do you want to enter in more names: ";
string answ;
cin>>answ;
cin.ignore(1000,'\n');
if (answ == "YES" || answ == "Y" || answ == "yes" || answ == "y"){
choice = 0;
}
else {
choice = 1;
}
}
it is not clear to me from the description what problem the program really tried to solve. I'm assuming it's kind of like a two column spreadsheet, the second column is the name entered by the user(but what is in the first column?).
assume you need to keep the array in sorted order as the data goes in, just do a binary search (you can do a linear search for small dataset like 100 entries).
// we don't have lambda before C++11
struct comparator {
bool operator () (const string (&x)[2], const string (&y)[2]) const {
return x[1] < y[1];
}
};
//... omitted
string data[100][2];
int count = 0;
while (count < 100) {
// no rvalue, move, rvo, etc. before C++11
string name;
input_name(name);
// no type deduction and lambda
string (*position)[2] =
std::lower_bound(&data[0], &data[count], name, comparator());
int index = position - &data[0];
// simulate an vector::insert operation, but for our array
for (int i = count; i > index; --i) {
// before we had move in C++, we would do swap with an empty element.
// in this case, the entry at data[count] is default constructed
std::swap(data[i][1], data[i-1][1]);
}
data[index][1] = name;
}
//... omitted
of course we can use a typedef to make it cleaner, but that's left to you.

I have an invalid initialization of reference of type int& from expression of type in passing argument 1

Im trying to lean structures and I think I am doing something wrong when I use the structure and trying to call it into a function.
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
//Structure
struct Inventory
{
int NumberPartsBin;
};
//Function Prototypes.
void choiceMenu();
void AddParts(int &);
void RemoveParts(int &);
int main()
{
char Election;
int choice;
Inventory Parts = {10};
const int Valve_Choice = 1,
Quit_Choice = 2;
I am trying to to resolve this problem with one item, but I will use arrays for 10 items.
do {
choiceMenu();
cin>> choice;
if (choice >= Valve_Choice & choice <= Quit_Choice)
{
switch(choice){
case Valve_Choice:
cout<<"Enter A for Add Parts or R to Romove Parts";
cin >> Election;
if (Election=='A')
{
AddParts(Parts);// My problem is here
}
if else (Election =='R'){
RemoveParts(Parts);}
else{
cout << "Invalid Entry. Try Again";
cin >> Election; }
break;
case Quit_Choice:
cout<<"Program Ending";
return;
else
{
cout<<"Enter a valid choice!!;
cin >> choice;
}
}
}
while (choice >= Valve_Choice & choice < Quit_Choice);
system("pause");
return 0;
// Bin Choice
void choiceMenu()
{
// We use ofstream to create and write on a text file.
ofstream outputFile;
outputFile.open("C:\\Users\\Alexander MR\\Desktop\\CompanyABCPayRoll.txt");
// The headed of the document.
outputFile << " Inventoy\n";
outputFile << " = = = = = = = = \n";
outputFile << " *Choose the part of your preference.\n";
outputFile << " 1. valves = " << Parts.NumberPartsBin << endl;
outputFile << " 11. Choose 2 to quit the Program" << endl;
outputFile.close();
}
I am not sure of my function either.
my function to add parts
void AddParts(int &Parts1)
{
int Enter1;
Parts1.NumberPartsBin = Parts1.NumberPartsBin + Enter1;
}
My function to remove parts
void RemoveParts(int &Parts2)
{
int Enter2;
Parts2.NumberPartsBin = Parts2.NumberPartsBin - Enter2;
}
Reading the question with only parts of the code formatted is quite hard. The first thing I saw was:
void RemoveParts( int &Parts2 ) {
int Enter2;
Parts2.NumberPartsBin = Parts2.NumberPartsBin - Enter2;
}
This makes no sense at all. If Parts2 is an int, then you will never be able to say Parts2.NumberPartsBin. The second thing is int Enter2;. You never give it a value, but in the next line you want to subtract it from something‽
I'm guessing (at least with this function) that you are trying to do something like this:
void RemoveParts( Inventory& inventoryItem, int amountOfParts ) { // inventoryItem is passed by reference, amountOfParts is passed by value
inventoryItem.NumberPartsBin = inventoryItem.NumberPartsBin - amountOfParts;
}
Looking at your code, I'm guessing you're quite new to all of this. I'm no guru, but please:
Capitalize class/struct names and start variable names with a lowercase. ( like parts or election)
If you want to change the value that comes into a function, pass it by reference, but if it is something like an int or a char, simply pass it by value.
p.s. it's if, else if, else and not if else which will otherwise be the next error in your code.