Segmentation fault while declaring vector string array C++ - 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

Related

Why is there a segmentation fault when I use vector storing vector?

I'm dealing with an algorithm homework which need to be executable on linux(I'm using wsl), and this homework need to store the solution and export to the output file.
To store the solution, I need to open an 2D array of "vectors storing pairs", and at the end, I need to sort the pairs by its first component in the ascending order.
I know that for the first requirement, the running time would be O(N^2)(This is also the standard answer for this dynamic programming problem), and for the second one, I've google C++ STL, and it says that the algorithm used by c++ only needs O(NlogN).
(1)It return 'killed' if I use the new to declare 2D array of vector, for the cases that N=10000, but it works fine if N=1000.
[Edited]
(2) I check the comment, and they suggest that I should write the code using vector to store vector instead of new. However, when I change to using vectors storing vectors, now the program cannot run, keep throwing segmentation fault.
I don't know where is happening. Can anybody help?
problem description:
https://drive.google.com/file/d/1m8ISIGlVGXH3oeyechLbBA1QQVSmsw-q/view?usp=sharing
file: https://drive.google.com/file/d/1Ci8MXUsX65oVOxKCD1u3YcWiXsKNYToc/view?usp=sharing
Note:
The .o files are alredy make, finish editing, you need to 'make', and run
./bin/mps [inputfile] [outputfile]
I've modified some code, but it can only run with case N=12, 1000; not for larger N.
chord.h:
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
class Chord {
public:
Chord(int);
~Chord();
void setEndPoint(int, int);
int getMaximumChords();
void print();
int size;
int* data; //stores the endpoints of the chord
// vector<pair<int,int>>** sol;
//I recently use this(1), works for N=1000, but killed if N larger
vector< vector< vector<pair<int, int>> >>sol;
//suggest to change to this(2), not working even for N=12,
//return segmentation fault
int getEndPoint(int);
};
chord.cpp:
#include "chord.h"
#include <iostream>
Chord::Chord(int tmp){ //initialize all elements 0
size = tmp;
data = new int [size];
};
Chord::~Chord(){
delete[] data;
}
void Chord::setEndPoint(int a, int b){
data[a] = b;
data[b] = a;
return;
}
void Chord::print(){
for(int i=0;i<size; i++){
cout << data[i] << endl;
}
return;
}
int Chord::getEndPoint(int a){
return data[a];
}
int Chord::getMaximumChords(){
for(int j=1; j<size; j++){
for(int i=j-1; i>=0; i--){
int k = getEndPoint(j);
if(k==i){ //case 1: ij is the chord
sol[i][j] = sol[i+1][j-1]; //make a copy
sol[i][j].reserve(1);
sol[i][j].push_back(make_pair(i,j));
}else if(k<i || k>j){ //case 2: k outside interval[i,j]
sol[i][j] = sol[i][j-1];
}else{ //case 3: k inside interval[i,j]
if (sol[i][j-1].size() > sol[i][k-1].size() + sol[k+1][j-1].size() + 1){
sol[i][j] = sol[i][j-1];
}else{
sol[i][j] = sol[i][k-1];
sol[i][j].reserve(sol[k+1][j-1].size()+1);
sol[i][j].push_back(make_pair(k,j));
sol[i][j].insert(sol[i][j].end(),sol[k+1][j-1].begin(), sol[k+1][j-1].end());
}
}
}
}
sort(sol[0][size-1].begin(), sol[0][size-1].end());
return sol[0][size-1].size();
}
main.cpp
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include "chord.h"
using namespace std;
int main(int argc, char* argv[]){
if (argc < 3){
printf("Please enter output file name!");
return 0;
}
//import input
fstream fi(argv[1]);
fstream fo;
fo.open(argv[2], ios::out);
int N=0, a=0, b=0;
char buffer[200];
fi >> N;
Chord chord(N);
while(fi>> a >>b){
chord.setEndPoint(a,b);
}
//chord.print();
int ans= chord.getMaximumChords();
//export output
fo << ans <<endl;
for(int i=0; i<chord.sol[0][chord.size-1].size(); i++){
fo << chord.sol[0][chord.size-1][i].first << " " << chord.sol[0][chord.size-1][i].second << endl;
}
fi.close();
fo.close();
return 0;
}
By default, std::vector is constructed with 0 size, and I see that you don't ever resize the vector, but you access its elements by index [i][j]. You have to resize first two (or maybe three) dimensions of 3-dimensional vector sol to fit necessary size, do following resize inside constructor:
Chord::Chord(int tmp){ //initialize all elements 0
size = tmp;
data = new int [size];
sol.resize(size, vector< vector<pair<int, int>> >(size));
};
After this resize change in constructor your program doesn't crash on 10000 input, at least on my Windows laptop.
Also maybe you need to resize two dimensions to bigger than size, you should know better. Also 3rd dimension might be needed to resize too, if you need this by algorithm, up to you. If you need to resize 3rd dimension, then do following (but if I understand your algorithm correctly you don't need this change, resizing 3rd dimension, you need it to be of size 0):
sol.resize(size1, vector< vector<pair<int, int>> >(size2, vector<pair<int, int>>(size3)));
(here size1/size2/size3 are three sizes of three dimensions, so that your vector gets 3-dimensional shape (size1, size2, size3), decide what these 3 sizes should be at your algorithm start, I think they should be (size, size, 0))

How can I eliminate garbage value in this output?

In this below program, I'm trying to marge 2 arrays into a single vector, but while returning the function I'm getting additional garbage values along with it.
Please anyone suggest me how to remove those!
#include <bits/stdc++.h>
#include <vector>
#include <string>
using namespace std;
vector <int> merge(int a[],int b[]){
vector <int> marr1;
marr1.clear();
int i=0,j=0;
while(i+j <= ((*(&a+1)-a)+(*(&b+1)-b)))
{
if ((i<= *(&a+1)-a)){
marr1.push_back(a[i]);
i++;
}
else{
marr1.push_back(b[j]);
j++;
}
}
sort(marr1.begin(),marr1.end());
return marr1;
}
int main(){
//array imlementation
int arr1[] = {5,7,4,5},arr2[] = {8,3,7,1,9};
vector <int> ans;
ans.clear();
ans = merge(arr1,arr2);
for (auto i=ans.begin();i<ans.end();++i){
cout<<*i<<"\t";
}
}
output produced:
0 0 0 0 1 3 4 5 5 7 7 8 9 32614 32766 4207952 1400400592
You want something like this:
include <iostream>
#include <vector>
#include <algorithm> // <<<< dont use #include <bits/stdc++.h>,
// but include the standard headers
using namespace std;
vector <int> mergeandsort(int a[], int lengtha, int b[], int lengthb) { // <<<< pass the lengths of the arrays
vector <int> marr1; // <<<< and use meaningful names
// marr1.clear(); <<<< not needed
for (int i = 0; i < lengtha; i++)
{
marr1.push_back(a[i]);
}
for (int i = 0; i < lengthb; i++)
{
marr1.push_back(b[i]);
}
sort(marr1.begin(), marr1.end());
return marr1;
}
int main() {
int arr1[] = { 5,7,4,5 }, arr2[] = { 8,3,7,1,9 };
vector <int> ans;
// ans.clear(); <<<< not needed
ans = mergeandsort(arr1, 4, arr2, 5);
for (auto i = ans.begin(); i < ans.end(); ++i) {
cout << *i << "\t";
}
}
Look at the <<<< comments for explanations.
There is still room for improvement:
passing the hard coded lengths of the arrays in mergeandsort(arr1, 4, arr2, 5) is bad practice, if you add/remove element from the arrays, you need to change the lengths too.
you shouldn't use raw arrays in the first place but vectors like in vector<int> arr1[] = { 5,7,4,5 };, then you don't need to care about the sizes as a vectors knows it's own size. I leave this as an exercise for you.
Since you're not passing the length of the array, there is no way inside the merge function to know about their length. Your program seems to produce undefined behavior as can be seen here. If you execute this program again and again you'll notice that the output changes which is an indication of undefined behavior.
Secondly, you're using std::vector::clear when there is no need to use it in your program. I have commented it in the code example i have given below.
You can use pass the length of the arrays as arguments to the merge function. Below is the complete working example:
#include <bits/stdc++.h>
#include <vector>
#include <string>
using namespace std;
vector<int> merge(int a[], int lengthA, int b[], int lengthB){
vector <int> marr1;
//marr1.clear();//no need for this since the vector is empty at this point
for(int i = 0; i< lengthA; ++i)
{
//std::cout<<"adding: "<<a[i]<<std::endl;
marr1.push_back(a[i]);
}
for(int i = 0; i< lengthB; ++i)
{
//std::cout<<"adding: "<<b[i]<<std::endl;
marr1.push_back(b[i]);
}
sort(marr1.begin(),marr1.end());
return marr1;
}
int main(){
//array imlementation
int arr1[] = {5,7,4,5},arr2[] = {8,3,7,1,9};
vector <int> ans;
//ans.clear();//no need for this since the vector is empty at this point
ans = merge(arr1,4, arr2, 5);
for (auto i=ans.begin();i<ans.end();++i){
cout<<*i<<"\t";
}
}
You pass two int[] which degrade to pointers. This means you cannot tell the number of elements which you attempt to do with i+j <= ((*(&a+1)-a)+(*(&b+1)-b)). Either pass in a length of each array, or even better (C++) pass in two vectors instead. Also, if you don't know the STL has a merge() function in <algorithm>.

Printing an array in reverse

Task
You'll be given an array of N integers and you have to print the integers in the reverse order.
Constraints
1<=N<=1000
1<=A_i<=10000, where A_i is the ith integer in the array.
Input
4
1 2 3 4
Output
4 3 2 1
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int N, y; //declaring N as the length of array
cin >> N; //intakes the length as an input
if (N>=1 && N<=1000){ //checks whether the length satisfies the rules
int a[N]; // makes an array containing N elements
for (int x =1; x<N; x++){ //starts transcription on the array
cin>>y; //temporarily assigns the input on a variable
if (y>=1&&y<=10000){ //checks if the input meets rules
a[x]=y; //copies the variable on the array
}
}
for (int z = N; z>1; z--){ //runs a loop to print in reverse
cout<<a[z]<<endl;
}
}
return 0;
}
Problem
Obtained output is
-1249504352
3
2
Indicating an error in transcription.
Question
Can somebody please tell me where I am making a mistake? Secondly, is it possible to directly check whether an input is meeting requirement rather than temporarily declaring a variable for it?
Here is a solution in idiomatic c++11, using std::vector, which is a dynamically resizable container useful for applications like this.
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
int size;
std::cin >> size; // take in the length as an input
// check that the input satisfies the requirements,
// use the return code to indicate a problem
if (size < 1 || size > 1000) return 1;
std::vector<int> numbers; // initialise a vector to hold the 'array'
numbers.reserve(size); // reserve space for all the inputs
for (int i = 0; i < size; i++) {
int num;
std::cin >> num; // take in the next number as an input
if (num < 1 || num > 10000) return 1;
numbers.push_back(num);
}
std::reverse(numbers.begin(), numbers.end()); // reverse the vector
// print each number in the vector
for (auto &num : numbers) {
std::cout << num << "\n";
}
return 0;
}
A few things to note:
using namespace std is considered bad practice most of the time. Use (e.g.) std::cin instead for things which come from the std namespace.
numbers.reserve(size) is not necessary for correctness, but will make the program faster by reserving space in advance.
for ( auto &num : numbers ) uses a range-based for loop, available in c++11 and later versions.
You could make your for loop indices go from high to low:
for (int i = N-1; i > 0; --i)
{
std::cout << a[i] << "\n"; // Replace '\n' with space for horizontal printing.
}
std::cout << "\n";
This would apply with std::vector as well.
With std::vector, you can use a reverse iterator. There are other techniques available (as in other answers).

C++ console reading uncertain number of inputs and put them in an Array?

Assume the following numbers are inputed in VC++ Console(separate with a space). N maybe 10, 20 or 100, it is uncertain.
1 2 3 4 ... N [Enter]
The number of inputs is uncertain, maybe 10, or 20. After I press the Enter key, how put these numbers into an Array?
array[0]=1; array[1]=2; ...
How to implement that with C++ code?
(The number of inputs is uncertain!)
As PeterT pointed out, If you don't know the size of the array ahead of time, you'll have to use dynamic memory allocation. Luckily, the STL has a container that does it for you.
You can use std::vector for that job.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main() {
std::string nums; // the numbers in the format "1 2 3 4 10 -20"
std::getline(std::cin,nums);
std::stringstream stream(nums);
int n;
std::vector<int> vec;
while(stream >> n) {
vec.push_back(n);
}
return 0;
}
(code is based on Abdulla Al Sun's answer.)
This is an O(n) (linear complexity) solution.
If you want to convert it in to an actual array, you can do:
int array[vec.size()];
std::copy(vec.begin(), vec.end(), array);
Another approach is to figure out how many elements the user inputted by storing his input in a string, and counting the tokens.
Then you know how big of an array you need.
unsigned int getSize(std::string s) {
unsigned int size = 0;
std::stringstream ss(s);
int in;
while (ss >> in)
++size;
return size;
}
int main() {
std::string nums; // the numbers in the format "1 2 3 4 10 -20"
std::getline(std::cin,nums);
const unsigned int size = getSize(nums);
int array[size];
std::stringstream stream(nums);
int n;
for(unsigned int i = 0; stream >> n && i < size; ++i) {
array[i] = n;
}
return 0;
}
This is an O(2n) (linear complexity) solution.
My code assumes that the compiler allows variable array size. If it doesn't, use:
int* array = new int[size];
...
delete[] array;
To utilize RAII, wrap it in a struct like so:
struct DynArr {
int* data;
unsigned int size;
DynArr(const unsigned int size) :
size(size) {
data = new int[size];
}
~DynArr() {
delete[] data;
}
};
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
int array[1000]; // your heighest input range
vector<int> numbers;
int main() {
string nums; // the numbers in the format "1 2 3 4 10 -20"
getline(cin,nums);
stringstream stream(nums);
int i = 0;
int n;
while(stream >> n){
array[i++] = n;
numbers.push_back(n);
}
// The number of integers in array is i. You can do anything with this number.
// numbers contains the input numbers.
return 0;
}
I have added vector after getting PeterT's idea. You can add vector for not setting the static size of array.
Try this code. The header of stringstream is sstream. I have compiled in in codeblocks, I think this will work on VC++ compiler too.
I'm going to steal Abdulla's code and make a couple slight modifications.
#include <iostream>
#include <string>
#include <sstream>
#include <cstring.h> // for memcpy
//using namespace std; frowned on. polutes global namespace
//the highest input range is undefined, so this isn't safe
//int array[1000]; // your heighest input range
int main() {
int max=10;
int * array = new int[max];// allow resizing of array by dynamically allocating
std::string nums; // the numbers in the format "1 2 3 4 10 -20"
std::getline(std::cin,nums);
std::stringstream stream(nums);
int i = 0;
while(stream){
if (i==max)
{
int * temp = new int[max*2];// note statistical analysis has found
//1.5 is generally a better multiplier
memcpy(temp, array, max*sizeof(array[0]));
// note do not use memcpy for copying complex data. It is too stupid.
delete array; // release memory of old array
array = temp; // replace old array with new array
max*=2;
}
int n;
stream>>n;
array[i++] = n;
}
// The number of integers in array is i. You can do anything with this number.
delete array; // all done. clean up.
return 0;
}
The really smart way is to use a std::vector. Odds are really good that this is going to be frowned on by the marker, so make your own resizable array class. With a class you can easily take advantage of RAII and automate the clean-up so it's exception safe.

array concatenation of two different arrays

im doing simple genetic algorithm uniform crossover operation . for that im using two arrays as parent and mother.i want concatenate the childs for getting the offsprings(childs).
i have problem in adding the arrays .any help plssss.i did it ubuntu
#include<iostream>
#include <fstream>
#include <algorithm>
#include<vector>
using namespace std;
int main()
{
int P[ ]={3,7,6,5,2,4,1,8};
int N[ ]={8,6,7,2,5,3,4,1};
int r= (sizeof(P)/sizeof(*P)) ;
int s= (sizeof(N)/sizeof(*N));
int val=r/2 ;
int t1[val],t2[val],t3[val],t4[val],n=0,p=0;
for(int m=0;m< val;m++)
{
t1[n]=P[m];
t2[n]=N[m];
n++;
}
for(int x=val;x< r;x++)
{
t3[p]=P[x];
t4[p]=N[x];
n++;
}
int* child=new int [val+val];
copy(t1,t1+val,child);
copy(t3,t3+val,child+val);
cout << child;
}
return 0;
}
This part is wrong:
int t1[val], t2[val], t3[val], t4[val]
You can only use constant values to declare the size of arrays.
You can either use a std::vector or dynamically allocate memory for the t-arrays.
std::vector<int> t1(val);
std::vector<int> t2(val);
for(int m = 0; m < val; m++)
{
t1[n] = P[m];
t2[n] = N[m];
n++;
}
There seem to be multiple errors in your code.
Variable length arrays are at present not supported in C++.
int val=r/2 ;
int t1[val]; // Not OK
In the second for loop I guess you meant p++ instead of n++;
Instead of manually doing all the memory allocation - deallocation, you should use std::vectors
cout << child; // This outputs the address of the pointer, not the entire array.