Allocating dynamically an array of Strings in C++ - c++

I have allocated a string array in CPP with initial size and I need to dynamically resize it based on a counter.
This the initialization statement: string buffer[10];
I need to resize it based on a counter.
Is there a realloc function in cpp?

You should use something like a linked list such as std::vector or std::list to do so, here is an example:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <list>
using namespace std;
int main()
{
list<string> buffer;
int count = 0;
while (true)
{
string s;
cin >> s;
if (s._Equal("exit"))
break;
buffer.push_back(s);
count++;
}
cout << endl << endl << "We have a total of " << count << " string(s):";
for (auto i = buffer.begin(); i != buffer.end(); i++)
cout << endl << "- " << (*i).c_str();
cout << endl << endl;
system("pause");
return 0;
}
link: std::vector
std::vector is a sequence container that encapsulates dynamic size arrays.

Related

Why does my vector::erase call throw "vector subscript out of range"?

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.

increasing size of array of string in c++

I want to increase the size of the array of string after declaring it once, how can it be done. I need to increase the size in the following code..
#include<iostream>
using namespace std;
#include<string>
int main()
{
int n;
string A[] =
{ "vaibhav", "vinayak", "alok", "aman" };
int a = sizeof(A) / sizeof(A[0]);
cout << "The size is " << a << endl;
for (int i = 0; i < a; i++)
{
cout << A[i] << endl;
}
cout << "Enter the number of elements you want to add to the string"
<< endl;
cin >> n;
cout << "ok now enter the strings" << endl;
for (int i = a; i < n + a; i++)
{
cin >> A[i];
}
a = a + n;
A.resize(a); // THIS KIND OF THING
for (int i = 0; i < a; i++)
{
cout << A[i] << endl;
}
return 0;
}
Plain and simple: you cannot.
You can get a larger array, copy all your stuff over and use that instead. But why do all that, when there is a perfectly good class already there, doing it all for you: std::vector.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> A = {"vaibhav", "vinayak", "alok", "aman"};
std::cout << "The size is " << A.size() << std::endl;
for(string s : A)
{
std::cout << s << std::endl;
}
// want to enter more?
sd::string more;
std::cin >> more;
A.push_back(more);
std::cout << "The size is " << A.size() << std::endl;
for(string s : A)
{
std::cout << s << std::endl;
}
return 0;
}
Convert your code over to use std::vector and this problem becomes much easier to solve.
#include<iostream>
#include<string>
#include<vector>
int main(){
int n;
std::vector<std::string> A = {"vaibhav", "vinayak", "alok", "aman"};
int a = A.size();
std::cout << "The size is " << a << std::endl;
//Prefer Range-For when just iterating over all elements
for(std::string const& str : A){
std::cout << str << std::endl;
}
std::cout << "Enter the number of elements you want to add to the string" << std::endl;
std::cin >> n;
std::cout << "ok now enter the strings" << std::endl;
for(int i = 0; i < n; i++ ) {
//emplace_back automatically resizes the container when called.
A.emplace_back();
std::cin >> A.back();
//If you're using C++17, you can replace those two lines with just this:
//std::cin >> A.emplace_back();
}
for(std::string const& str : A){
std::cout << str << std::endl;
}
return 0;
}
Also, don't use using namespace std;, since it leads to expensive to fix bugs and makes your code harder to read for other C++ programmers.
I want to increase the size of the array of string after declaring it
once, how can it be done.
It cannot be done. Use std::vector if the element count isn't known at compile time or can change dynamically. It even has a resize member function named exactly like the one in your code.
You cannot increase the size of a Raw Array, you could use an std::vecto<std::string> as this type of array can grow at runtime.
However, you could also create a class that will store an array of string and create your own implementation to resize the raw array. Which would be creating a bigger array and copying all the other values over, then setting the class array to the new array (or just return it)

Increase all elements of a List in C++

#include <iostream>
#include <vector>
#include <iterator>
#include <iostream>
#include <cmath>
#include <string>
#include <utility>
#include <cstring>
#include <list>
using std::vector;
using std::cout;
using std::list;
using std::endl;
using std::string;
using namespace std;
template <typename T>
void showContents(T& input)
{
typename T::iterator it;
for (it=input.begin(); it != input.end(); it++)
{ cout << *it << " "; }
cout << endl;
}
int main()
{
int B[10] = {0,1,2,3,4,5,6,7,8,9};
cout<< "The first array is: "<< "\n";
int i;
for (i = 0; i<10; i++)
{cout<< B[i]<< " ";}
vector<int> KVec(B,B+10);
cout << "\n \n" << "The first vector is: " << endl;
showContents(KVec);
list<int> BList(B,B+10);
cout << "\n" << "The first list is: " << endl;
showContents(BList);
int BCopy [10];
cout<< "\n" <<"The second array is: "<< endl;
for(int i = 0; i <10; i++)
{
BCopy[i] = B[i];
BCopy[i] += 2;
cout<< BCopy[i]<< " ";
}
vector<int> KVec2(KVec);
cout<< "\n \n" << "The second vector is: "<< endl;
for (int i = 0; i<KVec2.size(); i++){
KVec2[i] += 3;
}
showContents(KVec2);
cout<< "\n" << "The second list is: "<< endl;
std::list<int> BList2 (BList);
for (std::list<int>::iterator b = BList.begin(); b!=BList.end(); ++b)
{
( *b += 5 );
showContents(BList2);
}
This is the code I have. I was able to correctly copy all the arrays, vectors , and lists and increasing the values of those accordingly. The only one I have not been able to increment in the list. My goal is to increment all the elements of the second list by 5. I have been using mulitple references to try and do it but I have tried everything and can not get it to work. Below I have my latest attempt at trying to increment all the values but that doesn't seem to work either so now I need help. That is the only thing left to do in this assignment so any help would be appreciated. Thank you.
Since my comment fixed your problem, I am converting it into an answer.
You copy constructed BList2 using values from BList (I am changing to brace initialization to avoid Most vexing parse). But then, you are iterating over values of BList again. Also, you don't need parentheses around *b += 5. Finally, your showContents function is probably meant to be outside of the loop.
std::list<int> BList2 {BList};
for (std::list<int>::iterator b = BList2.begin(); b != BList2.end(); ++b)
{
*b += 5;
}
showContents(BList2);

C++ vector confusion with .size() result

With the code below, I cannot figure out why numbs[numbs.size()] doesn't give me an appropriate response. I would assume it would give me the last item in the sorted vector, in this case it should be the largest. Yet, cout << numbs[numbs.size()]spits out garbage, e.g.
Number 1 entered. [1], smallest: 1. there are 1 elements in the vector. 1.36617e-231 is the largest.
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;
int main()
{
double number_input = 0.0;
string unit = " ";
vector<double> numbs;
while (cin >> number_input)
{
numbs.push_back(number_input);
cout << "Number " << number_input << "entered.\n";
for(int i = 0; i < numbs.size(); ++i)
{
cout << "[" << numbs[i] << "],";
}
sort(numbs.begin(),numbs.end());
cout << "smallest: " << numbs[0] << endl;
cout << "there are " << numbs.size() << " elements in the vector.\n";
cout << numbs[numbs.size()] << " is the largest.";
}
return 0;
}
Indexes in a vector are 0-based, just as arrays are. So the last value in a vector v is v[ v.size() - 1 ] assuming v.size() > 0

Dynamically Allocated Array of Structures: Assignment Issues (C++)

It's the last problem of the set. I need to created a dynamically allocated array of structures, and then I must access the data in these structures to insert into the output stream. Problem is, the compiler I'm using (g++) won't accept the way I'm assigning values to the structures in the array. Here is the code:
#include <iostream>
#include <cstring>
using namespace std;
struct candy
{
string name;
float weight;
int cal;
};
int main()
{
candy * pc = new candy [3];
pc[0] = {"ChocoBar", 4.5, 230};
pc[1] = {"SugarCrack", 9.3, 690};
pc[2] = {"TamponBar", 1.3, 100};
cout << "Bar None:\n";
cout << "Name: " << pc[0].name << endl;
cout << "Weight: " << pc[0].weight << endl;
cout << "Calories: " << pc[0].cal << "\n\n";
cout << "Bar One:\n";
cout << "Name: " << pc[1].name << endl;
cout << "Weight: " << pc[1].weight << endl;
cout << "Calories: " << pc[1].cal << "\n\n";
cout << "Bar Two:\n";
cout << "Name: " << pc[2].name << endl;
cout << "Weight: " << pc[2].weight << endl;
cout << "Calories: " << pc[2].cal << "\n\n";
delete [] pc;
return 0;
}
Having defined the structure type -- candy; and created a pointer(pc) to hold the address in memory assigned for three structures by new, I then attempted to assign values to the three structures. However, the compiler spit out a message saying that "extended initializer lists are not available...", which tells me that I botched the code such that the compiler doesn't even recognize my structure type as a structure (otherwise it would accept my list of three values).
I've just today learned of arrays, structures, pointers, and dynamic allocation of variables, and when it comes to arrays of structures statically assigned, and structures and arrays dynamically assigned (separately), I completed the exercises on the first try; but dynamically-assigned arrays of structures are giving me copious grief.
Please help.
First of all, you need to include the <string> header for std::string. Second, you need to ensure your compiler supports C++11. That would make the following code legal:
#include <iostream>
#include <string> // for std::string
struct candy
{
std::string name;
float weight;
int cal;
};
int main()
{
candy* pc = new candy[3];
pc[0] = {"ChocoBar", 4.5, 230}; // requires C++11
delete [] pc;
}
Next, you can learn about std::vector, a class template that does the dynamic memory allocation/de-allocation for you, and can resize its storage, effectively acting like an array that can grow in size:
#include <iostream>
#include <string>
#include <vector>
struct candy
{
std::string name;
float weight;
int cal;
};
int main()
{
using std::cout;
using std::endl;
using std::vector;
vector<candy> pc;
pc.push_back({"ChocoBar", 4.5, 230});
pc.push_back({"SugarCrack", 9.3, 690});
for (size_t i = 0; i < pc.size(); ++i)
{
cout << "Name: " << pc[i].name << endl;
}
}
Note that in C++11 you can also initialize the vector with a set of elements:
std::vector<candy> candies{{"ChocoBar", 4.5, 230},
{"SugarCrack", 9.3, 690},
{"TamponBar", 1.3, 100}};