C++ String subcript out of range issue - c++

I'm a student currently studying C++ and I have a problem with a code that I am trying to create. The code I am supposed to create is meant to find the hamming distance of 2 words that the user will input. (For e.g "Ironman" and "Iron" hamming distance is "3")
However, I ran into an error when I tried compiling and I can't seem to find out what the problem is. The error of "String subscript out of range" keeps popping up if the first input is longer than the second input.(It only fails to work when I try to input "Spiderman Ironman". Shorter words such as "Sean Sea" works fine.) If the second input is longer than the first input, OR if both the inputs are the same length, the entire code works fine.
string str1;
string str2;
cout << "Question 1" << endl;
cout << "Input two words (separated by space or enter) : ";
cin >> str1;
cin >> str2;
int count = hamming_distance(str1, str2);
cout << "> Hamming distance between \"" << str1 << "\" and \"" << str2 << "\" is " << count << endl;
int i;
int firstLength = str1.length();
int secondLength = str1.length();
int thirdLength;
int counter = 0;
//if the longest word is first string (Where the issue is causing)
if (firstLength > secondLength)
{
thirdLength = firstLength - secondLength;
for (i = 0; i < firstLength; i++)
{
if (str1[i] != str2[i])
{
counter++;
}
}
for (i = 0; i < thirdLength; i++)
{
counter++;
}
}
//if the longest word is second string
else if (secondLength > firstLength)
{
thirdLength = secondLength - firstLength;
for (i = 0; i < secondLength; i++)
{
if (str1[i] != str2[i])
{
counter++;
}
}
for (i = 0; i < thirdLength; i++)
{
counter++;
}
}
//if both words have the same length
else if (firstLength == secondLength)
{
for (i = 0; i < firstLength; i++)
{
if (str1[i] != str2[i])
{
counter++;
}
}
}
return counter;
It would be greatly appreciated if y'all could help me find out what the actual problem is with my code. Thank you!

You need to initialise your variables correctly:
int firstLength = str1.length();
int secondLength = str2.length();
You're also determining that one string is bigger than another, then proceeding to access elements in the shorter string according to the length of the longer one, which is giving you the subscript out of range error. You need to revise the tests when firstLength > secondLength and vice versa.

Related

C++ Comparing strings to determine palindrome

I am trying to determine if a string is a palindrome by reversing the string and then comparing the letters of both strings. The code is provided underneath. So far whatever I put I always get "is a palindrome " as an output. I am aware of the short cut method for doing this easily and efficiently but trying to understand the long way as well. I am using C++ 11
#include <iostream>
#include <string>
using namespace std;
string reversed = " ";
void reverse_sentence(string s)
{
for (int i = 0; i <= s.length(); i++)
{
reversed = s[i] + reversed;
}
cout << reversed;
}
void is_pal(string reversed, string s)
{
int flag = 0;
// if(s == string(s.rbegin(), s.rend())){
// cout << "is a palindrome"<<endl;
// }else{
// cout <<"failed"<<endl;
// }
for (int i = 0; i <= s.length(); i++)
{
for (int j = 0; j <= reversed.length(); j++)
{
if (s[i] != reversed[j - 1])
{
flag = 1;
}
}
}
if (flag == 1)
{
cout << "is palindrome" << endl;
}
else
{
cout << "not palindrome" << endl;
}
}
int main()
{
string s = "hello";
reverse_sentence(s);
is_pal(s, reversed);
return 0;
}
First issue...
your for loops go out of bounds... length() gives you number of characters in the string. Those characters have index 0 through length() - 1. Because you are using <= s.length() however, then the last time through you get erroneous data, if it doesn't give you out of bounds error. For loops using length() should be from i = 0 to i < s.length()
Biggest issue...
void is_pal(string reversed, string s)
{
int flag = 0;
for (int i = 0; i <= s.length(); i++)
{
for (int j = 0; j <= reversed.length(); j++)
{
if (s[i] != reversed[j - 1])
{
flag = 1;
}
}
}
if (flag == 1)
{
cout << "is palindrome" << endl;
}
else
{
cout << "not palindrome" << endl;
}
}
Your j loop is inside of your i loop.. which means that s[i] never changes as you compare it to every single value in reversed... unless every single character in reversed is the same character... then one of them is guaranteed to be not equal to s[i] which means that flag will be set to 1... which means your function reports it to be a palindrome...
Not only that.. but you already went through the process of doing the reverse... why are you trying to compare against reverse.. in reverse order? That would be the same as comparing against the original string in normal order...
Assuming your reverse_sentence function works correctly... then s.length() is the same as reversed.length(). So to see if s is the same forwards as it is backwards then the letter at each index of s should be exactly the same as the letter at the same index in reversed. Also what you are looking for is when they don't match... so you should initialize your flag to assume at the beginning that they are going to be matching and only set it to false when you discover that they don't match...
void is_pal(string reversed, string s)
{
bool flag = true;
// run loop through length of s or until we know s doesn't match reversed
for (int i = 0; i < s.length() && flag; i++)
{
if (s[i] != reversed[i])
{
flag = false;
}
}
if (flag)
{
cout << "is palindrome" << endl;
}
else
{
cout << "not palindrome" << endl;
}
}

C++ - does string contain a word - with simple loop?

//EDIT
the code below works only in case that str1 has only 1 beginning letter of str2; how to fix it?
for ex. if str1 / 2 = overflow / flo it works.
but if str1 is overflowfabc (has two "f"s) --> it doesn't work
//
I need to check for a word in a string using simple loop. The idea is:
find an element in str1 that is equal to 1. element of str2
if it exists, we set flag = 1, and it remains 1 if following elements are also equal. If they are not, flag is set to 0.
.
#include <iostream>
using namespace std;
int main() {
string str1, str2;
int flag;
cout << "Enter a string 1: ";
getline(cin, str1);
cout << "Enter a string 2: ";
getline(cin, str2);
for(int i = 0; i < str1.size(); i++)
{
if (str1[i] == str2[0]) // find element in str1 that is equal to first element of str2
{
flag = 1; //
for(int j = i+1; j < i + str2.size(); j++)
if (str1[j] != str2[j-i]) // checking if following elements are also equal
{
flag = 0; // if any of them is not equal
break;
}
if (flag==1)
cout << "str2 is Substring of str1" ;
else
cout << "str2 is NOT Substring" ;
}
}
return 0;
}
bool isSubStr(const string& parent, const string& child)
{
// Check each starting position
for (int i=0; i<(parent.size()-child.size()+1); ++i)
{
// Check if the substring starts at this position
// TODO make this a helper method to avoid the need for a flag
bool isSubString = true;
for (int j=0; j<child.size(); ++j)
{
if (parent[i + j] != child[j])
{
isSubString = false;
break;
}
}
if (isSubString)
{
return true;
}
}
return false;
}
The string class in C++ contains a function named find, and in my opinion you should use that.
The documentation can be found here.
An excerpt about the Return value:
The position of the first character of the first match.If no matches
were found, the function returns string::npos.
#include <iostream>
using namespace std;
int main() {
string str1, str2;
cout << "Enter a string 1: ";
getline(cin, str1);
cout << "Enter a string 2: ";
getline(cin, str2);
size_t found = str1.find(str2);
if (found != string::npos)
cout << "str2 is Substring of str1" << endl;
else
cout << "str2 is NOT Substring" << endl;
return 0;
}
It is shorter and easier to understand. So why not going with that ?
Otherwise I believe your code is not correct in more than one aspect; e.g.
you print out the text depending on the flag variable within the for loop. This does not look right to me.
the second for loop looks strange to me. I believe you are trying to program something that you believe might be considered sophisticated and well thought. To be honest with you, I suggest that do not try to do that. Do simple and clear.
Following your comment I took the time to try to improve your code.
#include <iostream>
using namespace std;
int main() {
string str1, str2;
int flag = 0;
cout << "Enter a string 1: ";
getline(cin, str1);
cout << "Enter a string 2: ";
getline(cin, str2);
for(unsigned int i = 0; i < str1.size(); i++) {
if (str1[i] == str2[0]) { // find element in str1 that is equal to first element of str2
unsigned int j = 0;
for( ; j < str2.size(); j++) {
if ( str1[i+j] != str2[j] ) { // checking if following elements are also equal
break;
}
}
if ( j == str2.size() ) { // if j equals the size of substring then all chars seem equal
flag = 1;
break;
}
}
}
if ( flag )
cout << "str2 is Substring of str1" ;
else
cout << "str2 is NOT Substring" ;
return 0;
}

Maximum number of vowels in a word in string array

I have written a program to input 2 strings in a string array.
And then print the maximum vowels stored in the list.
Where am i going wrong here,and is there a more elegant method to this.
#include<iostream.h>
#include<string.h>
int main()
int i,j,c=0,k=0,maxo=0,len1,maxo1=0,len3;
char vow[] = "AEIOUaeiou";
char list[100][100],vow[]={"AEIOUaeiou"};
for(i=0;i<2;i++) {
cout<<"Enter word: ";
gets(list[i]);
for(i=0;i<2;i++) {
len1=strlen(list[i]);
for(k=0;k<len1;k++) {
for(j=0;list[j][k]!='\0';j++)
if(list[j][k]==vow[j])
c++;
}
if(c>maxo)
maxo=c;
c=0;
}
cout<<"Maximum Vowel count:"<<maxo<<endl;
}
fflush(stdin);
getchar();
return 0;
}
The bigger programme where i am trying to incorporate this code.The necessary comments are in the code.I really cannot undertand where i am going wrong in the last part.
Should i include the last bit of code at first so that the program works?
#include<iostream.h>
#include<string.h>
int main()
{
int i,n,len=0,sum=0,j,max,min,c=0,c2=0,k=0,maxo=0,len1,maxi=0,c1=0,len2;
float avg;
char list[100][100] = { 0 };
char vow[] = "AEIOUaeiou";
for(i=0;i<2;i++)
{
cout<<"Enter word: ";
gets(list[i]);
len=strlen(list[i]);
sum=sum+len;
cout<<"Length of word: "<<len<<endl;
if(list[i][len-1]=='s')
{cout<<"The Word "<<list[i]<<" ends with s"<<endl;
c2++;
}
}
//Word input by user.Prints word along with length.
min=strlen(list[0]);
max=strlen(list[0]);
//Initialising max and min.
for(i=0;i<2;i++)
{
if(strlen(list[i])<min)
{min=strlen(list[i]);}
if(strlen(list[i])>max)
{max=strlen(list[i]);}
}
for(i=0;i<2;i++)
{
if(max==strlen(list[i]))
cout<<"The max value of the lengths stored:"<<list[i]<<endl<<"Word count:"<<max<<endl;
if(min==strlen(list[i]))
cout<<"The min value of the lengths stored:"<<list[i]<<endl<<"Word count:"<<min<<endl;
}
//Max and Min value of string lengths are printed.
avg=sum/2;
cout<<"Avg length:"<<avg<<endl;
//Average value printed.
cout<<"The number of words with s:"<<c2<<endl;
//Word ending with s.
{for (i = 0; i <2; i++)
len1 = strlen(list[i]);
for (k = 0; k < len1; k++)
{
for (j = 0; j < strlen(vow); j++)
//if (list[j][k] == vow[j])
if (list[i][k] == vow[j])
c++;
}
cout << "Number of vowels in line " << i << ": " << c << '\n';
if (c>maxo) maxo = c;
c = 0;
cout << "Maximum Vowel count so far:" << maxo << "\n\n";
cout << "Maximum Vowel count:" << maxo << endl;
}
for(i = 0 ;i < 2 ;i++)
{ len3 = strlen(list[i]);
letter = list[i][0];
{for(j=0;j<len3;j++)
if(list[i][j]==letter)
counter++;
}
cout << "Number of identical letters as first letter in line " << i << ":
" << counter << '\n';
if (c>maxo1) maxo1 = counter;
counter = 0;
cout << "Maximum letter count so far:" << maxo1 << "\n\n";
cout << "Maximum letter count:" << maxo1 << endl;
}
PS:
I have edited my code one more time to display the alphabet which has occurred the maximum number of times as starting letter of a word in the list,and the number of times it has occurred.
This won't compile for me for two reasons:
1) gets()
The most recent revision of the C standard (2011) has definitively
removed this function from its specification. The function is
deprecated in C++ (as of 2011 standard, which follows C99+TC3).
And so I can't use the gets() function.
2) You can't declare
char list[100][100], char vow[] = {"AEIOUaeiou"};
both with a comma separator.
You read the input for the first line string into the first row of the array i = 0; then you instantly loop through i, which doesn't make sense. The following is not a good solution as in C++ you should be using std::vectors and std::string, and not generally mixing C and C++ but I've tried to keep it as close to your version, using my telepathic powers to read your mind about what you're trying to do.
#include <iostream>
#include <cstring>
using namespace std;
const int numLinesToGet = 10;
const int maxCharsPerLine = 100;
int main()
{
int i, j, c = 0, k = 0, maxo = 0, len1;
//char list[100][100], char vow[] = {"AEIOUaeiou"};
char list[100][100] = { 0 };
char vow[] = "AEIOUaeiou";
//for (i = 0; i < 2; i++)
for (i = 0; i < numLinesToGet; i++)
{
cout << "Enter word: ";
std::cin.getline(list[i], maxCharsPerLine);
//gets(list[i]);
//for (i = 0; i < 2; i++) Get rid of this second loop entirely
len1 = strlen(list[i]);
for (k = 0; k < len1; k++)
{
//for (j = 0; list[j][k] != '\0'; j++)
for (j = 0; j < sizeof(vow); j++)
//if (list[j][k] == vow[j])
if (list[i][k] == vow[j])
c++;
}
cout << "Number of vowels in line " << i << ": " << c << '\n';
if (c>maxo) maxo = c;
c = 0;
cout << "Maximum Vowel count so far:" << maxo << "\n\n";
}
cout << "Maximum Vowel count:" << maxo << endl;
fflush(stdin);
getchar();
return 0;
}
Online example here
#include<stdio.h>
int main ()
{
char a[] = "i love to code in education";
int i, count = 0, vow = 0, mvow = 0;
for (i = 0; a[i] != '\0'; i++)
{
if (a[i] == 'a' || a[i] == 'e' || a[i] == 'i' || a[i] == 'o'
|| a[i] == 'u')
{
vow++;
}
if (a[i]==' ')
{
count++;
mvow = vow;
vow = 0;
}
}
printf ("Total words: %d\n", count+1);
if(vow>mvow) printf ("Max Vowels in a word: %d", vow);
else printf("Max Vowels in a word: %d", mvow);
return 0;
}

program to check is there any alphabet(a-z) exists in all string(list of novels) and print number of alphabets found

will you please tell me what will be the procedure to find alphabet occur in all strings(char string lists) in c++
the output will only return matched values(alphabet numbers)
i m trying this
#include <vector>
#include <iostream>
#include <cstdio>
int main()
{
//setup
std::vector<int> alphabetCount;
for (int i = 0; i < 26; ++i)
{
alphabetCount.push_back(0);
}
//now the interactive bit
std::cout << "Enter a line of text\n";
std::string line;
std::getline(std::cin, line);
for (size_t i = 0; i < line.size(); ++i)
{
char currentChar = tolower(line[i]);
if (isalpha(currentChar))
{
++alphabetCount[currentChar - 'a']; //subtract a, so if currentChar = a, 'a' - 'a' = 0, so its index 0
}
}
for (size_t i = 0; i < alphabetCount.size(); ++i)
{
std::cout << "there were " << alphabetCount[i] << " occurences of " << static_cast<char>(i + 'a') << "\n"; //add 'a' for the same reason as above, though we have to cast it to a char.
}
system("pause");
return 0;
}
but it only returns values from single string i want result from all string
The reason why it is taking one string at a time is because you are taking one as input, you should make a vector of string and take input in it.
You have not read the string more than once in program. below is sample program, which is very naive to demonstrate the process. The loop terminating condition can be much better than mine though.
int main()
{
//setup
std::vector<int> alphabetCount;
for (int i = 0; i < 26; ++i)
{
alphabetCount.push_back(0);
}
//now the interactive bit
std::cout << "Enter a line of text\n";
std::string line;
do{
std::getline(std::cin, line);
for (size_t i = 0; i < line.size(); ++i)
{
char currentChar = tolower(line[i]);
if (isalpha(currentChar))
{
++alphabetCount[currentChar - 'a']; //subtract a, so if currentChar = a, 'a' - 'a' = 0, so its index 0
}
}
}while(line != "exit");
--alphabetCount['e' - 'a'];
--alphabetCount['x' - 'a'];
--alphabetCount['i' - 'a'];
--alphabetCount['t' - 'a'];
for (size_t i = 0; i < alphabetCount.size(); ++i)
{
std::cout << "there were " << alphabetCount[i] << " occurences of " << static_cast<char>(i + 'a') << "\n"; //add 'a' for the same reason as above, though we have to cast it to a char.
}
system("pause");
return 0;
}

C++ array with wrong input

So I wrote this program to code to read in a number of ints, and then its supposed to read the array back to backwards. however, it just reads back all 0s
while (true)
{
cin >> input;
if (input == -1 && gotStuff == false) {return 0;}
else if (input == -1 && gotStuff == true) {break;}
else
{
inputData[pos1] = input;
pos1 ++;
gotStuff = true;
}
}
for (int i = pos1; i >= 0; i--)
{
outputData[pos2] = inputData[pos1];
pos2 ++;
cout << outputData[pos1] << " ";
}
Why is this reading back as all 0s?
You have a clear problem here
for (int i = pos1; i >= 0; i--)
{
outputData[pos2] = inputData[pos1];
pos2 ++;
cout << outputData[pos1] << " ";
}
because you always try to print outputData[pos1] but pos1 is never changed within your loop. Therefore you always output the same character. Similarly you are always copying the same character of inputData to the outputData array so when the loop exits, outputData will just contain the same character at different indices.
You might have better luck with the following loop which at least copies and prints the correct characters
pos2 = 0;
for (int i = pos1-1; i >= 0; i--)
{
outputData[pos2] = inputData[i];
cout << outputData[pos2] << " ";
pos2++;
}
You may have other problems with your code too as you do not show us in the question what the values of pos1 and pos2 have been initialised with.
When you loop through the array here:
for (int i = pos1; i >= 0; i--)
{
outputData[pos2] = inputData[pos1];
pos2 ++;
cout << outputData[pos1] << " ";
}
you are always accessing the same position: pos1 in your input data. If you change this loop to this
for (int i = pos1 - 1; i >= 0; i--)
{
outputData[pos2] = inputData[i];
pos2 ++;
cout << outputData[pos2 - 1] << " ";
}
it will count down like you intended it to. That is because i is decremented with every iteration of the loop, while pos1 is not. It was probably reading all 0s because inputData[pos1] was 0.