VisualStudios throws exception while codeblocks does not [C++] - c++

I have 2 questions:
Why does this work in codeblocks, but in visual studios throws an exception?
Can someone tell me what exactly this is doing: "if (text[i + j] == word[j]) {"
I spent hours trying to understand what it's trying to do but failed.
Source: https://github.com/Codecademy/learn-cpp/tree/master/8-references-and-pointers/bleep
Do I still need to point out I'm new to programming? Well I'm new so take it slow.
btw before looking at their solution I did find a way to do it using google I found the replace() function worked for me. But I still copied and pasted = no good. Their's is more natural without the use of others/inbuilt function(s).
main
#include <iostream>
#include <string>
#include "functions.h"
int main() {
std::string word = "broccoli";
std::string sentence = "I sometimes eat broccoli. The interesting thing about broccoli is that there are four interesting things about broccoli. Number One. Nobody knows how to spell it. Number Two. No matter how long you boil it, it's always cold by the time it reaches your plate. Number Three. It's green. #broccoli";
bleep(word, sentence);
for (int i = 0; i < sentence.size(); i++) {
std::cout << sentence[i];
}
std::cout << "\n";
}
functions.h
void bleep(std::string word, std::string &text);
void asterisk(std::string word, std::string &text, int i);
functions.cpp
#include <string>
void asterisk(std::string word, std::string &text, int i) {
for (int k = 0; k < word.size(); ++k) {
text[i+k] = '*';
}
}
void bleep(std::string word, std::string &text) {
for (int i = 0; i < text.size(); ++i) {
int match = 0;
for (int j = 0; j < word.size(); ++j) {
if (text[i+j] == word[j]) {
++match;
}
}
if (match == word.size()) {
asterisk(word, text, i);
}
}
}

On this line:
if (text[i+j] == word[j])
you are indexing too far into text. If you index out of bounds, that invokes undefined behavior. Anything can happen, including working on one platform, but not on another.
Since you only want to find complete words, you can make the index i stop earlier:
for (int i = 0; i < text.size() - word.size(); ++i)

Related

First try on string array not working. Is there something I don't know?

I just tried to use string array for the first time, and I experienced consistent crashes. It's supposed to draw a shrinking circle. Did I forget to add some important line, or is there an error in the existing code? I'm a beginner, so please don't be too mean..
#include <iostream>
#include <string>
#include <cmath>
#include <windows.h>
using namespace std;
int main() {
for (int h = -10; h < 10; h ++)
{
int r = abs(h);
string gps[20];
for (int i = -10; i < 10; i ++)
{
for (int j = -10; j < 10; j ++)
{
if (i*i + j*j <= r*r && i*i + j*j >= (r-1)*(r-1))
gps [j+10][i+10] = char (219);
else
gps [j+10][i+10] = ' ';
}
}
for (int i = 0; i < 20; i ++)
{
for (int j = 0; j < 20; j ++)
cout << gps[i][j];
cout << '\n';
}
//system("CLS"); // I know this isn't the best method, but it's the only one i know that works
// By proffesional analysis (cout), i diagnosed the problem to occur right about here
}
return 0;
}
One major issue with your code is that you are writing to the string at an out-of-bounds index here:
//...
gps [j+10][i+10] = char (219);
//...
gps [j+10][i+10] = ' ';
This declaration:
string gps[20];
declares an array of 20 empty strings. Since the strings are empty, you cannot simply write to any position in these string. These strings must already be sized appropriately before writing to a particular location.
What you may need to do is the following:
string gps[20];
for (auto& s : gps)
s.resize(20);
This will resize each string in the array to 20 elements, thus making your loop access valid entries in any of those strings. Writing to an out-of-bounds string position is undefined behavior, where in your case, the program crashes.
Now, will this draw the circle correctly, I am not sure. But this answer focuses on the crash you are getting when running the program.

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.

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

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.

Add a newline every set amount of letters in std::string

I'm working with a few long strings inside a C++ program (up to 65535 letters).
What am looking for is a way to add a new line every set amount of letters with an function like this:
addNewLinesToString(std::string* string, u8 lettersBetween newline);
Which would work like this:
string test = "Testing1234567";
addNewLinesToString(&test, 7); //test == "Testing\n1234567\n"
I have yet to find such a function that only used the standard class library (C and/or C++)
If somebody has a simple solution for this would be great :)
Thanks.
You can use string::insert for this purpose.
addNewLinesToString(std::string& str, int sep)
{
for (int i = 0; i < str.size(); i += sep)
str.insert(i, "\n");
}
But this will be O(n^2) (as pointed by #stefan) , you can also
addNewLinesToString(std::string& str, int sep)
{
string ans;
int i = 0;
while (i < str.size())
{
if (i % sep == 0 && i)
ans.push_back('\n');
ans.push_back(str[i]);
i++;
}
return ans;
}
Which uses more memory but is O(n).
Take a look at examples: http://www.cplusplus.com/reference/string/string/insert/
std::string insert_newlines(const std::string &in, const size_t every_n)
{
std::string out;
out.reserve(in.size() + in.size() / every_n);
for(std::string::size_type i = 0; i < in.size(); i++) {
if (!(i % every_n) && i) {
out.push_back('\n');
}
out.push_back(in[i]);
}
return out;
}
This:
allocates memory exactly once.
doesn't make the mistake of using int where size_t or std::string::size_type is required, so you don't run into strange problems for large strings or embedded platforms.
runs in linear O(n) time.
has an functional interface (rather than modifying the string in-place), an algorithm that modifies the input string and runs in O(n) time would be much more complex.
Try this function:
void addNewLinesToString(std::string* s, int change){
if(change <= 0)
return;
for(int i = 0; i < s.size(); i += change){
s.insert(i, "\n");
i++;
}
}
Edit: I don't know why your post got voted down, I up voted.
Maybe not fastest, but working:
void addNewLinesToString (std::string* txt, int limit)
{
if(limit <= 0)
return;
limit++;
for (int i=1; i<=txt->size()/limit; i++)
txt->insert((i*limit)-1, "\n");
}