C++ std::string::at throwing std::out_of_range [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 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++) {

Related

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;
}

why it's impossible to sort a string just like a sorting of a c++ array? [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
can't we sort a string just like a classical sorting(bubble sort or something..) of an array?I tried. But it's not working.
string newstr = "dcba";
for(int i = 0; i < (newstr.size())-1; i++)
{
for(int k = i+1; k < newstr.size(); k++)
{
if(newstr[i] > newstr[k])
{
temp = newstr[i];
newstr[k] = newstr[i];
newstr[i] = temp;
}
}
}
The less code you write the less mistakes you make is a good rule to follow. To sort a string you can just do:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string newstr = "dcba";
std::sort(newstr.begin(), newstr.end());
std::cout << newstr << "\n";
}
The actual bug in your code is due to an incorrect implementation of swap:
temp = newstr[i];
newstr[k] = newstr[i];
newstr[i] = temp;
Should be:
temp = newstr[k];
newstr[k] = newstr[i];
newstr[i] = temp;
Or again more simply:
std::swap(newstr[i], newstr[k]);
You are not swapping the characters correctly.
Use
temp = newstr[k];
instead of
temp = newstr[i];
With your code you are duplicating newstr[i] everywhere, because
temp = newstr[i]; // tmp = i
newstr[k] = newstr[i]; // k = i
newstr[i] = temp; // i = tmp = i
brush up on your basics . you are running the loop till newstr.size()-1; which means you arent considering the last element or reaching it . your's swap logic is also wrong .
modified code -
for(int i = 0; i < newstr.size(); i++)
{
for(int k = i+1; k < newstr.size(); k++)
{
if(newstr[i] > newstr[k])
{
std::swap(newstr[i] , newstr[k]);
}
}
}
you can also do std::sort(newstr.begin(),newstr.end());

Sorting out duplicates between 2 char arrays [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 6 years ago.
Improve this question
I'm struggling with an assignment for my class where we have to take input from the user into a char array (word) and take out the duplicates in the word inputted if needed. Comparing the array of the modified array (word) with the alphabet array (abc) to remove the repeated letters from the list. Once the duplicates are removed then just output the modified word followed by the new form of the alphabet into the newAbc array.
For example:
The word HELLO would first become HELO then after comparing to the alphabet the end output from the new array should be HELOABCDFGIJKMNPQRSTUVXYZ.
I'm stuck more on the for loops comparing the new word to the alphabet really.
char word[20], newAbc[40] = { '\0' };
char abc[27] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int i = 0, b = 1, n = 0, leng, dup;
//dup counts up the repeats but is established in the first portion of the program but i've excluded it as it works perfectly.
cout << "Please enter a word: ";
cin >> word;
leng = strlen(word);
b = 0;
n = leng - dup;
i = 0;
for (i = 0; i < n; i++)
{
for (b = 0; b < 27; b++)
{
if (newAbc[i] != abc[b])
{
newAbc[n] = abc[b];
n++;
}
}
}
for (i = 0; i < 27; i++)
cout << newAbc[i];
cout << endl;
return 0;
}
I'd appreciate any kind of insight on my mistakes.
The major problem for crash is that you are changing n inside for loop for iterating in newAbc. And your if condition will be true for at least 25 times so incrementing n by 25(minimum) in each iteration resulting in accessing out of bound memory(SEG-FAULT).
for (i = 0; i < n; i++)
{
for (b = 0; b < 27; b++)
{
if (newAbc[i] != abc[b]) // this condition is not correct
{ // this will be true atleast 25 times
newAbc[n] = abc[b]; // wrong memory access
n++; // here is the problem
}
}
}
Assuming that your duplicate counting works fine, below are the changes required:-
char word[20];
// FIXME: your new array should not contain no duplicate so size can be 27
char newAbc[40] = {'\0'};
// FIXME: simply can be char abc[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char abc[27] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
cout << "Please enter a word: ";
cin >> word;
// dup counts up the repeats but is established in the first portion of
// the program but i've excluded it as it works perfectly.
// Lets say word = "HELLO"; so dup = 1, and newArray, should have "HELO"
memcpy(newAbc, "HELO", 4); // from your excluded part of code
int dup = 1; // from your excluded part of code
int leng = strlen(word); // length of input word
int n = leng - dup; // char remained to be inserted
// iterator for new array(newAbc)
int c = n; // n elements are already there
// Just reversed your loop
for (int b = 0; b < 27; b++)
{
int found = 0;
for (int i = 0; i < n; i++)
{
if (newAbc[i] == abc[b])
{
found = 1;
break;
}
}
if (!found)
{
newAbc[c] = abc[b];
c++;
}
}
for (int i = 0; i < 27; i++)
cout << newAbc[i];
cout << endl;
return 0;

Segmentation Fault in g++ and reading from files [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 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.

Removing more than one element from an array and creating a dynamic array 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 6 years ago.
Improve this question
I'm still new to c++ so this is a learning process for me. Also i know that i should initially use a vector to do this but i have an exercise that specifies an array so i'm trying to write a function that removes all duplicate elements in an array but i receive the error
C2100: illegal indirection
if someone could point me in the right direction
int main()
{
int *t;
int removel[9] = { 1, 1, 1, 2, 3, 4, 5, 6, 6, };
t = removeAll(removel, 9, 1);
for (int i = 0; i < 8; i++)
cout << t[i] << " ";
}
int* removeAll(int list[], int listlength, int removeitem)
{
int count = 0;
int* list2;
int removeindex;
int length;
int tempindex;
for (int i = 0; i < listlength; i++)
{
if (removeitem == list[i])
count++;
}
length = listlength - (count + 1);
list2 = new int[length];
int j;
while (j<=length)
{
remove_if(list[0], list[listlength - 1], removeitem);
for (j = 0; j < length; j++)
if (list[j] == NULL)// not sure what the remove_if func puts inplace of the removed element
continue;
else
list2[j] = list[j];
}
return list2;
}
Firstable you should calculate length like listlength - count, not listlength - (count + 1).
Then, after list2 = new int[length]; you should copy elements which are different with removeitem and skip other ones. You can do it like this
int j = 0;
for (int i = 0; i < listlength; i++) {
if (removeitem == list[i])
continue;
list2[j] = list[i];
j++;
}
and return successfully created list2. But you should also know its size. You can do it by creating int tSize in main and pass it to removeAll by link. removeAll will change its value to length. So add int & list2size to the parameters list of removeAll and write list2size = length; before returning list2. Finally, when printing t, change i < 8 to i < tSize.
If you do all this program will work right but don't forget about formatting.