I've read about 2d dynamic arrays but I obviously haven't quite got my head around it as this program doesn't work. The program seems to lie in displaying the array.
The input file is a text file with V and E on the first line with a 'tab indent' between them. The input vertices are on the next lines again tab indented with a new set on each line. On DevCpp it says there is a segmentation fault. Any help would be very much appreciated. thanks.
#include <iostream>
#include <fstream>
using namespace std;
#define maxV 100
#define unseen 0
typedef int Vertex;
class Graph {
private:
int V, E;
int**adj;
public:
Graph(char filename[]);
void display();
};
// constructor ask you for file name
Graph::Graph(char fname[]) {
Vertex u,v;
int j;
ifstream f;
f.open(fname, ios::in);
if(!f) {
cout << "\nError: Cannot open file\n";
return;
}
//Input number of vertices and edges
f >> V >> E;
int** adj = new int*[V];
for (int i=0;i<=V;i++)
{
adj[i]= new int[V];
}
for(int x=0;x<=V; ++x) // initially 0 array
{
for (int y=0;y<=V;++y)
adj[x][y] = 0;
}
// Set diagonal to 1
for(int z=0; z<=V; ++z)
adj[z][z]=1;
for (j =0;j<=E;++j)
{
f>>u>>v;
adj[u][v] = 1;
adj[v][u] = 1;
}
}
// This method displays the adjacency lists representation.
void Graph::display(){
int a,b,c;
for (a=0;a<=V;++a)
{
cout << a << " ";
}
cout << endl;
for (b=0;b<=V;++b)
{
cout << b << "| ";
for (c=0;c<=V;++c)
{
cout<<adj[b][c]<<"| ";
}
cout<<endl;
}
}
int main()
{
char fname[20];
cout << "\nInput name of file with graph definition: ";
cin >> fname;
Graph g(fname);
g.display();
}
//Input number of vertices and edges
f >> V >> E;
// You're hiding your member variable in the following line, leading to an incorrect initialization
// int** adj = new int*[V];
adj = new int*[V];
for (int i=0;i<=V;i++)
{
adj[i]= new int[V];
}
I see two significant problems just in the code that initializes the data array. First, a loop like this
for (int i=0;i<=V;i++)
loops over one more element than actually exists in the array. The correct form of a loop if the array is V elements long is
for (int i=0;i<V;i++)
That's "less than" rather than "less than or equal".
Secondly, you allocate both the array of pointers to be V pointers long, and than the individual columns to be V elements long as well; but later you use the same array and expect it to be V x E in size. Altogether, then, I think the allocation code ought to be
int** adj = new int*[V];
for (int i=0;i<V;i++)
{
adj[i]= new int[E];
}
There are likely to be other errors elsewhere, but at least I've got you started.
I don't know which line is causing the segmentation fault but here are some things to look at:
for (j =0;j<=E;++j)
{
f>>u>>v;
adj[u][v] = 1;
adj[v][u] = 1;
}
Are u and v guaranteed to be less than V? If not you could be writing outside the bounds of the matrix.
What happens when j == E? You are trying to read a line past the last line in the file. You should be checking instead for j < E. A better way still would be to ignore E all together and just do this:
while(f >> u >> v)
{
adj[u][v] = 1;
adj[v][u] = 1;
}
More likely though the segmentation fault is here:
for (b=0;b<=V;++b)
{
cout<<(b+1)<<"| ";
for (c=0;c<=V;++c)
{
cout<<adj[b][c]<<"| ";
}
cout<<endl;
}
the for loop conditionals should be checking b < V and c < V not <=. when either b or c == V you are definitely reading outside the matrix.
Related
This question already has answers here:
Segmentation Fault (SIGSEGV) when getting data as input in the vector of struct
(2 answers)
Closed 2 years ago.
Getting SIGESV error in following cpp code, kindly check.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
int sa = 0, sb = 0, c = 0;
cin >> n >> m;
vector<int> a;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<int> b;
for (int i = 0; i < m; i++) {
cin >> b[i];
}
int k = min(n, m);
while (k--) {
sa = accumulate(a.begin(), a.end(), 0);
sb = accumulate(b.begin(), b.end(), 0);
if (sb >= sa) {
swap(*min_element(a.begin(), a.end()),
*max_element(b.begin(), b.end()));
c++;
} else {
break;
}
}
if (sb >= sa) {
cout << "-1" << endl;
} else {
cout << c << endl;
}
}
return 0;
}
The code asks for two arrays and swaps only if array a has a summation less than array b.
Getting error as SIGESV, also can take 'b' array as an input, what to do?
When you're doing cin >> a[i], a is still empty, so attempting to access its i-th element produces a segfault. Resize it before with a.resize(n) or initialise it with the proper size: vector<int> a(n);
The size and capacity of vector a is 0 and never changes.
This code is broken:
vector<int> a;
for(int i=0;i<n;i++){
cin>>a[i];
}
operator[]() does not grow the vector. You are assigning values to memory that does not belong to a.
You want a.push_back(i) at a minimum. What you probably really want is:
vector<int> a;
a.reserve(n);
for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp;
a.push_back(tmp);
}
Reserving memory stops the vector from re-allocating. Not doing it in a constructor also stops default initialization of all elements.
The same goes for the b vector.
You also never change the values of sa or sb, but that shouldn't crash anything, it's just a logic error from what I can see.
The file as a whole is also rife with bad practices. "Competitive" coding sites actively make you a worse programmer.
When you know size you need while declaring vector you should declare vector like this
vector<int>arr(n);
vector<int>arr2(m);
this will create an vector of size n will value being zero at all indexes in vector at initialization.
Don't use <bits/stdc++.h> and trying coming up for better name for variables it will really help you as well as us. I know this is compeitive programming question but still.
I wrote the following C++ program to implement breadth first search to solve this problem of finding shortest path for all the nodes from the source.
#include<iostream>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;
int main()
{
int test;
cin >> test;
while(test--)
{
int m,n,source;
cin >> n >> m;
bool visited[n+1];
int dist[1001];
queue<int> q;
memset(dist, -1, sizeof(dist));
vector<int> adj[1001];
for(int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
cin >> source;
dist[source] = 0;
visited[source] = true;
q.push(source);
while(q.size())
{
int v = q.front();
q.pop();
for(int i : adj[v])
{
if(!visited[i])
{
q.push(i);
dist[i] = dist[v] + 6;
visited[i] = true;
}
}
}
for(int i = 1; i <= n; i++)
{
if(i != source)
{
cout << dist[i] << " ";
}
}
cout << "\n";
}
}
It works well if the value of test is 1, but when the value is 2 or more, some values of the boolean array "visited" become 1 in the second and later iterations. I do not understand why and how it happens as I declare the boolean array in every iteration and the default value for its elements is 0. Can somebody please explain this.
I declare the boolean array in every iteration and the default value for its elements is 0.
No, it's not 0. There are no default values for C++ simple types. My bet is you propably get some random values, as your array isn't initialised automatically.
You aren't initialising the array, and local arrays are not zero initialised, so explicit initialisation is needed.
I'm creating this very simple C++ program.
the program asks the user to enter a few integers and stores them in an array.but when a specific integer(for example 50)is entered,the input is ended and then,all of the integers are displayed on the screen except for 50.
for example:
input:
1
2
88
50
output:
1
2
88
the error i'm getting is when i use cout to print the array,all of numbers are shown,including 50 and numbers i did'nt even entered.
this is my code so far:
#include<iostream>
int main() {
int num[100];
for(int i=0;i<=100;i++) {
cin >> num[i];
if (num[i]!=50) break;
}
for(int j=0;j<=100;j++) {
cout << num[j] << endl;
}
return 0;
}
Change the program the following way
#include<iostream>
int main()
{
const size_t N = 100;
int num[N];
size_t n = 0;
int value;
while ( n < N && std::cin >> value && value != 50 ) num[n++] = value;
for ( size_t i = 0; i < n; i++ ) std::cout << num[i] << std::endl;
return 0;
}
Here in the first loop variable n is used to count the actual number of entered values. And then this variable is used as the upper bound for the second loop.
As for your program then the valid range of indices for the first loop is 0-99 and you have to output only whose elements of the array that were inputed.
A do while loop is more suitable for your problem. The stop condition will check if the number fit inside the array (if k is not bigger than 100) and if number entered is 50.
#include<iostream>
using namespace std;
int main() {
int num[100];
int k = 0;
// A do while loop will be more suitable
do{
cin >> num[k++];
}while(k<100&&num[k-1]!=50);
for (int j = 0; j < k-1; j++) {
cout << num[j] << endl;
}
return 0;
}
Also, a better solution to get rid of 100 limitation is to use std::vector data structure that automatically adjust it's size, like this:
vector<int> num;
int temp;
do {
cin >> temp;
num.push_back(temp);
} while (temp != 50);
Note, you can use temp.size() to get the number of items stored.
You read up to 101 numbers, but if you enter 50 you break the loop and go for printing it. In the printing loop you go through all 101 numbers, but you actually may have not set all of them.
In the first loop count in a count variable the numbers you read until you meet 50 and in the printing loop just iterate count-1 times.
You have allocated an array of 100 integers on the stack. The values are not initialized to zero by default, so you end up having whatever was on the stack previously appear in your array.
You have also off-by-one in both of your loops, you allocated array of 100 integers so that means index range of 0-99.
As the question is tagged as C++, I would suggest that you leave the C-style array and instead use a std::vector to store the values. This makes it more flexible as you don't have to specify a fixed size (or manage memory) and you don't end up with uninitialized values.
Little example code (requires C++11 compiler):
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers; // Store the numbers here
for(int i = 0; i < 100; ++i) // Ask a number 100 times
{
int n;
std::cin >> n;
if( n == 50 ) // Stop if user enters 50
break;
numbers.push_back(n); // Add the number to the numbers vector
}
for (auto n : numbers) // Print all the values in the numbers vector
std::cout << n << std::endl;
return 0;
}
There are just 2 changes in your code check it out :
int main()
{
int num[100],i; //initialize i outside scope to count number of inputs
for(i=0;i<100;i++) {
cin >> num[i];
if (num[i]==50) break; //break if the entered number is 50
}
for(int j=0;j<=i-1;j++)
{
cout << num[j] << endl;
}
return 0;
}
Okay, others already pointed out the two mistakes. You should use i < 100 in the loop conditions instead of i <= 100 and you have to keep track of how many elements you entered.
Now let me add an answer how I think it would be better.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; // a temp variable in the for loop.
numbers.size() < 100 && // check that we have less than 100 elements.
std::cin >> temp && // read in the temp variable,
// and check if the read was a success.
temp != 50) // lastly check that the value we read isn't 50.
{
numbers.push_back(temp); // Now we just add it to the vector.
}
for (int i = 0; i < numbers.size(); ++i)
std::cout << numbers[i]; // Now we just print all the elements of
// the vector. We only added correct items.
}
The above code doesn't even read anymore numbers after it found 50. And if you want to be able to enter any number of elements you just have to remove the check that we have less than 100 elements.
Now I commented the above code a bit much, if you compress it it'll reduce to just:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; numbers.size() < 100 && std::cin >> temp && temp != 50)
numbers.push_back(temp);
for (int i = 0; i < numbers.size(); ++i)
std::cout << numbers[i];
}
If you can use the C++11 standard it reduces to:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; numbers.size() < 100 && std::cin >> temp && temp != 50)
numbers.push_back(temp);
for (int element : numbers)
std::cout << element;
}
for (auto element : numbers) is new, it basically means for every int 'element' in 'numbers'.
So I wanted to clean the rust off my C++ skills and thought I'd start with something fairly simple. An equilibrium point in a vector A of size N is a point K, such that: A[0] + A[1] + ... + A[K−1] = A[K+1] + ... + A[N−2] + A[N−1]. The rationale behind the function algorithm is simple: Check each consecutive element of the vector and compare the sum of the elements before said element with the sum of the elements after it and if they are equal, output the index of that element. While it sounds simple (and I imagine that it is) it turned out to be harder to implement in reality. Here's what the code looks like:
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
void EquilibriumPoint(std::vector<int> &A);
void VectorPrint(std::vector<int> &V);
void main()
{
int input;
std::vector<int> Vect1;
cout << "Input the vector elements" << endl;
while (cin >> input)
Vect1.push_back(input);
VectorPrint(Vect1);
EquilibriumPoint(Vect1);
}
void EquilibriumPoint(std::vector<int> &A)
{
for (int it = 0; it != A.size(); ++it)
{
int lowersum = 0;
int uppersum = 0;
for (int beg = 0; beg != it; ++beg) lowersum += A[beg];
for (int end = it + 1; end != A.size(); ++end) uppersum += A[end];
if (uppersum == lowersum) cout << it;
}
}
void VectorPrint(std::vector<int> &V)
{
for (int i = 0; i != V.size(); ++i)
cout << V[i] << endl;
}
As you can see I threw in a print function also for good measure. The problem is that the program doesn't seem to execute the EquilibriumPoint function. There must be a problem with the logic of the implementation but I can't find it. Do you guys have any suggestions?
cin >> input
always returns true for you - so IMHO you have an endless loop. You need to stop collecting elements at some point, for instance
int input = 1
while (input)
{
cin >> input;
Vect1.push_back(input);
}
Will accept all elements that are not zero, when zero arrives, it will end the vector and run your function.
Or you can first input the number of elements (if you want to include zeros), example:
int count;
cin >> count
for (int i = 0; i < count; ++i)
{
cin >> input;
Vect1.push_back(input);
}
I didn't check the rest of the code, though. One problem at a time.
I am trying to read the unknown contents of a text file into a 2D array and have it come out looking like:
M [0] [0]=2 M [0] [1]=1 M [0] [2]=0
M [1] [0]=0 M [1] [1]=1 M [1] [2]=3
M [2] [0]=8 M [2] [1]=9 M [2] [2]=1
M [3] [0]=3 M [3] [1]=5 M [3] [2]=2
when the text file looks like this:
2
1 0
0 1
3
8 9 1
3 5 2
-2 3 -1
0
The zero at the end shows the end of the file.
My problem is the array can be a max size of 10X10 so there is no way of knowing what the size of the 2D array is and how to get it to look like i have shown above.
Any ideas?
Just use 'fstream'. It ignores new lines and works just like 'iostream'. You just need to keep track of your matrix row and column.
//open "myFileName.txt" with an input file stream
std::ifstream inputFile("myFileName.txt");
while(!inputFile.eof()) //Check for end-of-file character
{
//do this while keeping track of your matrix position
inputFile >> M [curRow] [curColumn]
}
inputFile.close();
And don't forget to include the library:
#include <fstream>
Edit: The >> operator will also attempt to auto-cast the input as whatever type you are using:
double dTemp;
int iTemp;
std::string sTemp;
std::ifstream in("myFile.txt");
in >> dTemp; //input cast as double
in >> iTemp; //input cast as integer
in >> sTemp; //input cast as string
in.close();
Edit: Get the number of elements of the file
int temp, numberOfInputs;
while(!inputFile.eof())
{
inputFile >> temp;
++numberOfInputs;
}
inputFile.seekg(0, std::ios::beg); //Go to beginning of file
Once you have the number of inputs you can use that to figure out the number of rows and colums.
For some dimensions N x M
char c;
int x;
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
c = fgetc(file);
if(c == ' ') continue;
if(c == EOF) return;
if(c == '-')
{
c = fgetc(file);
x = -1 * ((int)c);
} else {
x = c;
}
if(x == 0)
{
array[i][j] = x;
} else {
return;
}
}
}
But if you're talking about "what's the size of the matrix required to store these" then you're going to need a way to figure out what dimensions you want.
Try:
#include <vector>
#include <fstream>
#include <iostream>
int main()
{
std::ifstream file("plop.dat");
if(!file)
{
std::cerr << "Failed to open File\n";
return 1;
}
// Keep looping until we are done.
while(true)
{
int size;
file >> size;
// You said a size zero indicates termination.
if (size == 0)
{ break;
}
// Create a square 2D vector (Vector inside a Vector)
std::vector<std::vector<int> > matrix(size, std::vector<int>(size, 0));
// Loop over each axis
for(int x = 0;x < size; ++x)
{
for(int y = 0;y < size; ++y)
{
// Read one number for each location.
// The operator >> automatically skips white space
// White Space includes newline and tab. So it should work
// perfectly if the input is OK. But it is hard to detect
// an error in the format of the file.
file >> matrix[x][y];
}
}
}
}
~
So all row of the array have 3 values?
Simply read the values into the array keeping a count of which column you are in and ignore the newlines?
Look at getline
getline and stringstream to read, vector< vector<int> > to store.
Edit: Oh, so the size is always N*N? Then just read using while(cin>>x) { if (cin.good()) ...; } into a vector<int>, check the total size, and split into vector< vector<int> >
Single and multi-dimensional C arrays are just contiguous pieces of memory. The difference is more syntactical in terms of what indexing into the array does: for a 2-dimensional array it just multiplies one dimension by the size of the other dimension before adding the second dimension to find the offset.
So to solve:
read the values into a std::vector (other answers have sugegsted ways to do this)
work out the size (integer square root of myArray.size())
calculate the index as, e.g.:
int idx(int size, int d1, int d2)
{
return (d1*size)+d2;
}
Return the vector element at the index e.g.:
for (int d1 = 0; d1 < size; d1++)
{
for (int d2 = 0; d2 < size; d2++)
std::cout << "M [" << d1 << "] [" << d2 << "]=" << myArray[idx(size, d1, d2)] << " ";
std::cout << std::endl;
}
gives me:
$ g++ arr.cpp && ./a.out
M[0][0]=2 M[0][1]=1 M[0][2]=0
M[1][0]=0 M[1][1]=1 M[1][2]=3
M[2][0]=8 M[2][1]=9 M[2][2]=1