why should i use back_inserter in function generate_n? - c++

hi guys i will show three codes 1 and 2 makes same work but the third one doesnt work. I want to understand why doesnt work or why do work the other two ? (strrand function produces random string)
1.
int main(){
vector<string> svec(50);
randomize();
generate_n(svec.begin(), 20, strrand);
display(svec.begin(), svec.end());
return 0;
}
2.
int main() {
vector<string> svec;
randomize();
generate_n(back_inserter(svec), 20, strrand);
display(svec.begin(), svec.end());
return 0;
}
3.
int main(){
vector<string> svec;
randomize();
generate_n(svec.begin(), 20, strrand);
display(svec.begin(), svec.end());
return 0;
}

The third has undefined behavior. In the first, you specify the vector size where you define the vector. That means it starts as a vector of 50 default-initialized (empty) strings. You then overwrite those strings with your random strings.
In the second, you use a back_insert_iterator to add the strings to the vector individually.
In the third, you start with an empty vector, and you attempt to use the (invalid) iterator to its (nonexistent) beginning. You then write 20 strings starting at whatever spot in memory its (random) initial value happens to refer to. You have not, however, at any time actually inserted a string into the vector. A vector normally keeps a count of how many items it current contains; in your third case, that will start out 0, and remain 0 throughout. When you attempt to show the "contents", you should get nothing (though, since you've already had undefined behavior at that point, anything is possible -- especially if some of the data you wrote happened to overwrite part of the vector's internal data.
What you have is a marginally more subtle (but equally problematic) version of well known beginner mistakes like:
char *s;
strcpy(s, "This will give UB");

Related

Is it possible to initialize a vector of strings from an array? If so, how?

So for example, on GeeksForGeeks.org, contributing user "Kartik" offers the following example for initializing a vector of integers:
// CPP program to initialize a vector from
// an array.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int arr[] = { 10, 20, 30 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vect(arr, arr + n);
for (int x : vect)
cout << x << " ";
return 0;
}
If I understand what I'm reading correctly, sizeof(arr) is some number (which I assume is the length of the array arr; i.e. 3, please correct me if I'm wrong) divided by sizeof(arr[0]) (which I assume to be 1) -- basically just being a roundabout way of saying 3/1 = 3.
At this point, vector<int> vect(arr, arr + n) appears to be a vector of size 3, with all values initialized to arr + n (which I'm assuming is a way of saying "use the 3 items from arr to instantiate; again, please correct me if I'm wrong).
Through whatever sorcery, the output is 10 20 30.
Now, regardless of whether or not any of my above rambling is coherent or even remotely correct, my main question is this: can the same technique be used to instantiate some example vector<string> stringVector such that it would iterate through strings designated by some example string stringArray[] = { "wordA", "wordB", "wordC" }? Because, as I understand it, strings have no numeric values, so I imagine it would be difficult to just say vector<string> stringVector(stringArray, stringArray + n) without encountering some funky junk. So if it is possible, how would one go about doing it?
As a rider, why, or in what type of instance, would anyone want to do this for a vector? Does instantiating it from an array (which as I understand it has constant size) defeat the purpose of the vector?
Just as a disclaimer, I'm new to C++ and a lot of the object-oriented syntax involving stuff like std::vector<_Ty, _Alloc>::vector...etc. makes absolutely no sense to me, so I may need that explained in an answer.
To whoever reads this, thank you for taking the time. I hope you're having a good day!
Clarifications:
sizeof(arr): returns the size in bytes of the array, which is 12 because it has 3 ints, and each int in most implementations has a size of 4 bytes, so 3 bytes x 4 = 12 bytes.
sizeof(arr[0]): returns the size in bytes of the first element of the array, which is 4 because it is an int array.
vector<int> vect(arr, arr + n): the vector class has multiple constructors. Here we are not using the constructor you are thinking of. We are using a constructor that takes begin and end iterators for a range of elements, making a copy of those elements. Pointers can be used as iterators, where in this case arr is the begin iterator and arr + n is the end iterator.
Note: int* + int returns int*.
Note: We should also consider that the "end" of an array is a pointer to the next space after the last item in the array, and the constructor will copy all the items except the item past the end.
Answer:
Yes, remember that here, the constructor is taking iterators, not any item of the array, so we can do it easily like this with little changes:
#include <bits/stdc++.h>
using namespace std;
int main()
{
// changed int to string and the array values
string arr[] = { "one", "two", "three" };
int n = sizeof(arr) / sizeof(arr[0]);
// changed int to string
vector<string> vect(arr, arr + n);
// changed int to string
for (string x : vect)
cout << x << " ";
return 0;
}
sizeof(arr)
sizeof gets the size of an object in bytes. The size of an object is the total number of bytes required by the object. Note that I'm using "object" in the C++ context, not the OOP context (an instance of a class).
The size of an object of a given type is always the same. A std::string containing "a" is the same size as a string containing the unabridged text of War and Peace. Any object that appears to have a variable size really contains a reference to variable length data stored elsewhere. In the case of std::string at its most basic, it is a pointer to a dynamically allocated array and an integer keeping track of how much of the dynamically allocated array is actually in use by the string. std::vector is similar, typically it's a pointer to the start of its data, a pointer to the end of its data, and a pointer to the first empty position in the data. No matter how big the vector is, sizeof(vector) will return the size of the pointers, any other book-keeping variables in the vector implementation, and any padding needed to guarantee correct memory alignment.
This means every item in an array is always the same size and thus the same distance from one another.
Through whatever sorcery...
The above means that the total size of the array divided by the size of one element in the array, sizeof(arr) / sizeof(arr[0]), will always provide the number of elements in the array. It doesn't matter what the array contains, numerical or otherwise. There are of course prettier ways like
template <class T, size_t N>
size_t getsize (const T (&array)[N])
{
return N;
}
and later
size_t n = getsize(arr);
As a rider, why, or in what type of instance, would anyone want to do this for a vector?
In the old days one could not directly construct a vector pre-loaded with data. No one wants to write some arbitrary number of lines of push_back to pound all the values in manually, It's boring as hell, a programmer almost always has better things to do, and the odds of injecting an error are too high. But you could nicely and easily format an array and feed the array into the vector, if you needed a vector at all. A lot of the time you could live off the array by itself because the contents were unchanging or at worst would only be shuffled around.
But if the number of contents could change, it could be time for a vector. If you're going to add items and you don't know the upper limit, it's time for vector. If you're calling into an API that requires a vector, it's time for a vector.
I can't speak for everybody, but I'm going to assume that like me a lot of people would have loved to have that easy-peasy array-style initialization for vectors, lists, maps, and the rest of the usual gang.
We were forced to write programs that generated the appropriate code to fill up the vector or define an array and copy the array into the vector much like the above example.
In C++11 we got our wish with std::initialzer_list and a variety of new initialization options1 that allowed
vector<string> vect{"abc","def","ghi"};
eliminating most cases where you would find yourself copying an array into a library container. And the masses rejoiced.
This coincided with a number of tools like std::size, std::begin and std::end to make converting an array into a vector a cakewalk. Assuming you don't pass the array into a function first.
1 Unfortunately the list of initialization options can get a lil' bewildering
Yes, you can do so - you just need to define something that the constructor for String will take (which is a 'const char')
const char * arr[] = { "abc","def","ghi" };
int n = sizeof(arr) / sizeof(arr[0]);
vector<string> vect(arr, arr + n);
for (string &x : vect)
cout << x << " ";
What this is effectively doing is creating the vector from two iterators (a pointer is, loosely, an iterator):
https://en.cppreference.com/w/cpp/container/vector/vector
Constructs the container with the contents of the range [first, last).
This constructor has the same effect as vector(static_cast<size_type>(first), static_cast<value_type>(last), a) if InputIt is an integral type.
And as #MartinYork pointed out, it's much more readable to use the C++ syntax:
const char * arr[] = { "abc","def","ghi" };
vector<string> vect(std::begin(arr), std::end(arr));
So if it is possible, how would one go about doing it?
Simply use vector constructor number 5, which accepts iterators to start and end of range
Constructs the container with the contents of the range [first,
last).
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::string arr[] = { "wordA", "wordB", "wordC" };
std::vector<std::string> v {std::begin(arr), std::end(arr)};
for (auto& str : v)
std::cout << str << "\n";
return 0;
}
Here's how you'd do it. Note that it's a tad awkward to get the length of the array, but that's just because arrays don't carry that information around with them (use a vector!).
#include<string>
#include<vector>
#include<iterator>
#include<iostream>
int main()
{
std::string arr[] = {"abc", "def", "ghi"};
std::vector<std::string> tmp;
std::copy(arr, arr + sizeof(arr)/sizeof(arr[0]), std::back_inserter(tmp));
for(auto str : tmp) {
std::cout<<str<<"\n";
}
}
Update: Yes good point about using std::begin and std::end for the array.

Find End of Array Declared as Struct Type C++

I was recently learning to use struct datatype in c++. I know how the basics of struct datatype work and how to manipulate its variables. But I was wondering how would I determine the end of struct datatype array. For example consider the code below:
struct PersonDetails
{
string name, address;
int age, number;
}
Now in c++ program I create an array of struct type as follows:
PersonDetails Data[500];
Now consider that I have 30 records in data array and I have to display these records by looping through data array's index. So how would I determine that I have to loop through only first 30 indexes as the data is only stored in these indexes. As in char array we compare all indexes with '\0' to determine the end of array. Then what method will we use for Data[] array?
An edit that I have no idea about Vectors and the project i am working on requires me to use basics of c++(functions, control structures, loops, etc.).
It's not feasible.
For char[], back in times of C standardization, developers agreed to use \0 (integer value 0) as a special character marking end-of-string. Everything works as long as everyone is following this convention (i.e. both standard library functions and developers using those functions).
If you wanted to have such a convention for your type, you could just write down "Data object with both strings empty and both ints equal to 0 is array terminator", but you would have to follow this convention. You'd have to write functions that would stop processing array upon finding such an object. You'd have to make sure that in every array there is at least one such object.
Instead
You should use std::vector<Data> which can automatically accomodate for any number of Data objects and will now precisely how many of them are currently stored (using size() method)
or
use std::array<Data, 30>, which can store exactly 30 objects and you can assume all of them are valid objects.
IMHO the correct way to solve this is to not use a C-style array, but instead use a std::array or std::vector that knows it's .size().
Iterating a std::vector or std::array is trivial:
for (const auto& element : Data_array) {
// Do something with the array element
}
See also:
https://en.cppreference.com/w/cpp/container/array
https://en.cppreference.com/w/cpp/container/vector
https://en.cppreference.com/w/cpp/language/for
https://en.cppreference.com/w/cpp/language/range-for
The simplest solution is to just have a separate variable specifying how many array elements are filled in.
PersonDetails Data[500];
int numPersons = 0;
Data[0].name = ... ;
Data[0].address = ...;
Data[0].age = ...;
Data[0].number = ...;
numPersons = 1;
Data[1].name = ... ;
Data[1].address = ...;
Data[1].age = ...;
Data[1].number = ...;
numPersons = 2;
...
Then you use that variable when looping through the array.
for (int i = 0; i < numPersons; ++i)
{
// use Data[i] as needed...
}
I don't really agree using std::array makes any difference.
The problem you currently have doesn't occur in whether we have such an element in the container, but whether the element we are inspecting useful.
Consider the example you gave, for an array of chars, we simply check whether one of the elements is \0 to decide whether or not we should halt the iteration.
How does that work? The ramaining elements, of course, default initialized to be \0, they exist, but of no use.
Similarly, you can check, in this example, whether
name.empty()
Or, in order to avoid any possible exception, as mentioned in the comment section, do this:
add user-defined constructor to the class ( or struct, they are same actually.) which initialize age to -1 and then check if age == -1.
because it's impossible for a people not having any name, that means, you have not assign to any of the remaining elements. Thus, stop iteration.
As a supplement, using std::vector makes sense, but if that isn't a option for you for the time being, you don't need to consider it.

is it possible to access an element within array of array?

i have an array b[i] which stores the certain indices of another array a[i];both are integer arrays
Is it possible to access it as
a[b[i]]
#include <iostream>
using namespace std;
int main()
{
int k=0,v=0,i,b[10],c[10];
int a[]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
if(a[i]%2==0)
{b[k]=i; k++;}
}
for(i=0;i<10;i++)
{
c[v]=a[b[i]];
v++;
}
return 0;
}
results in segmentation fault
In your second loop, the b array is only half initialized (once for every even number from 1 to 10) so when you try to dereference b[5] you get undefined behavior and hence a segfault
It works fine until you get to i = 5 for the second loop. When i = 5, a[b[5]] is undefined because b[5] is uninitialized. After the first loop, you have b[] = {1, 3, 5, 7, 9, ....} the rest is uninitialized. Try to initialize b[10] and it should work.
b[10] = {};
This method should work:
a[b[i]];
I'm not 100% sure it will work though, because the compiler has a role to play here too. For example, it works perfectly in TC++...
A better way to do it is this:
for(i=0;i<10;i++)
{
int temp=b[i];
c[v]=a[temp];
v++;
}
Here is the reason for the error you see:
'Segmentation fault' in this case means that you used a[] array index well beyond a value within memory available to the process (note: it does not need to be beyond the memory range of your computer to get this error; also note that using indexes slightly bigger than array size usually do not cause segmentation faults; but such index value is still a semantic error, of course).
When you declare b[], you do not initialize it (and that is usual).
Your first loop only initializes selected elements of b[]: only as much elements from the beginning of b[], as there are even numbers in a[] (you use the condition:a[i]%2==0).
Currently, you have 5 even numbers in a: 2,4,6,8,10. This is sufficient to initialize elements of b[0]...b[4]. The elements of b[] starting with b[5] are left uninitialized, i.e. contain numbers which can be considered random, or trash. You can print b[5]...b[9] to see what do they contain without initialization – it is often 0’s (making debugging even harder, because a[0] does not cause segmentation faults - but a[0] is probably not what you want to get in c[]).
But in different runs of your program elements of b[] starting with b[5] can be anything (and then any of them can make a segmentation fault, e.g. a[-2000000000]).
Chances are extremely low that these accidental values will represent valid indexes of a[].
Relief: change your SECOND loop so it runs only k times, not 10 times. This was probably your initial intention, anyway:
for(i=0;i<k;i++)
#include <iostream>
using namespace std;
int main()
{
int k=0,v=0,i,b[10],c[10];
int a[]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
if(a[i]%2==0)
{b[k]=i; k++;}
}
for(i=0;i<5;i++)
{
c[v]=a[b[i]];
v++;
}
return 0;
}
works well

c++ vectors and pointers

As i understand if i dont store pointers, everything in c++ gets copied, which can lead to bad performance (ignore the simplicity of my example). So i thought i store my objects as pointers instead of string object inside my vector, thats better for performance right? (assumining i have very long strings and lots of them).
The problem when i try to iterate over my vector of string pointers is i cant extract the actual value from them
string test = "my-name";
vector<string*> names(20);
names.push_back(&test);
vector<string*>::iterator iterator = names.begin();
while (iterator != names.end())
{
std::cout << (*iterator) << ":" << std::endl;
// std::cout << *(*iterator); // fails
iterator++;
}
See the commented line, i have no problem in receiving the string pointer. But when i try to get the string pointers value i get an error (i couldnt find what excatly the error is but the program just fails).
I also tried storing (iterator) in a new string variable and but it didnt help?
You've created the vector and initialized it to contain 20 items. Those items are being default initialized, which in the case of a pointer is a null pointer. The program is having trouble dereferencing those null pointers.
One piece of advice is to not worry about what's most efficient until you have a demonstrated problem. This code would certainly work much better with a vector<string> versus a vector<string*>.
No, no, a thousand times no.
Don't prematurely optimize. If the program is fast, there's no need to worry about performance. In this instance, the pointers clearly reduce performance by consuming memory and time, since each object is only the target of a single pointer!
Not to mention that manual pointer programming tends to introduce errors, especially for novices. Sacrificing correctness and stability for performance is a huge step backwards.
The advantage of C++ is that it simplifies the optimization process by providing encapsulated data structures and algorithms. So when you decide to optimize, you can usually do so by swapping in standard parts.
If you want to learn about optimizing data structures, read up on smart pointers.
This is probably the program you want:
vector<string> names(20, "my-name");
for ( vector<string>::iterator iterator = names.begin();
iterator != names.end();
++ iterator )
{
std::cout << *iterator << '\n';
}
Your code looks like you're storing a pointer to a stack-based variable into a vector. As soon as the function where your string is declared returns, that string becomes garbage and the pointer is invalid. If you're going to store pointers into a vector, you probably need to allocate your strings dynamically (using new).
Have a look at your initialization:
string test = "my-name";
vector<string*> names(20);
names.push_back(&test);
You first create a std::vector with 20 elements.
Then you use push_back to append a 21st element, which points to a valid string. That's fine, but this element is never reached in the loop: the first iteration crashes already since the first 20 pointers stored in the vector don't point to valid strings.
Dereferencing an invalid pointer causes a crash. If you make sure that you have a valid pointers in your vector, **iterator is just fine to access an element.
Try
if (*iterator)
{
std::cout << *(*iterator) << ":" << std::endl;
}
Mark Ransom explains why some of the pointers are now
string test = "my-name";
vector<string*> names(20);
The size of vector is 20, meaning it can hold 20 string pointers.
names.push_back(&test);
With the push_back operation, you are leaving out the first 20 elements and adding a new element to the vector which holds the address of test. First 20 elements of vector are uninitialized and might be pointing to garbage. And the while loop runs till the end of vector whose size is 21 and dereferencing uninitialized pointers is what causing the problem. Since the size of vector can be dynamically increased with a push_back operation, there is no need to explicitly mention the size.
vector<string*> names; // Not explicitly mentioning the size and the rest of
// the program should work as expected.

C++ How can I iterate till the end of a dynamic array?

suppose I declare a dynamic array like
int *dynArray = new int [1];
which is initialized with an unknown amount of int values at some point.
How would I iterate till the end of my array of unknown size?
Also, if it read a blank space would its corresponding position in the array end up junked?
Copying Input From users post below:
Thing is:
a) I'm not allowed to use STL (means: no )
b) I want to decompose a string into its characters and store them. So far I wanted to use a function like this:
string breakLine (string line){
int lineSize = line.size();
const char *aux;
aux=line.data();
int index=0;
while (index<=lineSize){
mySynonyms[index]=aux[index];
index++;
}
I thought that the array aux would end up junked if there was a large blank space between the two numbers to be stored (apparently not). And I was wondering if there was a way to iterate till an undefined end in this type of array. Thanks for you answers.
You don't: wrap the array into a structure that remembers its length: std::vector.
std::vector v(1);
std::for_each( v.begin(), v.end(), ... );
No portable way of doing this. Either pass the size together with the array, or, better, use a standard container such as std::vector
Short answer is that you can't. If you have a pointer to the first element of an array, you can't know what the size of the array is. Why do you want to use a array in the first place. You would be much better off using a std::vector if your array can change size dynamically, or a boost::Array if it will be a fixed size.
I don't understand your second question.
Your code needs to keep to track of the array, so the size would never be unknown. (Or you would have to use some library with code that does this.)
I don't understand the last part of your quesiton. Could you elaborate?
You explained in your post below that you want to look at the guts of a std::string.
If you are expecting your stirng to be like a c-string (aka doesn't contain NULLs), then use line.c_str() instead of line.data(). This will guarantee that aux points to a null terminates c-style string.
After that you can iterate until aux[index] == '\0';
Otherwise, you can use line.data() and string.length/size to get it's size like in your example.
However, "decomposing a string into its characters" is pretty pointless, a string is an array of characters. Just make of copy of the string and store that. You are allowed to do:
char ch = line[index];
Better yet, use iterators on the original string!
for(std::string::const_iterator it = line.begin(); it != line.end(); ++it) {
const char ch = *it;
// do whatever with ch
}
a) I'm not allowed to use STL (means:
no )
What?? Who's moronic idea was that?
std::vector isn't part of the "STL" (which is a copyrighted product of HP), but is (and has been for nearly a decade) part of the C++ Language Standard.
If you're not allowed to use the STL (for whatever reason), the first thing you want to do is actually to implement your own version of it – at least the parts you need, with the level of customizability you need. For example, it's probably overkill to make your own vector class parametrizable with a custom allocator. But nevertheless do implement your own lightweight vector. Everything else will result in a bad, hardly maintainable solution.
This smells like homework, and the teacher's objective is to give you a feeling of what it takes to implement dynamic arrays. So far you're getting an F.
You need to realize that when you allocate memory like this
int *dynArray = new int [1];
you allocate precisely one integer, not an indefinite number of integers to be expanded by some unidentified magic. Most importantly, you can only say
dynArray[0] = 78;
but you cannot say
dynArray[1] = 8973;
The element at index 1 does not exist, you're stepping into memory that was not reserved for you. This particular violation will result in a crash later on, when you deallocate the array, because the memory where you stored 8973 belongs to the heap management data structures, and you corrupted your heap.
As many other responders mention, you must know how many elements you have in the array at all times. So, you have to do something along the lines of
int arraySize = 1;
int *dynArray = new int [arraySize];
arraySize goes together with the array, and is best combined with dynArray in one C++ object.
Now, before you assign to dynarray[1], you have to re-allocate the array:
if (index > arraySize) {
int newSize = index+1;
int *newArray = new int[newSize]
// don't forget to copy the data from old array to new
memcpy(newarray dynArray, sizeof *newArray * arraySize);
arraySize = newSize;
dynArray = newArray;
}
// now you're ready!
dynArray[index] = value;
Now, if you want to make it a bit more efficient, you allocate more than you need, so you don't have to allocate each time you add an element. I'll leave this as an exercise to the reader.
And after doing all this, you get to submit your homework and you get to appreciate the humble std::vector that does all of this for you, plus a lot more.
Use a vector, which has a vector.size() function that returns an integer and a vector.end() function that returns an iterator.
You could create a simple Vector class that has only the methods you need. I actually had to recreate the Vector class for a class that I took this year, it's not very difficult.
If there's a value that cannot be valid, you can use that as a sentinel, and make sure all of your arrays are terminated with that. Of course, it's error-prone and will cause hard-to-find bugs when you happen to miss doing it once, but that's what we used to do while reading files in FORTRAN (back in the all-caps days, and before END= became standard).
Yes, I'm dating myself.