C++ delete duplicates from cstring [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 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;
}

Related

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.

Hackerrank "Abort Called": I don't know what's wrong[C++]

I was solving a problem from hackerrank in VSCode. I thought I had finally figured out the solution, so I copied it over to the hackerrank compiler. I hit compile and it pops up an "Abort Called" error. Here's the code:
#include <iostream>
#include <bits/stdc++.h>
void printEvenArray(char charArray[], int length)
{
for(int i = 0; i < length; i++)
{
if(i == 0 || i % 2 == 0)
{
std::cout << charArray[b];
}
}
std::cout << ' ';
}
void printOddArray(char charArray[], int length)
{
for(int i = 0; i < length; i++)
{
if(i != 0 && i % 2 != 0)
{
std::cout << charArray[i];
}
}
std::cout << '\n';
}
int main() {
int numOfSubjects, stringLength = 0;
std::cin >> numOfSubjects;
std::string subjectString[numOfSubjects];
char stringToCharArray[stringLength + 1];
for(int i = 0; i < numOfSubjects; i++)
{
std::cin >> subjectString[i];
}
for(int x = 0; x < numOfSubjects; x++)
{
stringLength = subjectString[x].length();
strcpy(stringToCharArray, subjectString[x].c_str());
printEvenArray(stringToCharArray, stringLength);
printOddArray(stringToCharArray, stringLength);
}
return 0;
}
This code compiles fine in VSCode. It gives me the desired outcome, but as soon as I bring it over to hackerrank, it gives an "Abort Called" error. I've read up online that abort called only shows up when either I try to use memory I don't have access to or is read only, or if I use a certain macro, am I'm not using any macros. I'm also relatively knew to C++, and clueless to memory management if that's what the issue is here. I appreciate any help a whole lot.
char stringToCharArray[stringLength + 1];
So, stringToCharArray has length 1. Nothing in the loop changes that. Your strcpy is much longer than one character, so it just overwrites whatever was next in memory. On one compiler you got away with this behavior, but the other (probably deliberately set to look for boundary violations like this) aborted.
Read about https://en.wikipedia.org/wiki/Buffer_overflow.
There are some other improvements you can make. For instance, i+=2 can step through a loop two at a time without checking whether i be odd or even.

Working with vectors C++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Complicated question, probably simple answer. So the program I need to make cannot include any library other than String, iostream, and vector. I need to create a program that has 3 functions. One that creates an integer vector, one that reverses a vector, and one that prints a vector. In order to take in values I need to use getline to intake a string, if the string states quit, we stop putting new values into it. Other wise we need to test if its an integer(positive or negative) and add it to the vector. My code is starting to get complicated so I really need some help. Below is what i have so far. I'm also using Visual Studio, if that matters. Thanks for any help in advance! The question I have is when I run the program, it will only output the first digit. I don't know why and would like to know what I'm doing wrong.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> CreateVector()
{
string tempvariable;
bool quit = false;
vector<int> userinput;
cout << "Please enter in an integer, type 'quit' to exit " << endl;
while (!quit)
{
getline(cin, tempvariable);
if (tempvariable == "quit")
quit = true;
else
{
bool isaninteger = true;
for(int i = 1; i <= tempvariable.size(); i++)
{
if (tempvariable[i] = "-" || isdigit(tempvariable[i]))
continue;
else
{
cout << "You entered in an incorrect option, please enter in a correct option" << endl;
cin.clear();
cin.ignore();
isaninteger = false;
break;
}
}
if (isaninteger)
userinput.push_back(stoi(tempvariable));
cout << "Please enter in an integer, type 'quit' to exit " << endl;
}
}
return userinput;
}
void printVector(vector<int> userinput)
{
int amountofspots = userinput.size();
cout << "Your Vector is ";
for (int i = 0; i < amountofspots; i++)
{
if (i = (amountofspots - 1))
cout << userinput.at(i) << endl;
else
cout << userinput.at(i) << " , ";
}
}
void reverseVector(vector<int>& userinput)
{
int amountofspots = userinput.size();
vector<int> tempvector;
for (int i = 0; i < amountofspots; i++)
tempvector.push_back(userinput.at(amountofspots - i));
for (int i = 0; i < amountofspots; i++)
userinput.pop_back();
for (int i = 0; i < amountofspots; i++)
userinput.push_back(tempvector.at(i));
}
int main()
{
vector<int> CreatedVector = CreateVector();
printVector(CreatedVector);
reverseVector(CreatedVector);
printVector(CreatedVector);
system("pause");
return 0;
}
Change if (i = (amountofspots - 1)) to if (i == (amountofspots - 1)) in the loop in printVector().
Change tempvariable[i] = "-" to tempvariable[i] == '-' in CreateVector().
= is the assignment operator, == is the comparison operator. Also, single characters are surrounded by single quotes, not double quotes.
void reverseVector(vector<int>& userinput)
{
int amountofspots = userinput.size();
vector<int> tempvector;
for (int i = 0; i < amountofspots; i++)
tempvector.push_back(userinput.at(amountofspots - i));
should probably be
void reverseVector(vector<int>& userinput)
{
int amountofspots = userinput.size();
vector<int> tempvector;
for (int i = 1; i < amountofspots+1; i++) // Index error
tempvector.push_back(userinput.at(amountofspots - i));
The following:
for(int i = 1; i <= tempvariable.size(); i++)
{
if (tempvariable[i] = "-" || isdigit(tempvariable[i]))
Must become:
for(int i = 0; i < tempvariable.size(); i++)
{
if (tempvariable[i] == '-' || isdigit(tempvariable[i]))
Explanation:
String indices start from 0 and end at size() - 1.
[i] returns a single char. "-" is not a single char but an entire string literal. You cannot directly compare a single char with an entire string. -, however, is a single char, so that comparison will work.
= is not comparison but assignment. == is used for comparison. As your compiler should have warned you!
Note that there are further problems with your code:
if (i = (amountofspots - 1))
You are again mixing assignment and comparison. Make that ==. And pay attention to compiler warnings!
And finally, isdigit is not exactly a great function. In order to really use it correctly, you'd first have to cast the operand to int and at the same time make sure it is not an invalid value, as documented here.
Why don't you just catch the exception thrown by stoi if the specified string cannot be parsed?

How do i implement bubblesort and where [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
The task is to implement a bubblesort function followed by a linearsearch aka "linsok" in my "familj" array. the array keeps both the name and the age, so i want to sort the array after their age and print it out. ive got the line search to work but now im stuck with the bubblesort.
The problem is that i dont know how to make my bubble sort code work for this code.
so do i implement the second piece of code in this?
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
string namn;
int alder;
void skrivUt(string _namn, int _alder)
{
namn = _namn;
alder = _alder;
}
};
int linsok(Person* PersonArray, int key)
{
for (int i = 0; i < 4; i++)
{
if (PersonArray[i].alder == key)
return i;
}
return -1;
}
int main()
{
Person familj[4];
familj[1].skrivUt("Emma",23);
familj[3].skrivUt("Emilia",29);
familj[2].skrivUt("Johan",26);
familj[0].skrivUt("Timmy ",21);
int index = linsok(familj,22); //the age of the person im looking for.
if(index== -1)
cout << "Personen hittades ej!"; //person not found
else
//prints out the persons name and the index.
cout << "Personen heter " << familj[index].namn << " hen finns på index " << index << endl;
cin.get();
return 0;
}
This is the piece of bubble-sort code i used before and it works.
int p [] = {10,56,73,23,31,24,43};
int a = 6;
for (int i = 0; i < a; i++)
{
int nrLeft = a - i;
for (int j = 0; j < nrLeft; j++)
{
if (p[j] > p[j+1])
{
int temp = p[j];
p[j] = p[j+1];
p[j+ 1] = temp;
}
}
}
for(int i = 0; i < 7; i++)
cout << p[i] << endl;
cin.get();
It's likely that you want to convert this to a function that you pass your array of Person objects to, along with the size of it, and then you just access the part that you want to compare. Since you'd be implementing it as a function, you can use it in the same way you use your linsok function, although you'd probably want it to return the sorted array as opposed to an index.
Disclaimer for following code: Neither run nor compiled
Person* bubbleSort(Person* p, int size)
{
for (int i = 0; i < size; i++)
{
int nrLeft = size - i;
for (int j = 0; j < nrLeft; j++)
{
if (p[j].alder > p[j+1].alder)
{
Person temp = p[j];
p[j] = p[j+1];
p[j+ 1] = temp;
}
}
}
return p;
}
That's based off you sorting them by alder (which I guess is age? I don't speak Swedish(?)) You just need to provide the signature, and alter it based on your needs, but the basic idea is that you just change what you compare, and the data types.
Another way to do this is to return an int or void(But you should return an int to tell you if it was successful or not), and pass a pointer to the array, so Person** in the signature, and operate directly on that array, but that's a little more difficult, and arguably bad practice, depending on use case.

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++) {