Segmentation Fault in g++ and reading from files [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a problem with this program, it reads from two files.
Each file, A and B contains an int at the top wich is the number of the strings it has. The program has to do a B - A operation, file A has 2 strings, "two" and "three". File B has 4 strings, "one", "two", "three" and "four". So the result in the third file has to be "one" and "four". Those which are not in the file A, but yes in file B.
First I read the size of each file, then the strings of each one.
I calculate the size of result file and compare the strings of the two files.
I have used gdb debugger and it says that the problem is in the for that compares the files. What I do is:
If string in B, is not found in A, I put it in the result.
I write here the whole program (not too big) so you can get a better idea.
Many thanks and sorry for spanish name in variables.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main(){
int contador = 0;
string* datosA;
string* datosB;
string* resultado;
int tamA, tamB, tamResultado;
ifstream fichA("fA.txt");
if(fichA){
fichA>> tamA;
datosA = new string [tamA];
for(int i = 0; i < tamA; i++){
fichA>> datosA[i];
}
fichA.close();
}
ifstream fichB("fB.txt");
if(fichB){
fichB>> tamB;
datosB = new string [tamB];
for(int i = 0; i < tamB; i++){
fichB>> datosB[i];
}
fichB.close();
}
tamResultado = tamB - tamA;
resultado = new string [tamResultado];
contador = 0;
for(int i = 0; i < tamB; i++){
bool enc = true;
for(int j = 0; j < tamA && enc; j++){
if(datosB[i] != datosA[j]){
enc = false;
}
}
if(!enc){
resultado[contador] = datosB[i];
contador++;
}
}
delete[] datosA;
delete[] datosB;
ofstream fout("resultado.txt");
if(fout){
for(int i = 0; i < tamResultado; i++){
fout<< resultado[i];
}
fout.close();
}
delete[] resultado;
datosA = datosB = resultado = 0;
return 0;
}

Check your conditions.
You are changing your flag whenever you come across different element. But it should happen only when ALL of the elements in the array A are different from the one in the array B for specific position.
The way it is written now, you are trying to add all four elements from array B to your resulting array which is segmentation fault because you are trying to access unallocated memory.
One possible solution would be to add counter which checks if both elements in array A are different from the element in array B.
Something like this:
for(int i = 0; i < tamB; i++){
bool enc = true;
// counter that keeps track of number of different elements
int count = 0;
for(int j = 0; j < tamA && enc; j++){
if(datosB[i] != datosA[j]){
count++;
}
}
// check if all elements in datosA are different than datosB[i]
if(count == tamA){
resultado[contador] = datosB[i];
contador++;
} }
That should work as intended.

Related

Is there a way to count the number of ocurrences of each element of a string array?

I have the following code that does exactly what I want. The problem is that I need the sample array to compare the strings and keep the count. Is there a way to count the number of occurrences of each string on any array without a sample?
For a little bit more context, the initial problem was to read data from a .txt file including vehicles information, like:
Volkswagen Jetta
Ford Focus
Volkswagen Jetta
And count the number of vehicles of each brand. Keep in mind that this is from an introductory course for programming, and we don't know how to use vectors or maps.
#include <iostream>
#include <string>
using namespace std;
using std::string;
#define MAX 20
int main(){
int counter[MAX];
string arr[MAX]={"ABC","AOE","ADC","ABC","ADC","ADC"};
string sample[MAX]={"ABC", "AOE", "ADC"};
for(int i=0; i<=MAX; i++){
counter[i]=0;
}
for(int i=0; i<MAX;i++){
for(int j=0; j<MAX; j++){
if (sample[i]==arr[j]){
counter[i]++;
}
}
}
for(int i=0; i<3;i++){
cout<< sample[i] << "=" << counter[i]<<endl;
}
return 0;
}
All you are expected to do is keep a list (an array will do) of brand names, and an array of counts for each name:
std::string brand_names[100];
int counts[100]; // number of times each element of brand_names[] was read from file
int num_items = 0;
Each time you read a brand name from file, try to find it in the array of strings. If found, just add one to the count at the same index. If not found, add it to the end of the brand_names[] array, add 1 to the end of the counts[] array, and increment num_items.
You do not need anything more than a simple loop for this:
an outer loop to read the next brand name from file
an inner loop to try to find the brand name in the list
If you want to solve this problem without knowing the initial values of the sample array:
Create an empty sample array. When you see new elements add them to this array.
Use a variable sample_size to keep track how many samples have been seen. Below is a simple example which doesn't use std::vector or dynamic allocation.
int main()
{
std::string arr[MAX] = { "ABC","AOE","ADC","ABC","ADC","ADC" };
std::string sample[MAX];
int sample_size = 0;
int counter[MAX] = { 0 };
for (int i = 0; i < MAX; i++)
{
if (arr[i].empty()) break;
bool sample_found = false;
for (int j = 0; j < sample_size; j++)
if (arr[i] == sample[j])
{
sample_found = true;
counter[j]++;
break;
}
if (!sample_found)
{
sample[sample_size] = arr[i];
counter[sample_size]++;
sample_size++;
}
}
for (int i = 0; i < sample_size; i++)
cout << sample[i] << "=" << counter[i] << std::endl;
return 0;
}

C++ delete duplicates from cstring [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a c-string that looks something like ABBBCACACACBA and I'm supposed to create a function that deletes the duplicate characters so I end up with ABC. I created a nested for loop that replaces every letter that matches the letter in the outer loop with a \0 and increments a counter that keeps track of the repeats. I'm getting -1 as the amount of repeats that should be documented, and from checking it spits out ABBC instead of ABC. I'm stumped, any ideas?
for (int i = 0; i < SIZE; i++)
{
for (int j = i + 1; j < SIZE; j++)
{
if (letter[i] == letter[j])
{
letter[j] = '\0';
repeatCounter++;
}
}
}
It is not enough to just replace duplicates with '\0', you have to actually remove them from the string and shift the remaining characters down. Try something more like this:
int size = SIZE, i = 0;
while (i < size)
{
int j = i + 1;
while (j < size)
{
if (letter[j] == letter[i])
{
for (int k = j + 1; k < size; k++)
{
letter[k-1] = letter[k];
}
letter[--size] = '\0';
repeatCounter++;
continue;
}
j++;
}
i++;
}
Live Demo
Here's a simple example which does what you want. It uses std::string to store the output. You can copy-n-paste the code here to test and run. Look into using std::string as it has functions which will make your life easy.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string input("ABBBCACACACBA");
string output;
for(size_t i = 0; i < input.size(); i++)
{
if(output.find(input[i]) == string::npos)
{
output += input[i];
}
}
cout << "Input: " << input << endl;
cout << "Output: " << output << endl;
return 0;
}

Is this the correct implementation of Insertion Sort? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
OUTPUT
#include <iostream>
using namespace std;
int main()
{
//declaring the size of array and taking input from the user
int n = 0;
cout<<"Enter the Number of elements you want in the Array : ";
cin>>n;
//checking the user input
if(n <= 0)
{
cout<<"Not Possible\n";
return 1;
}
//declaring array of size 'n' and taking input from user
int list[n];
cout<<"Enter the Elements of the array of size "<<n<<" : ";
for(int i = 0; i < n; i++)
cin>>list[i];
//Insertion Sort
int swap = 0; //number of swaps
int comp = 0; //number of comparison
int temp; //temporary variable
for(int i = 0; i < n-1; i++)
{
for(int j = i+1; j > 0; j--)
{
if(list[j] < list[j-1])
{
//swapping equivalent to shifting
temp = list[j-1];
list[j-1] = list[j];
list[j] = temp;
comp++;
swap++;
}
else
{
comp++;
break;
}
}
//printing the iteration
cout<<"Iteration "<<(i+1)<<" : ";
for(int k = 0; k < n; k++)
cout<<list[k]<<" ";
cout<<"\n";
}
cout<<"\nSwap : "<<swap<<"\n";
cout<<"Comparison : "<<comp<<"\n";
cout<<"Sorted Array : ";
for (int i = 0; i < n; i++)
{
cout<<list[i]<<" ";
}
return 0;
}
Is this implementation of insertion sort correct because I have seen many implementation online using while loop and other things?
If not can you point out what is wrong?
Thanks in advance
link - https://github.com/ish-u/DiscreteStructures/blob/master/InsertionSort.cpp
No, this is a different type of sort, known as bubble sort. It still sorts, but insertion sort works in a different way, by keeping the array sorted at all times (moving elements if a new insertion would break the ordering).
So instead of just tagging new elements to the end of the array where you read them from cin, you should place each element directly in the right spot in the array. This will likely involve moving existing elements in order to keep the array sorted.
Note that your line
int list [n];
is wrong; you cannot allocate memory this way (and I'm surprised it even compiles). A better choice would be to use std::vector.

How to compare two 2d arrays of char in C/ C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am passing two 2d arrays of char into a function, that will return 1 if the arrays are equal and 0 otherwise.
size of the arrays is [4][4], However when I try to iterate through the array I get an error.
int checkIfWin(char** array, char** array2){
int winner = 0;
for(int i = 0; i < 4; i++){
if(strcmp(array2[i], array[i])==0){
winner = 1;
}
else
winner = 0;
}
return winner;
}
UPDATE:
The reason why I was getting an errorn while strcmp is because I did not malloc the second 2d array.
char[] is different from char *, the first places the value '\0' at the end of the array instead the second does not.
The function strcmp will compare the elements until it finds the value '\0', for that task better compare element to element and if you find a difference returns automatically.
int checkIfWin(char** array, char** array2){
for(int i = 0; i < 4; ++i){
for (int j = 0; j < 4; ++j){
if(array2[i][j] != array[i][j]){
return 0;
}
}
}
return 1;
}
Here is a solution using strncmp():
int winner = 1, i;
for(i = 0; i < 4; i++){
if((strncmp(array2[i], array[i], 4)) != 0){
winner = 0;
break;
}
}
return winner;

C++ std::string::at throwing std::out_of_range [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
void Display::displayText(const char* text) {
using std::string;
using std::vector;
string line = string(text);
vector<string> temp(1);
if (Display::startLine < 0) Display::startLine = 0;
bool cont = true;
int lastRegex = 0;
int regex = 1;
string tmp = string(" ");
for (int i=0; i<line.length(); i++) {
if(line.at(i)=='\n') {
tmp = line.substr(lastRegex, i-lastRegex);
tmp.erase(tmp.find("\n"), tmp.find("\n"));
lastRegex = i+1;
regex++;
temp.resize(regex);
temp[regex-1] = tmp;
}
if (i - lastRegex == COLS-3) {
bool b = true;
int j = i;
while (b) {
if (line.at(i) == ' ') {
b = false;
tmp = line.substr(lastRegex, j-lastRegex);
lastRegex = j+1;
regex++;
temp.resize(regex);
temp[regex-1] = tmp;
}
j--;
}
}
}
regex++;
temp.resize(regex);
temp[regex-1] = line.substr(lastRegex, string::npos);
if (Display::startLine+1 > temp.size()) Display::startLine = temp.size()-1;
for (int i=0; i<temp[startLine].length(); i++) Window::draw(i+1, 1, temp[Display::startLine].at(i));
if (Display::startLine+1 <= temp.size()-1)
for (int i=0; i<temp[Display::startLine+1].length(); i++) Window::draw(i+1, 2, temp[Display::startLine].at(i));
if (Display::startLine > 0) Window::draw(COLS-2, 1, '^');
if (Display::startLine + 1 < temp.size()-1) Window::draw(COLS-2, 2, 'v');
}
}
This code compiles correctly. When I run it, however, I get an std::out_of_range error for std::basic_string::at.
I have tried to add a check for if line is empty, and change the for loop so it is .length()-1, but both of those produce the same result.
This function is supposed to take in the text, and display it on the top two lines of a window, (thus the COLS variable and the Window::draw) and add arrows to the end of the lines if the text expands past the two lines. The text I'm inputting currently that throws the error is "Hello World!".
It isn't a problem with the draw function, if I manually display the same text with Window::draw. (This method is specifically made to automatically wrap the text around the screen and cap it at two lines)
Strings are arrays of characters that are indexed starting at 0. If you want to access the first character, its at position 0, if you want to access the last character, its at position length -1.
For example, string test = "hello";
test.at(0) would give me 'h', test.at(4) would give me '0', test.at(5) = test.at( test.length() ) = out of range error
Change your for loop to
for (int i=0; i<line.length() - 1; i++) {