i'm trying to store some elements that is going to change every time, but i don't know which
way is better and why. I'm thinking about two ways, 1) declaring array of int and loop or
use vector's.
Which way is better and why?
Does declaring array of int have any future memore problems as leak?
the code down below show the two ways i'm talking about:
1)
#include <iostream>
#include <vector>
int main()
{
int x[5];
x[0] = 10;
x[1] = 20;
x[2] = 30;
x[3] = 40;
x[4] = 50;
for(unsigned int i = 0;i<=sizeof(x[5]); i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
2)
#include <iostream>
#include <vector>
int main()
{
std::vector<int> x;
x.push_back(10);
x.push_back(20);
x.push_back(30);
x.push_back(40);
x.push_back(50);
for(unsigned int i = 0;i<=x.size()-1; i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
If this is all you have to do, and your array will always have a size that is known at compile time, then you do not need std::vector.
On the other hand, in C++11 you could use std::array instead of a plain C array (std::array is a zero-overhead, safer and more functional wrapper over a C array):
#include <iostream>
#include <array>
int main()
{
std::array<int, 5> x = { 10, 20, 30, 40, 50 };
for (unsigned int i = 0; i < x.size(); i++)
// ^^^^^^^^
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
}
Here is a live example. Notice, that std::array offers a size() member function which you may want to use instead of the sizeof operator.
Moreover, since std::array is a standard sequence container, you could iterate through its element this way:
std::size_t i = 0;
for (auto e : x)
{
std:: cout << "x[" << i++ << "] = "<< e << std::endl;
}
Here is a live example.
If the size is known at compile time, use std::array. If not, use std::vector. In either case, use iterators to look at the elements:
typedef std::array<int> my_container_type;
typedef my_container::iterator iterator;
my_container_type my_container = { whatever };
for (iterator it = my_container.begin(); it != my_container.end(); ++it)
std::cout << "x[" << (it - my_container.begin()) << "] = " << *it << '\n';
By using iterators you greatly reduce the risk of accidentally using a loop limit like sizeof(x[5]), which is nonsense.
Neither is "better". They both address entirely different use cases.
If you know the array size at compile time and are 100% sure it will never change, sure, use a plain old array. It has less overhead, and the compiler can even aid you with static analysis by spotting any attempts to read outside the boundaries.
On the other hand, if you are unsure of the array's side (i.e. you will be reading input from a file or the user), then use the std::vector. It can grow to any size to meet your needs.
Related
Doing an exercise to find the mean and mode of a list of numbers input by a user. I have written the program and it works, but I'm wondering if my function 'calcMode' is too large for this program. I've just started looking into functions which is a first attempt. Would it be better to write smaller functions? and if so what parts can I split? Im pretty new to C++ and also looking if I can improve this code. Is there any changes I can make to make this run more efficient?
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int calcMean(vector<int> numberList)
{
int originNumber = numberList[0];
int nextNumber;
int count = 0;
int highestCount = 0;
int mean = 0;
for (unsigned int i = 0; i <= numberList.size() - 1; i++)
{
nextNumber = numberList[i];
if (nextNumber == originNumber)
count++;
else
{
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
count = 1;
originNumber = nextNumber;
}
}
if (count > highestCount)
{
highestCount = count;
mean = originNumber;
}
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
return mean;
}
int main()
{
vector<int> v;
int userNumber;
cout << "Please type a list of numbers so we can arrange them and find the mean: "<<endl;
while (cin >> userNumber) v.push_back(userNumber);
sort(v.begin(), v.end());
for (int x : v) cout << x << " | ";
cout << endl;
cout<<calcMean(v)<<" is the mean"<<endl;
return 0;
}
One thing to watch out for is copying vectors when you don't need to.
The function signature
int calcMode(vector<int> numberList)
means the numberList will get copied.
int calcMode(const & vector<int> numberList)
will avoid the copy. Scott Meyer's Effective C++ talks about this.
As an aside, calling is a numberList is misleading - it isn't a list.
There are a couple of points that are worth being aware of in the for loop:
for (unsigned int i = 0; i <= numberList.size()-1; i++)
First, this might calculate the size() every time. An optimiser might get rid of this for you, but some people will write
for (unsigned int i = 0, size=numberList.size(); i <= size-1; i++)
The size is found once this way, instead of potentially each time.
They might even change the i++ to ++i. There used to a potential overhead here, since the post-increment might involve an extra temporary value
One question - are you *sure this gives the right answer?
The comparison nextNumber == originNumber is looking at the first number to begin with.
Try it with 1, 2, 2.
One final point. If this is general purpose, what happens if the list is empty?
Would it be better to write smaller functions?
Yes, you can make do the same job using std::map<>; which could be
a much appropriate way to count the repetition of the array elements.
Secondly, it would be much safer to know, what is the size of the
array. Therefore I suggest the following:
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
In the calcMode(), you can easily const reference, so that array
will not be copied to the function.
Here is the updated code with above mentioned manner which you can refer:
#include <iostream>
#include <algorithm>
#include <map>
int calcMode(const std::map<int,int>& Map)
{
int currentRepetition = 0;
int mode = 0;
for(const auto& number: Map)
{
std::cout << "The Number " << number.first << " appears " << number.second << " times." << std::endl;
if(currentRepetition < number.second )
{
mode = number.first; // the number
currentRepetition = number.second; // the repetition of the that number
}
}
return mode;
}
int main()
{
int arraySize;
int userNumber;
std::map<int,int> Map;
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
std::cout << "Please type a list of numbers so we can arrange them and find the mean: " << std::endl;
while (arraySize--)
{
std::cin >> userNumber;
Map[userNumber]++;
}
std::cout << calcMode(Map)<<" is the mode" << std::endl;
return 0;
}
Update: After posting this answer, I have found that you have edited your function with mean instead of mode. I really didn't get it.
Regarding mean & mode: I recommend you to read more. Because in general, a data set can have multiple modes and only one mean.
I personally wouldn't split this code up in smaller blocks, only if i'd want to reuse some code in other methods. But just for this method it's more readable like this.
The order of excecution is aroun O(n) for calc which is quite oke if you ask me
Is there any alternative to a range-based for loop when it comes to vector arrays? I've noticed that c++98 won't allow range-based for loops. Here is some sample code looping through a vector array using a range based for loop:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vecArray1 (3,20);
for (int v: vecArray1) {
cout << "ArrayValue:" << v << endl;
}
return 0;
}
Now here is an alternative I've tried that didn't work:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vecArray1 (3,20);
for (int i=0; i<sizeof(vecArray1); ++i) {
cout << "ArrayValue:" << vecArray1[i] << endl;
}
return 0;
}
It outputs 10 elements instead of 3 defined by the vector array above. Are there any alternatives to range-based for loops that work with c++98?
C++98 does not allow for range-based for-loops.
In C++98 you would need to do the following:
for(unsigned int i=0;i<vecArray.size();++i)
std::cout << "ArrayValue: " << vecArray[i] << std::endl;
or
for(std::vector<int>::iterator it=vecArray.begin();it!=vecArray.end();++it)
std::cout << "ArrayValue: " << *it << std::endl;
The operator
sizeof
does NOT give you the length of an array. Instead, it returns an unsigned integer representing the number of bytes of the type you give as the argument.
For example,
std::cout << sizeof(unsigned long long) << std::endl;
prints
8
on my machine, because the type unsigned long long consista of 64-bits, or 64/8 = 8 bytes.
In C++11 we now have range-based for-loops:
Examples:
for(int i : vecArray)
std::cout << "i = " << i << std::endl;
for(const int& i : vecArray)
std::cout << "i = " << i << std::endl;
In the first example the values are copied from vecArray into the variable i. In the second example you are instead working with const references to the values in vecArray (which could be useful for objects which are expensive to copy).
In fact, the range-based for loops in C++11 are available for all types on which you can call begin() and end() (i.e. those which you can iterate through).
sizeof(vecArray1) doesn't do what you think it does.
Either use:
for (int i=0; i<vecArray1.size(); ++i) {
cout << "ArrayValue:" << vecArray1[i] << endl;
}
or:
for (std::vector<int>::iterator it = vecArray1.begin(); it != vecArray1.end(); it++) {
cout << "ArrayValue: " << *it << endl;
}
The second one is more verbose, but works for other types of collections as well (like std::list) and is more similar to what the range-based for loop does.
I have noticed that in gcc C11 you can pass any matrix to a function fn(int row, int col, int array[row][col]). How to translate my below placed (in a link to an another stackoverflow answer) program in C11 to a program in C++11?
C - allocating a matrix in a function
As you can see I can pass to functions static and dynamic allocated arrays in C11. Is it possible in C++11?
I have made an exemplary program based on different stackoverflow answers, but all functions work for array1 and none of them works for array2, where double array1[ROW][COL] = { { } } and auto array2 = new double[ROW][COL]() ?
How to make a function for both arrays as is made in C11 fn(int row, int col, int array[row][col])?
#include <iostream>
#include <utility>
#include <type_traits>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
const int ROW=2;
const int COL=2;
template <size_t row, size_t col>
void process_2d_array_template(double (&array)[row][col])
{
cout << __func__ << endl;
for (size_t i = 0; i < row; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < col; ++j)
cout << array[i][j] << '\t';
cout << endl;
}
}
void process_2d_array_pointer(double (*array)[ROW][COL])
{
cout << __func__ << endl;
for (size_t i = 0; i < ROW; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < COL; ++j)
cout << (*array)[i][j] << '\t';
cout << endl;
}
}
// int array[][10] is just fancy notation for the same thing
void process_2d_array(double (*array)[COL], size_t row)
{
cout << __func__ << endl;
for (size_t i = 0; i < row; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < COL; ++j)
cout << array[i][j] << '\t';
cout << endl;
}
}
// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(double **array, size_t row, size_t col)
{
cout << __func__ << endl;
for (size_t i = 0; i < row; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < col; ++j)
cout << array[i][j] << '\t';
cout << endl;
}
}
int main()
{
double array1[ROW][COL] = { { } };
process_2d_array_template(array1);
process_2d_array_pointer(&array1); // <-- notice the unusual usage of addressof (&) operator on an array
process_2d_array(array1, ROW);
// works since a's first dimension decays into a pointer thereby becoming int (*)[COL]
double *b[ROW]; // surrogate
for (size_t i = 0; i < ROW; ++i)
{
b[i] = array1[i];
}
process_pointer_2_pointer(b, ROW, COL);
// allocate (with initialization by parentheses () )
auto array2 = new double[ROW][COL]();
// pollute the memory
array2[0][0] = 2;
array2[1][0] = 3;
array2[0][1] = 4;
array2[1][1] = 5;
// show the memory is initialized
for(int r = 0; r < ROW; r++)
{
for(int c = 0; c < COL; c++)
cout << array2[r][c] << " ";
cout << endl;
}
//process_2d_array_pointer(array2);
//process_pointer_2_pointer(array2,2,2);
int info;
cout << abi::__cxa_demangle(typeid(array1).name(),0,0,&info) << endl;
cout << abi::__cxa_demangle(typeid(array2).name(),0,0,&info) << endl;
return 0;
}
The feature that you are using in C11 was introduced in C99, and was specifically designed to allow efficient and easy handling of multidimensional arrays.
While C++ shares the basic syntax with C when it comes to (multidimensional) arrays, array types are significantly less powerfull in C++: In C++ the sizes of array types are required to be compile time constants. Here are a few examples:
void foo(int a, int b) {
int foo[2][3]; //legal C++, 2 and 3 are constant
int bar[a][3]; //Not C++, proposed for C++17: first dimension of an array may be variable
int baz[a][b]; //Not C++, legal in C99
int (*fooPtr)[2][3]; //legal C++
int (*barPtr)[a][3]; //Not C++, legal in C99
int (*bazPtr)[a][b]; //Not C++, legal in C99
typedef int (*fooType)[2][3]; //legal C++
typedef int (*barType)[a][3]; //Not C++, legal in C99
typedef int (*bazType)[a][b]; //Not C++, legal in C99
int (*dynamicFoo)[3] = new int[2][3]; //legal C++
int (*dynamicBar)[3] = new int[a][3]; //legal C++
int (*dynamicBar)[b] = new int[a][b]; //Not C++
}
As you see, almost everything that's possible in C with dynamic sized arrays is not possible in C++. Even the VLA extension that's proposed for the next C++ standard does not help much: it's restricted to the first dimension of an array.
In C++, you have to use std::vector<> to achieve what you can achieve with C99 variable length arrays. With all the consequences:
The data in an std::vector<std::vector<> > is not consecutive in memory. Your caches might not like this.
There is no guarantee with an std::vector<std::vector<> > that all line arrays have the same length. This can be useful, or a pain, depending on your use case.
If you have an iterator to an element in an std::vector<std::vector<> >, you can't advance it to the corresponding element in the next line.
C++ does not have VLA. It is proposed for C++17 but there's a lot of work to do yet because it is quite a big change to the type system, and using C-style arrays is discourated in C++ anyway.
As you have found, you can use templates when the size is known at compile-time. If the size is not known at compile-time then your best bet is to use a single-dimensional vector wrapped up in a class for accessing it in the way you want to access it.
The vector of vectors is also possible of course; that describes a jagged array. Whether you prefer that over the single large memory block depends on various things (complexity of coding, runtime speed / memory usage considerations etc).
I have made this code to store the position of each bit 1 entered in a binary sequence. The output of the program is not what it is desired. The output I get for 10100 is 0x7fff9109be00. Here is the code:
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
bitset <5> inpSeq;
int x = 0;
int xorArray[x];
unsigned int i;
cout << "Enter a 5-bit sequence: \n";
cin >> inpSeq;
for ( i = 0; i < inpSeq.size(); i++)
{
if ( inpSeq[i] == 1 )
{
x = x+1;
xorArray[x] = i;
}
}
cout << xorArray << "\n";
}
Update for clarity: What I had in mind was that 'cout << xorArray' will print bit 1's positions.
cout << xorArray << "\n";
This does not print the elements of xorArray; it prints its address.
You must iterate ("loop over") it:
for (auto x : xorArray)
cout << x << ' ';
cout << '\n';
Your other problem is that you're trying to use a variable-length array, which does not exist in C++. Use a vector instead.
Now it gives you your desired output:
#include <iostream>
#include <bitset>
#include <vector>
using namespace std;
int main()
{
bitset<5> inpSeq("10111");
std::vector<int> xorArray;
for (unsigned int i = 0; i < inpSeq.size(); i++) {
if (inpSeq[i] == 1)
xorArray.push_back(i);
}
for (auto x : xorArray)
cout << x << ' ';
cout << '\n';
}
If you're not using C++11 for whatever reason, you can perform that final loop the traditional way:
for (std::vector<int>::const_iterator it = xorArray.begin(),
end = xorArray.end(),
it != end; ++it) {
cout << *it << ' ';
}
Or the naive way:
for (unsigned int i = 0; i < xorArray.size(); i++)
cout << xorArray[i] << ' ';
I am a little unclear on exactly what you are trying to achieve, but I think the following might help.
#include <iostream>
#include <bitset>
#include <list>
using namespace std;
int main() {
bitset<5> inpSeq;
unsigned int i;
list<int> xorList;
cout << "Enter a 5-bit sequence: \n";
cin >> inpSeq;
for (i = 0; i < inpSeq.size(); ++i) {
if (inpSeq[i] == 1) {
xorList.push_back(i);
}
}
for (list<int>::iterator list_iter = xorList.begin();
list_iter != xorList.end(); list_iter++)
{
cout << *list_iter << endl;
}
return 0;
}
The reason why I am using a list is because you mentioned wanting to store the positions of the 1 bit. The list is being used as the container for those positions, in case you need them in another point in the program.
One of the problems with the original code was that you assigned variable 'x' the value 0. When you declared xorArray[x], that meant you were essentially creating an array of length 0. This is incorrect syntax. It looks like you actually were trying to dynamically allocate the size of the array at runtime. That requires a different syntax and usage of pointers. The list allows you to grow the data structure for each 1 bit that you encounter.
Also, you cannot print an array's values by using
cout << xorArray << endl
That will print the memory address of the first element in the array, so, xorArray[0]. Whenever you want to print the values of a data structure such as a list or array, you need to iterate across the structure and print the values one by one. That is the purpose of the second for() loop in the above code.
Lastly, the values stored are in accordance with the 0 index. If you want positions that start with 1, you'll have to use
xorList.push_back(i+1);
Hope this helps!
Here is what I have to do!
Write a program to perform the following steps.
Allocate memory dynamically to store an array of 10 ints.
Assign each int a random value between 1 and 100.
Copy each of the 10 random ints to a vector of ints.
Print the dynamically allocated array of ints and the vector of ints, each with a width of 5, as shown in the sample output below.
I have trouble with the last point. My code is working perfectly, but I don't know how to set width in vector of ints so it is the same as array of ints.
#include<iostream>
#include<iomanip>
#include<cstdlib>
#include <vector>
#include <algorithm>
#include <iterator>
#include <stdexcept>
using namespace std;
int main(){
const int SIZE = 10;
int *arr = new int[SIZE];
//assign rand numbers between 0 and 100
for (int i = 0; i < SIZE; ++i){
*(arr + i) = rand() % 100+1;
}
//print array
for (int i = 0; i < SIZE; ++i){
cout << setw(5) << *(arr +i) << " ";
}
std::vector<int> integers (arr, arr + 10);
std::ostream_iterator<int> output(cout, " ");
cout << endl;
cout << "Vector integers contain: " << endl;
std::copy(integers.begin(), integers.end(), output);
return 0;
}
Your code works fine as is. cout << setw(5); sets the width just fine. You could also use cout.width(5);.
If you really want to do this with an ostream_iterator, the cleanest way is probably with a small proxy class:
class integer {
int i;
public:
integer(int i) : i(i) {}
friend std::ostream &operator<<(std::ostream &os, integer i) {
return os << std::setw(5) < i.i;
}
};
Then to write them out, use that type as the template parameter to the ostream_iterator:
std::copy(integers.begin(), integers.end(),
std::ostream_iterator<integer>(std::cout, ' '));
This will create a temporary integer object, then write it out using the operator<< for integer, which sets the width. At least in theory, this probably imposes some overhead, but I'd expect (at least with optimization enabled) most compilers will probably see through the subterfuge (so to speak) and eliminate any extra copies and such.
Of course, if the width isn't cast in concrete, you could make integer a template, and supply the width as a template parameter:
template <int N>
class integer {
// ...
return os << std::setw(N) < i.i;
Unless I really needed to use an ostream_iterator, I think I'd use a range-based for loop though:
for (int i : integers)
std::cout << std::setw(5) << i << ' ';
Since the width of a stream is reset to 0 everytime it is used, you can't use a std::ostream_iterator<int> (well, you could by using a custom std::num_get<char> facet which restores the width but that seems a bit radical).
You can print the std::vector<int> like this, however:
std::for_each(integers.begin(), integers.end(),
[](int v){ std::cout << std::setw(5) << v << ' '; });