Where are these garbage values coming from? - c++

I have written this function that reverses the order of words within a string, the function behaves as expected until it has read two words then starts to behave unexpectedly:
string ReverseString(string InputString){
int EndOfGroup = 0;
string ReversedString = " ";
int k = 0;
ReversedString.resize(InputString.size());
for (int i = InputString.length(); i > 0; i--){
if (isspace(InputString[i]))
{
EndOfGroup = i;
for (int j = i; j >= EndOfGroup && j < InputString.length(); j++)
{
ReversedString[k] = InputString[j] ;
k++;
}
}
}
What I mean by behaves unexpectedly is that once I pass a string to the function it starts to populate the ReversedString variable with garbage values until the goes out of bounds.
This shoes the point the programme crashes:
InputString "the brown fox died"
ReversedString " died fox died brownÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««îþîþ"
j 9
i 3
EndOfGroup 3
k 20
This is not a duplicate question as my method is different to existing methods out there.

Think about the inner loop,
for (int j = i; j >= EndOfGroup && j < InputString.length(); j++)
For the first word, this is good, now for the second word - are the conditions correct?
Remember you are writing to the reversed string using an incrementing index k...

You are copying the word only when you are meeting space sign
if (isspace(InputString[i]))
{
//start of copying...
what does mean that you will not copy the first work (there is no space before the word).
resize() method is fullfilling the string will null character (due to reference) and they are probably show as
ÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««îþîþ
You need to handle the first word
for (int i = InputString.length(); i >= 0; i--){
if (isspace(InputString[i]) || i == 0)
Also it would be good to provide some default char instead of null by using
ReversedString.resize(InputString.size(), ' ');

Related

Why does this code output different results for the same inputs?

I wrote a simple program to find the longest sub-string with distinct characters in a given string in C++. My code works for certain inputs, but doesn't for others. Moreover, it gives me different outputs for the same inputs. Where am I going wrong?
int main() {
int t;
cin >>t;
while(t--){
string s;
cin >> s;
int n = s.length();
int maxlen = 0;
for(int i = 0; i < n; i++){
int count = 0;
int arr[26] = {0};
bool isDist = true;
int j = i;
while(isDist){
if(arr[(int)s[j] - (int)'a'] == 0){
count++;
arr[(int)s[j] - (int)'a'] = 1;
j++;
} else {
isDist = false;
}
}
if(count > maxlen) maxlen = count;
}
cout << maxlen << endl;
}
return 0;
}
for the following input:
3
aewergrththy
aewergrththy
aewergrththy
My code outputs:
5
4
4
Any help is appreciated, Thank you!
The problem is that there is no check that j remains less than n, so you start checking characters beyond the end of your string, leading to in unpredictable results. Try
while (isDist && j < n)
That should help but I haven't checked the rest of your code for errors.
You could also consider using s.at(j) instead of s[j]. That at least results in predictable behaviour when going out of bounds, at throws an exception in that case.
The program has undefined behavior because you do not bounds-test when iterating over the string with j. You should modify the inner loop to test for j in addition to isDist:
while(isDist && j < n)
Without this, it's very easy for j to shoot past the end of the string as soon as all remaining characters in the string have not yet been encountered.
In this case, it will be when you process the character 'y' at the end of the string. After dealing with 'y', you'll advance j such that s[j] returns the string terminator. Now, you'll be accessing the array with arr[0 - 'y'] which of course is undefined behavior due to being a negative index.

Having Trouble With The Reversal of a String

class Solution {
public:
string reverseWords(string s) {
int previousWhiteSpace = 0;
for(int i = 0; i <= s.size(); i ++){
if(isspace(s[i]) || i == s.size()){
for(int j = previousWhiteSpace; j < i/2; j++){
char temp = s[j];
s[j] = s[i-1-j];
s[i-1-j] = temp;
}
previousWhiteSpace = i + 1;
}
}
return s;
}
};
Hi. So the goal of my function is to reverse the input of a string. So for example, if I am given "Let's take LeetCode contest" , my function should return "s'teL ekat edoCteeL tsetnoc" . However, currently my function is ONLY returning
"s'teL take LeetCode contest" . I have a counter which I indicate as previousWhiteSpace to keep track of the start of every new word that seems to work for the first word, but not the rest. Any help would be appreciated.
You can simply assign " " to the variable previousWhiteSpace and no need to increment. thus your code will detect white space automatically till the end of the string and will run the code after every white space. As you have assigned value 0 to it will only perform the result for the first word and it will terminate.

How to remove 2 consecutive duplicates from an array? c++

I have an array a={1,2,3,3,2,2,3,3} and I need to remove the duplicates like this:
1: a={1,2,2,2,3,3}
2: a={1,2,3,3}
3: a={1,2}
I need to remove 2 consecutive duplicates: (1,2,3,3 will be 1,2), (1,2,2,2 will be 1,2).
Here is my try, but as you can see, I need some help.
#include <iostream>
int main()
{
int n;
std::cin >> n;
int a[n];
for (int i = 0; i < n; i++)
std::cin >> a[i];
int i, j;
for (i = 0; i < n; i++)
if (a[i] == a[i + 1]) {
for (j = i + 1; j < n; j++)
a[j - 1] = a[j];
n--;
i--;
}
if (n != 0)
for (int i = 0; i < n; i++)
std::cout << a[i] << " ";
return 0;
}
My problem is that I don't know how to remove 2 consecutive values. After multiple tries, I can't resolve this. Thank you in advance!
I'm not going to write code for you, but here are my thoughts.
First, write a function to check if there even exists "consecutive duplicates":
//returns true if there are no consecutive duplicates within the array, false otherwise
func noConsecDups(arr a)
for int i = 0, i <= a.length-2, i++
if a[i] = a[i++]
return false
end of if
end of loop
return true
end function
Now, write a function that removes the consecutive duplicates recursively (might not have to do it recursively, that's just my initial thought) while checking to see if you even need to remove any!
//function that takes an array as input and returns the array with all consecutive duplicates removed
func removeConsecDups(arr a)
if a.length is 1, return a
if a.length is 2 and a[0] != a[1], return a
if(noConsecDups(a)) then there are no consecutive duplicates, return a
otherwise look through the array and just remove the first consecutive duplicates
for int j = 0, j <= a.length-2, j++
if a[j] = a[j+1]
remove a[j+1]
remove a[j]
break
end if statement
end loop
recursively call removeConsecDups(a)
end function
If you just need the final result (an array with no consecutive duplicates left) then your best bet is probably to use a stack and just traverse the whole input array once, comparing the values to the stack top and poping the duplicates off the stack.
If you need to print out the array state after every intermediate step, then #BarronDuBois's suggestion is the way to go.
Either way the code itself should be simple enough, I'd be glad to help with any specific issue.

C++: using a substring to create a new string

I have a string..."APPLES" and i'm having difficulty using substring to effectively manipulate the string. My goal is to add a '-' every 3 characters. My problem is that when "APPLES" goes through, it returns "APP-ES-" which is incorrect, I'm trying to make it return "APP-LES-" any suggestions? Here is my code thus far...
for(int j = 0; j <= str.length(); j++){
str_substr += str.substr(j,j+3);
str_substr = str_substr + '-';
j = j+3;
cout << str_substr;
}
Just build a separate string by copying the relevant parts.
std::string s;
for(size_t i = 0; i < str.length(); i += 3) {
s += str.substr(i, 3) + "-";
}
(Just so you note it for sure: str.substr(j,j+3); is incorrect, it won't copy 3 characters, it will copy j + 3 characters. Read the documentation more carefully.)
You're incrementing j twice:
for(int j = 0; j <= str.length(); j++){
^-- once here
...
j = j+3;
^-- and again here
Also, it looks like you might get two -s at the end of a string with a length that's a multiple of three, since you're checking for j <= str.length() instead of j < str.length() Try:
for(size_t j = 0; j < str.length(); j+=3){
str_substr += str.substr(j,3) + '-';
}
cout << str_substr;
Since you're apparently just copying the result to cout, anyway, perhaps it's easiest to skip the intermediate string, and just copy 3 characters to cout, then write a -, three more characters, etc.
#include <string>
#include <iterator>
#include <iostream>
int main(){
std::string input("APPLES");
size_t len = 3;
for (size_t pos = 0; pos < input.length(); pos += len)
std::cout << input.substr(pos, len) << "-";
}
If you need to modify the existing string, you probably want to start by computing the number of dashes you're going to insert, then work from the end of the string back to the beginning, moving each character directly to its destination. If you start at the front and insert dashes where needed, it ends up as an O(N2) algorithm. Working from end to beginning and moving each character directly to its destination is O(N) instead.

Segfault in Cygwin but not VS, any ideas?

It works with Visual Studio, but segfaults in Cygwin, which is weird because I'm compiling the same source, and both generate a Windows executable. GDB doesn't work very well for me in Cygwin for some reason, and the error doesn't appear in VS so I can't really debug it there.
Any ideas?
int main(void)
{
Pair ***occurences = new Pair**[20];
int i, j, k;
for (i = 0; i < 20; i++)
{
occurences[i] = new Pair*[i+1];
for (j = 0; j < i+1; j++)
{
occurences[i][j] = new Pair[26];
for (k = 0; k < 26; k++)
{
Pair pair;
pair.c = k + 'a';
pair.occurs = 0;
occurences[i][j][k] = pair;
}
}
}
std::fstream sin;
sin.open("dictionary.txt");
std::string word;
while (std::getline(sin, word))
{
if (word.size() < 21)
{
for (i = 0; i < word.size(); i++)
{
// SEGFAULTING HERE
occurences[word.size()-1][i][word[i] - 'a'].occurences++;
}
}
}
for (i = 0; i < 20; i++)
{
for (j = 0; j < i+1; j++)
{
delete [] occurences[i][j];
}
delete [] occurences[i];
}
delete [] occurences;
return 0;
}
You marked this line as the critical point:
occurences[word.size()-1][i][word[i] - 97].occurs++;
All three array accesses might go wrong here, and you would have to check them all:
It seems like the first dimension of the array has the length 20, so the valid values for the index are [0..19]. word.size()-1 will be less than 0 if the size of the word is zero itself, and it will be larger than 19 if the size of the word is 21 or more.
Are you sure the length of the word is always in the range [1..20]?
The second dimension has variable length, depending on the index of the first dimension. Are you sure this never gets out of bound?
The third dimension strikes me as the most obvious. You subtract 97 from the character code, and use the result as index into an array with 26 entries. This assumes that all characters are in the range of [97..122], meaning ['a'..'z']. Are you sure that there will never be other characters in the input? For example, if there are any capital characters, the resulting index will be negative.
Just reformulating my comment as an answer:
occurences[word.size()-1][i][word[i] - 'a'].occurs++;
if word.size() is 100 (for example) this will crash (for i == 0) since occurences has only 20 elements.