Segmentation fault with multidimensional arrays - c++

I tried searching through this website for possible answers of why this error is occurring but couldn't find the exact answer.
For this little code, I basically have the program read input from a file. (It reads every single character.) Then store it in a multi-dimensional array (2D) and finally print out the array.
This is my code:
ifstream file;
char gamemap[20][26];
file.open("maze-hard.txt");
if(!file.is_open())
{
cout << "Error: Cannot open file" << endl;
return 0;
}
for(int i = 0; i < 20; i++)
{
for(int j = 0; j < 26; i++)
{
gamemap[i][j] = file.get();
cout << gamemap[i][j];
}
cout << endl;
}
It was somewhat successful, but I got a segmentation fault error. I don't know where the problem lies. Don't go hard on me for this one. I'm not all that advanced in C++.

for(int j = 0; j < 26; i++)
I'd replace that i++ with a j++.

increment j in the second cycle, not i ;)

While probably not strictly related to this particular segfault, I'd also check to make sure that the read is good for safety.
if(file.good())
{
gamemap[i][j] = file.get();
//etc etc
}

Related

2d array comparing with char

I have an array that reads data from a file, the data is binary digits such as 010011001001 and many others so the data are strings which I read in to my 2d array but I am stuck on comparing each value of the array to 0. Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string myArr[5000][12];
int i = 0, zeroCount = 0, oneCount = 0;
ifstream inFile;
inFile.open("Day3.txt");
while(!inFile.eof())
{
for(int i = 0; i < 5000; i++)
{
for(int j = 0; j < 12; j++)
{
inFile >> myArr[i][j];
j++;
}
i++;
}
}
for(int j = 0; j < 12; j++)
{
for(int i = 0; i < 5000; i++)
{
if(myArr[i][j].compare("0") == 0)
{
zeroCount++;
}
else
{
oneCount++;
}
i++;
}
if(zeroCount > oneCount)
{
cout << "Gamma is zero for column " << i << endl;
}
else
{
cout << "Gamma is One for column " << i << endl;
}
j++;
}
}
some input from the text file:
010110011101
101100111000
100100000011
111000010001
001100010011
010000111100
Thank you for editing you question and providing more information. Now, we can help you. You have 2 major misunderstandings.
How does a for loop work?
What is a std::string in C++
Let us start with the for loop. You find an explanation in the CPP reference here. Or, you could look also at the tutorial shown here.
The for loop has basically 3 parts: for (part1; part2; part3). All are optional, you can use them, but no need to use them.
part1 is the init-statement. Here you can declare/define/initialize a variable. In your case it is int i = 0. You define a variable of data type int and initialize it with a value of 0
part2 is the condition. The loop will run, until the condition becomes false. The condition will be check at the beginning of the loop.
part3 is the so called iteration-expression. The term is a little bit misguiding. It is basically a statement that is executed at the end of the loop, before the next loop run will be executed and before the condition is checked again.
In Pseudo code it is something like this:
{
init-statement
while ( condition ) {
statement
iteration-expression ;
}
}
which means for the part of your code for(int j = 0; j < 12; j++)
{
int j = 0; // init-statement
while ( j < 12 ) { // while ( condition ) {
inFile >> myArr[i][j]; // Your loop statements
j++; // Your loop statements PROBLEM
j++; // iteration-expression from the for loop
}
}
And now you see the problem. You unfortunately increment 'j' twice. You do not need to do that. The last part3 of the for loop does this for you already.
So please delete the duplicated increment statements.
Next, the std::string
A string is, as its names says, a string of characters, or in the context of programming languages, an array of characters.
In C we used to write actually char[42] = "abc";. So using really a array of characters. The problem was always the fixed length of such a string. Here for example 42. In such an array you could store only 41 characters. If the string would be longer, then it could not work.
The inventors of C++ solved this problem. They created a dynamic character array, an array that can grow, if needed. They called this thing std::string. It does not have a predefined length. It will grow as needed.
Therefore, writing string myArr[5000][12]; shows that you did not fully understand this concept. You do not need [12], becuase the string can hold the 12 characters already. So, you can delete it. They characters will implicitely be there. And if you write inFile >> myString then the extractor operator >> will read characters from the stream until the next space and then store it in your myString variable, regardless how long the string is.
Please read this tutorial about strings.
That is a big advantage over the C-Style strings.
Then your code could look like:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string myArr[5000];
int zeroCount = 0, oneCount = 0;
ifstream inFile;
inFile.open("Day3.txt");
while (!inFile.eof())
{
for (int i = 0; i < 5000; i++)
{
inFile >> myArr[i];
}
}
for (int i = 0; i < 5000; i++)
{
zeroCount = 0; oneCount = 0;
for (int j = 0; j < 12; j++)
{
if (myArr[i][j]== '0')
{
zeroCount++;
}
else
{
oneCount++;
}
}
if (zeroCount > oneCount)
{
cout << "Gamma is zero for column " << i << endl;
}
else
{
cout << "Gamma is One for column " << i << endl;
}
}
}
But there is more. You use the magic number 5000 for your array of strings. This you do, because you think that 5000 is always big enough to hold all strings. But what, if not? If you have more than 5000 strings in your source file, then your code will crash.
Similar to the string problem for character arrays, we have also a array for any kind of data in C++, that can dynamically grow as needed. It is called std::vector and you can read about it here. A tutorial can be found here.
With that you can get rid of any C-Style array at all. But please continue to study the language C++ further and you will understand more and more.
Ther are more subtle problems in your code like while(!inFile.eof()), but this should be solved later.
I hope I could help

C++ Convert one exact string element into an int

I want to create a string array and then after writing lines into it I want to change one exact character into int. I already know that all the characters are going to be numbers. As my goal is to change the one character at a time, options like atoi, stoi etc. are perhaps off? The closest I got is that:
#include <iostream>
int main()
{
int n=0,suma=0,i=0;
int multiplier[11]={1,3,7,9,1,3,7,9,1,3,1};
std::cin>>n;
std::string str[n];
for (int i = 0; i < n; ++i)
{
std::cin>>str[i];
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < 11; ++j)
{
i = str[i][j] - '0';
std::cout << i;
}
}
}
Although this is the output I get
"1-48"
I know that the string is going to be 11 characters long. Any ideas?
EDIT: It was a single typo that caused my confuse :p Yet still I'm looking forward to read and learn from your suggestions such as using different way to read n (from user input) strings. :)
In your loop:
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < 11; ++j)
{
i = str[i][j] - '0';
std::cout << i;
}
}
you are modifying outer loop variable i (looks like for the purpose of printing a value).
Given an unfortunate input, you would go out-of-bounds fast.

Crossover in genetic algorithm

The part where I get an error (more specifically, where I get a popup saying Debug error! Abort () has been called) is the part where I try to do a crossover.
for (int i = 0; i < number_of_variables; i++)
{
int gene1 = gene_selection(rng);
std::cout << gene1 << " ";
if (gene1 == 0)
{
std::cout << "test 0";
new_individuals[k].chromosomes[0].at(i) = individuals[father].chromosomes[0].at(i);
}
else if (gene1 == 1)
{
std::cout << "test 1";
new_individuals[k].chromosomes[0].at(i) = individuals[mother].chromosomes[0].at(i);
}
}
It gets far enough to display "test 0" or "test 1" but it won't actually assign the genes from the father/mother to the new_individual.
I've tried changing up the line where it assigns the old genes to the new individual, but regardless of what I try I can't get it working.
If anyone could show me where (or how) I'm messing up, I'd be very thankful :)
Edit: Stepping through the debugger, I get the following
http://prnt.sc/b0iprq
Unhandled exception at .... in LearnCPP.exe: Microsoft C++ exception: std::out_of_range at memory location .....
Another edit: Just to be clear, it's this exact line where the abort occurs:
new_individuals[k].chromosomes[0].at(i) = individuals[father].chromosomes[0].at(i);
I'm surprised you get "test0" or "test1", without a std::endl
Follow the story of new_individuals
You allocate and resize it with
std::vector<one_individual> new_individuals;
new_individuals.resize(population_size);
Next this resize(), you have a vector of population_size (5) one_individual elements where chromosomes are std::vector<std::vector<double>> of size 0.
Next you resize the chromosomes with
for (int i = 0; i < population_size; i++)
{
new_individuals[i].chromosomes.resize(number_of_variables);
}
At this point you have cromosomes of size number_of_variables (7) but what's the meaning of this?
It's mean than every cromosomes is an std::vector of seven std::vector<double> of size zero.
So, when you access
new_individuals[k].chromosomes[0].at(i)
with k == 1 (why 1 and not 0?) and i == 0, new_individual[1].chromosomes[0] exist but is of size 0, new_individuals[k].chromosomes[0].at(i) check the size of chromomoses[0] to see if at least 1, fail and cause an exception (std::out_of_range)
Your intention was to allocate every new_individuals[i].chromosomes[j]?
Or your intention was to write
new_individuals[k].chromosomes[0].push_back(individuals[father].chromosomes[0].at(i));
?
p.s.: sorry for my bad English.
--- EDIT---
If your intention is to reserve 7x7 chromosomes, one way can be
for (int i = 0; i < population_size; i++)
{
new_individuals[i].chromosomes.resize(number_of_variables);
for (int j = 0; j < population_size; j++)
new_individuals[i].chromosomes[j].resize(number_of_variables);
}
Even using push_back(), I suggest you to reserve space
for (int i = 0; i < population_size; i++)
{
new_individuals[i].chromosomes.resize(number_of_variables);
for (int j = 0; j < population_size; j++)
new_individuals[i].chromosomes[j].reserve(number_of_variables);
}

How do I determine the size of an array?

So I'm trying to have the user enter strings that will be put into an array with the maximum size of 50 strings. Whenever the user enters "stop", I want the loop to stop and the array to cutoff there.
I then want to read the array back to the user. I tried running this and got a really weird error. Can someone explain to me why this doesn't work and how I would fix it? Thanks.
int main(int argc, const char * argv[]){
string array[50];
// Get's inputs for array
for(int i = 0; i < 50; i++){
cout << "Enter string: ";
getline(cin, array[i]);
if(array[i]== "stop"){
array[i] = "\0";
break;
}
}
// Reads inputs from array
for(int i = 0; i < sizeof(array); i++){
cout << array[i] << "\n";
}
return 0;
}
I don't know why I'm getting down voted so hard?
Use std::vector for your task. It has the method push_back() where you can add elements dynamically. Also you can check the size of the vector easily by calling vector.size().
int main(int argc, const char * argv[]){
vector<std::string> array;
// Get's inputs for array
for(int i = 0; i < 50; i++){
cout << "Enter string: ";
string line;
std::getline(cin, line);
array.push_back(line);
if(array[i]== "stop"){
array[i] = "\0";
break;
}
}
// Reads inputs from array
for(int i = 0; i < array.size(); i++){
cout << array[i] << "\n";
}
return 0;
}
In your code you would have to implement a counter that counts, how many inputs the user did.
Normally you would use vectors, but since you have not reached that section of the book, I guess they want you to solve it with C-style arrays.
You can get the length of a C-style array like this
int size = (sizeof(array)/sizeof(*array)
But since you know the maximum number of entries are 50 and that you must stop when you reach the word stop, maybe you rather want this
for(int i = 0; i < 50; i++){
if (array[i] == '\0')
break;
cout << array[i] << "\n";
}
I just implemented a loop to find out how long the array is.
// Determines how long the array is
for(int i = 0; i < 50; i++){
if(array[i] == "\0"){
break;
}
counter++;
}

Assigning Symbols to Numbers in a 2D Array

I'm working on a program in C++ that is supposed to read in a file, store the content of the file into a 2D array, assign characters to each of the numbers in the array and store in a char array, and print both of these arrays. It's then supposed to go through the initial array and make sure that each number doesn't differ in value from it's neighboring numbers by more than 1, correct these errors by replacing these numbers with the value of the average of their neighbors, assign characters to this corrected array as it did before, and print both arrays.
The character assignments go as follows:
0=blank
1=.
2=,
3=_
4=!
5=+
6=*
7=#
8=$
9=&
I have the code written that opens the file and loads the array, but I have no idea where to go from there. To me the obvious, although probably not best, way to do the assignments is to go through the array with a for loop and use a series of if statements to check for the value of the number at each index and assign the appropriate symbol. I'm sure there's a better way to accomplish this.
Here is the code I have so far:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream prog;
prog.open("../prog1.dat");
//If file can't be opened, exit
if (!prog) {
cerr << "File could not be opened" << endl;
exit(EXIT_FAILURE);
}
else {
while (!prog.eof()) {
int size = 100, i, j;
prog >> size;
int **numArray = new int* [size];
for(i = 0; i < size; i++) {
numArray[i] = new int[size];
for(j = 0; j < size; j++) {
prog >> numArray[i][j];
}
cout << endl;
}
for(i = 0; i < size; i++) {
for(j = 0; j < size; j++) {
cout <<numArray[i][j] << " ";
}
cout << endl;
}
prog.close();
return 0;
}
}
}
I'm extremely new to this programming language, this is actually my first program I've done in C++ and I'm literally learning as I go. Any suggestions would be greatly appreciated.
In this code You have not put a check on the difference with neighbour.
Moreover their is no need for 2 nested for loops that is a very big overhead. You could have printed the numArray in the first nested for loop.
According to you it is your first programming assignment and you are already using double pointers and nested loops and also the way you checked the file is opened or not. Are you sure it's your first assignment