How to calculate sin and cos off all vector elements? - c++

My code
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <sstream>
#include <cmath>
#define PI 3.14159265
int main(){
std::ifstream ifs("MFSO7.dat");
std::string line;
std::vector<float> column1;
std::vector<float> column2;
std::vector<float> column3;
std::vector<float> vkos;
std::vector<float> vsin;
while(std::getline(ifs, line)) // read one line from ifs
{
std::istringstream iss(line); // access line as a stream
float item1;
float item2;
float item3;
// Read the items from the line
iss >> item1 >> item2 >> item3;
// Add them to the columns.
column1.push_back(item1);
column2.push_back(item2);
column3.push_back(item3);
}
for(int i=0;i<38;i++)
{
vkos[i]=cos(column3[i]* PI/180.0 );
vsin[i]=sin(column3[i]* PI/180.0 );
}
std::cout << vkos[1] << std::endl;
}
Whem I execute the code I got
milenko#milenko-X58-USB3:~/Calibration Files$ ./a1
Segmentation fault (core dumped)
Why?May be I should avoid the loop or...?

A vector will have some capacity to hold new items. This is different from size, the count of elements that are actually in the vector. Thus a capacity of n that does not mean that it already has n items. A vector would have no items when it just got constructed by the default constructor -- the one with no arguments.
Referring to the ith element via vector::operator[] is incorrect when i >= n, where n is the size; in your case n is 0. So first you create them by vkos.push_back(cos(value)) instead of directly assigning to the index. On every push_back, the vector's size increases by one.
for(auto angle : column3)
{
vkos.push_back(cos(angle * PI/180.0));
vsin.push_back(sin(angle * PI/180.0));
}
if (vkos.size() >= 2)
cout << vkos[1] << '\n';

std::valarray is made for that, sin is overloaded with valarray:
vkos = cos(column3 * PI/180.0);
vsin = sin(column3 * PI/180.0);
No need for a loop, that would work.

If you insist on iterating with an index into a vector, you can use:
for (int i = 0; i < column3.size(); ++i) ...
This way, you will at least not try to access at an index that is larger than the current number or elements + 1.
Otherwise, you can try to initialize the vector to have exactly that many values:
std::vector<float> column3(38, 0);
Or if you are using C++11 you could even go for the
for (auto x : column3) ...

The problem is you are trying to assign to memory you don't have. Why don't you use std::transform? Using standard algorithms will help avoid these types of bugs, can often perform better than hand written loops, and most importantly is easier to read & understand. Also, avoid using #define, prefer constexpr.
constexpr double Pi {3.14159265};
constexpr auto PiDiv180 = Pi / 180;
std::transform(std::cbegin(column3), std::cend(column3), std::back_inserter(vkos),
[PiDiv180] (const auto v) { return std::cos(v * PiDiv180); });
std::transform(std::cbegin(column3), std::cend(column3), std::back_inserter(vsin),
[PiDiv180] (const auto v) { return std::sin(v * PiDiv180); });

It's because you're assigning to elements of vkos and vsin that haven't been constructed yet.
It's best to stick to the STL for these types of loop-based tasks, a lot of errors are taken care of for you. For this particular problem, you're looking for std::transform. The following code has zero overhead compared to your accepted solution:
std::vector<std::pair<float, float>> vkossin{};
std::transform(
std::begin(column3), std::end(column3), std::back_inserter(vkossin),
[](float degs) {
float rads = degs*PI/180.0;
return std::make_pair(cos(rads), sin(rads));
});
std::cout << vkossin[1].first << '\n';
std::back_inserter, std::pair, std::make_pair

Related

Append data to array in C++

double b[3] = {3,3,4};
for(int i=0;i<3;i++) {
cout<<b[i]<<" "<<endl;
}
int sum = 0;
for(int i=0;i<3;i++) {
sum += b[i];
} cout<<"\n"<<sum<<endl;
for(int i=0;i<3;i++) {
double norm_b = b[i]/sum;
cout<<norm_b<<endl;
}
Result:
0.3
0.3
0.4
How to insert data (norm_b) to array, like append in Python?
The size of an array never changes through its lifetime. As such, there is no way to insert (nor to remove) elements.
What can be done instead, is to allocate an array dynamically, and upon insertion, allocate a bigger array, copy the elements from the old one, which can then be deallocated - or at least that is the general idea; I've skipped implementation details. Such data structure is called a resizable array. The standard library has an implementation of the resizable array: std::vector.
Because you mention Python, then there are better library classes and algorithms that are closer to what you might be used from Python.
#include <vector>
#include <algorithm>
#include <numeric>
void main() {
std::vector<double> b{3, 3, 4}; // Init vector
// If compiler supports C++11 you can use range-for
for (auto value : b)
{
std::cout << value << " " << std::endl;
}
double sum = std::accumulate(b.begin(), b.end(), 0); // sum b, sum should be double, not int?
std::cout << "\n"
<< sum << std::endl;
std::vector<double> norm_b(b.size()); // initialize norm_b with b.size() elements
size_t idx = 0;
std::generate(norm_b.begin(), norm_b.end(), [&b, &idx, &sum]() {
return b[idx++] / sum;
});
// Again range-for if C++11
for (auto value : norm_b)
{
std::cout << value << " " << std::endl;
}
}
There are a number of things in this code that you should look up if you don't fully understand:
Various way to initiliaze a std::vector (initializer list - braced initialization, count constructor etc)
std::vector iterators
std::accumulate
std::generate
lambdas
range-for
iterators based for (not used in the code above)
You can "append" a value only to a data structure that can dynamically grow in size. A c-like array if fixed size. You can try to use a std::vectorwhich has a push_back method, equivalent to python append method.
note: Instead of C-like array, consider to use std::array which is part of c++ STL and let you use STL algorithm on it.
Thank you guys
Solved
Update:
#include <vector>
vector<double> vec;
for(int i=0;i<3;i++) {
vec.push_back(b[i]/sum);
cout<<vec[i]<<endl;
}
you can use vector for append data as more as you like.For use vector you have to include a header file name vector.Here the code below:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//declare a vector first
vector<double>v;
int sum = 0;
for(int i=0;i<3;i++)
{
sum += b[i];
}
for(int i=0;i<3;i++)
{
vec.push_back(b[i]/sum);
cout<<vec[i]<<" "<<endl;
}
return 0;
}

segmentation fault using nested vectors

I stumbled upon the following code segment somewhere to create a list of random numbers in a certain interval:
#include <vector>
#include <iostream>
#include <math.h>
struct gen_rand_pos{
double factor;
public:
gen_rand_pos(double r=1.0): factor(r/RAND_MAX)
{}
double operator()(){
return rand()*factor;
}
};
int main(){
int N = 5;
std::vector<double> result(N);
std::generate_n(std::back_inserter(result), N, gen_rand_pos(1.0));
std::cout << result[0] << std::endl;
}
It works perfectly fine. I tried to take this one step further and do the same, but this time creating a list(vector) of random unit vectors, uniformly distributed on the sphere. Here is my go at this:
double l2_norm(std::vector<double> const& u) {
double accum = 0.;
for (double x : u) {
accum += x * x;
}
return sqrt(accum);
}
struct gen_rand_vec{
double factor;
public:
gen_rand_vec(): factor(2.0/RAND_MAX)
{}
std::vector<double> operator()(){
std::vector<double> result = {rand()*factor-1,rand()*factor-1,rand()*factor-1}; // uniform in each component
double norm = l2_norm(result);
std::transform(result.begin(), result.end(), result.begin(),
std::bind1st(std::multiplies<float>(),1/norm)); // normalize the vector
return result;
}
};
However if I now try to construct it in the same manner:
int main(){
int N = 5;
std::vector<std::vector<double>> result2(N);
std::generate_n(std::back_inserter(result2), N, gen_rand_vec());
std::cout << result2[0][0] <<std::endl;
}
I get a segmentation error. Is the problem lying in the back_inserter or am I doing something completely wrong? I can't figure out. I checked the construction of the single vectors and they work just fine, so the mistake has to lie somewhere after that.
Thanks in advance.
Default size of inner vectors for result2 for indices <0,4> is 0, so you cannot access
result2[0][0] // inner vector doesn't keep any elements
when you call generate_n with back_inserter, you add new vectors to the end of result2. In this case you can access indices of inner vector for result2[>=5].
Your problem is quite simple, std::back_inserter is inserting new vectors at the end of result2. Hence, you cannot access the first element, since it is not initialized. To solve this, just remove the (N) from the initialization of result2. Example.

Segmentation fault while declaring vector string array C++

#include<iostream>
#include<string>
#include<stdio.h>
#include<stdlib.h>
//#include<set>
#include<list>
#include<cmath>
//#include<algorithm>
#include<fstream>
#include<vector>
#define max 10000.0
using namespace std;
int main()
{
int n;//number of rooms
cin>>n;
vector<string> room_name(n,"");
for(int i=0;i<n;i++)
{
string tmp;
cin >> tmp;
room_name.push_back(tmp);
}
}
The error Segmentation fault: 11 still occurs.
Unable to find the point of error. Any idea why this might be happening?
It is not enough to declare a vector: unlike an array, it could grow, so by default it starts with a fixed size of zero.
If you know the size of the vector upfront, you can request a vector of a specific size (you can grow it after that, too)
vector<string> room_name(n, ""); // You can supply a different default, or no default here
This makes a vector of 100 empty strings, letting you access elements 0..n-1 in the subsequent loop.
Alternatively, you could make your vector grow one element at a time by using push_back, like this:
for(int i=0;i<n;i++)
{
string tmp;
cin >> tmp;
room_name.push_back(tmp);
}
Unless the vector is already sized, you need to use push_back to append to the end of the vector.
std::vector<int> foo;
for (int i = 0; i < 10; ++i)
{
foo.push_back(i);
}
Otherwise you need to ensure that the vector is already sized, either
std::vector<int> foo(10);
Or
std::vector<int> foo;
foo.resize(10);
Then you could use indexing as you did
for (int i = 0; i < 10; ++i)
{
foo[i] = i;
}
If you try to write to each index before you sized your array, you are writing to memory out of bounds.
Are you going indeed to enter 1000 strings manually in the vector?:)
Also it is a good idea to define canstant names using letters of upper case. So instead of
#define max 10000.0
it would be better to write
#define MAX 10000.0
And it is not clear why max is defined as a float number instead of an integer.
Take into account that variable n was not declared in your program. So the program does not compile. Maybe you mean max instead of n.
As the vector is defined as an empty vector
vector<string> room_name;
that is it does not have elements then you may not use the subscript operator to enter values in the vector.
You could use method push_back instead the following way
vector<string> room_name;
room_name.reserve( n );
for ( int i = 0; i < n; i++ )
{
string s;
cin >> s;
room_name.push_back( s );
}
And instead of the loop you could use standard algorithm std::copy_n declared in header <algorithm>
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#define N 2
int main()
{
std::vector<std::string>room_name;
room_name.reserve( N );
std::copy_n( std::istream_iterator<std::string>( std::cin ), N,
std::back_inserter( room_name ) );
for ( const std::string &s : room_name ) std::cout << s << std::endl;
return 0;
}
If to enter strings
my_room
your_room
then the program will output them from the vector
my_room
your_room

Best way to split a vector into two smaller arrays?

What I'm trying to do:
I am trying to split a vector into two separate arrays. The current int vector contains an element per line in a text file. The text file is a list of random integers.
How I'm planning to do it:
My current idea is to create two regular int arrays, then iterate over the entire vector and copy n/2 elements to each of the arrays.
What I would like to know:
What is the most elegant way of accomplishing my task? I have a feeling that I can do this without iterating over the vector multiple times.
Code:
#include <vector>
#include <fstream>
#include <iterator>
#include <iostream>
using namespace std;
vector<int> ifstream_lines(ifstream& fs)
{
vector<int> out;
int temp;
while(fs >> temp)
{
out.push_back(temp);
}
return out;
}
vector<int> MergeSort(vector<int>& lines)
{
int split = lines.size() / 2;
int arrayA[split];
int arrayB[split];
}
int main(void)
{
ifstream fs("textfile.txt");
vector<int> lines;
lines = ifstream_lines(fs);
return 0;
}
Thank you :)
Use iterators.
std::vector<int> lines;
// fill
std::size_t const half_size = lines.size() / 2;
std::vector<int> split_lo(lines.begin(), lines.begin() + half_size);
std::vector<int> split_hi(lines.begin() + half_size, lines.end());
Since iterator ranges represent half open ranges [begin, end), you don't need to add 1 to the second begin iterator: lines.begin() + half_size isn't copied to the first vector.
Note that things like
int split = lines.size() / 2;
int arrayA[split];
int arrayB[split];
Are not standard C++ (and as such not portable). These are so-called variable-length arrays (VLAs for short) and are a C99 thing. Some compilers have them as an extension while compiling C++ code (GCC, Clang). Always compile with -pedantic to get a warning. These VLAs act funky for non-POD types and aren't generally useful, since you can't even return them.
If you can't use code from Xeo answer due to strict compiler rules or you want more generic way, try std::advance:
#include <vector>
#include <iterator>
size_t middle = input.size()/2;
std::vector<int>::const_iterator middleIter(input.cbegin());
std::advance(middleIter, middle);
std::vector<int> leftHalf(input.begin(), middleIter);
std::vector<int> rightHalf(middleIter, input.end());
If you only need a reference to the numbers without manipulating them, then you can do:
int *array_1 = &lines[0];
int *array_2 = &lines[lines.size() / 2];
array_1 and array_2 are, actually, pointers to the start and middle of the vector. This works since STL guarantees that vectors store their elements within a continuous memory.
Note that referring to lines.begin() can't be used for this.
Solution to split vector to variable count parts using iterator.
#include <iostream>
#include <vector>
int main()
{
// Original vector of data
std::vector<double> mainVec{1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0};
// Result vectors
std::vector<std::vector<double>> subVecs{};
// Start iterator
auto itr = mainVec.begin();
// Variable to control size of non divided elements
unsigned fullSize = mainVec.size();
// To regulate count of parts
unsigned partsCount = 4U;
for(unsigned i = 0; i < partsCount; ++i)
{
// Variable controls the size of a part
auto partSize = fullSize / (partsCount - i);
fullSize -= partSize;
//
subVecs.emplace_back(std::vector<double>{itr, itr+partSize});
itr += partSize;
}
// Print out result
for (const auto& elemOuter : subVecs)
{
std::cout << std::fixed;
for (const auto& elemInner : elemOuter)
{
std::cout << elemInner << " ";
}
std::cout << "\n";
}
}

C++ Program Apparently Printing Memory Address instead of Array

#include <iostream>
using namespace std;
int main(){
int findMax(int *);
const int MAX = 100;
int values[MAX];
char ivals[256];
// Get the space-separated values from user input.
cin.getline(ivals, 256, '0');
char *helper;
// Clean input array and transfer it to values.
for(int i = 0; i < (MAX) && ivals[i] != 0; i++){
helper = ivals[i * 2];
values[i] = atoi(helper);
}
int mval = findMax(values);
cout << values << endl << mval;
return 0;
}
//Function to find the maximum value in the array
int findMax(int arr[]){
int localmax = 0;
for(int i = 0; i < (sizeof(arr)/sizeof(int)); i++){
if(arr[i] > localmax){
localmax = arr[i];
}
}
return localmax;
}
The purpose of this program is for the user to input a space-separated series of values ended by a 0. That array is then to be analyzed to find the max. I figured out how to convert what is originally a char[] into an int[] so that I can use the findMax() function on it without error but the sorting loop seems to have a problem of its own and when "cout << values << endl << mval;" is called, it returns only a memory address instead of what should be a non-spaced sequence of ints. Can anybody explain what I am doing wrong? It seems that I may have made some mistake using the pointers but I cannot figure out what.
Printing values won't print the contents of the array as you expect, it will print the memory location of the first element of the array.
Try something like this instead:
#include <iterator>
#include <algorithm>
// ...
copy(&values[0], &values[MAX], ostream_iterator(cout, " "));
Sorry I can't post actual working code, but your original post is a mess with many syntax and syntactic errors.
EDIT: In the interest of being more complete and more approachable & understandable to beginners, I've written a small program that illustrates 4 ways to accomplish this.
Method 1 uses copy with an ostream_iterator as I've done above.
Method 2 below is probably the most basic & easiest to understand.
Method 3 is a C++0x method. I know the question is tagged C++, but I thought it might be educational to add this.
Method 4 is a C++ approach using a vector and for_each. I've implemented a functor that does the dumping.
Share & Enjoy
#include <iostream>
#include <iterator>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
struct dump_val : public unary_function<int,void>
{
void operator()(int val)
{
cout << val << " ";
}
};
int main(){
int vals[5] = {1,2,3,4,5};
// version 1, using std::copy and ostream_iterator
copy(&vals[0], &vals[5], ostream_iterator<int>(cout, " "));
cout << endl;
// version 2, using a simple hand-written loop
for( size_t i = 0; i < 5; ++i )
cout << vals[i] << " ";
cout << endl;
// version 3, using C++0x lambdas
for_each(&vals[0], &vals[5], [](int val)
{
cout << val << " ";
}
);
cout << endl;
// version 4, with elements in a vector and calling a functor from for_each
vector<int> vals_vec;
vals_vec.push_back(1);
vals_vec.push_back(2);
vals_vec.push_back(3);
vals_vec.push_back(4);
vals_vec.push_back(5);
for_each( vals_vec.begin(), vals_vec.end(), dump_val() );
cout << endl;
}
When you pass around an array of X it's really a pointer to an array of X that you're passing around. So when you pass values to cout it only has the pointer to print out.
You really should look into using some of the standard algorithms to make your life simpler.
For example to print all the elements in an array you can just write
std::copy(values, values+MAX, std::ostream_iterator<int>(std::cout, "\n"));
To find the max element you could just write
int mval = *std::max_element(values, values+MAX);
So your code becomes
#include <iostream>
using namespace std;
int main(){
const int MAX = 100;
int values[MAX];
char ivals[256];
// Get the space-separated values from user input.
cin.getline(ivals, 256, '0');
char *helper;
// Clean input array and transfer it to values.
for(int i = 0; i < (MAX) && ivals[i] != 0; i++){
helper = ivals[i * 2];
values[i] = atoi(helper);
}
copy(values, values+MAX, ostream_iterator<int>(cout, "\n"));
cout << *std::max_element(values, values+MAX);
return 0;
}
Doing this removes the need for your findMax method altogether.
I'd also re-write your code so that you use a vector instead of an array. This makes your code even shorter. And you can use stringstream to convert strings to numbers.
Something like this should work and is a lot less code than the original.
int main(){
vector<int> values;
char ivals[256];
// Get the space-separated values from user input.
cin.getline(ivals, 256, '0');
int temp = 0;
stringstream ss(ivals);
//read the next int out of the stream and put it in temp
while(ss >> temp) {
//add temp to the vector of ints
values.push_back(temp);
}
copy(values.begin(), values.end(), ostream_iterator<int>(cout, "\n"));
cout << *std::max_element(values.begin(), values.end());
return 0;
}
Array of int is promoted to a pointer to int when passed to a function. There is no operator << taking ordinary array. If you want to use operator << this way, you need to use std::vector instead.
Note: it is possible technically to distinguish array when passed to a function using template, but this is not implemented for standard operator <<.
for(int i = 0; i < (sizeof(arr)/sizeof(int)); i++){
sizeof(arr) here is the size of the pointer to the array. C++ will not pass the actual array, that would be grossly inefficient. You'd typically only get one pass through the loop. Declare your function like this:
int findMax(int* arr, size_t elements) {
//...
}
But, really, use a vector.
Oh, hang on, the question. Loop through the array and print each individual element.