String Subscript out of range in C++ - string

I'm trying to convert Roman Numerals into Decimal numbers but I keep encountering this error every time I enter a Roman Numeral. I've tried editing the code numerous times but so far I haven't been able to figure out what's going on.
Here's my code:
Header:
#include <string>
using namespace std;
class romanNumeralType
{
public:
string setNumeral() const;
string getNumeral();
int convert(string romanNumber);
int getDecimal();
void printRoman() const;
void printDecimal() const;
private:
string romanNumber;
int englishNumbers;
};
Implementation:
string romanNumeralType::setNumeral() const
{
string romanNumber;
cout << "Please enter the Roman Numeral you wish to use: ";
cin >> romanNumber;
cout << endl;
return romanNumber;
}
string romanNumeralType::getNumeral()
{
return romanNumber;
}
int romanNumeralType::convert(string romanNumber)
{
englishNumbers = 0;
for (size_t i = 0; i < romanNumber.length(); i++ )
{
switch (romanNumber[i])
{
case 'm':
case 'M':
if (romanNumber[i] == 'M')
{
englishNumbers += 1000;
}
break;
case 'd':
case 'D':
if(romanNumber[i+1] == 'M')
{
englishNumbers += 500;
}
else if(romanNumber[i-1] == 'M')
{
englishNumbers -= 500;
}
break;
case 'c':
case 'C':
if(romanNumber[i+1] == 'M' || romanNumber[i+1] == 'D')
{
englishNumbers += 100;
}
else if(romanNumber[i-1] == 'M' || romanNumber[i-1] == 'D')
{
englishNumbers += 100;
}
break;
case 'l':
case 'L':
if(romanNumber[i+1] == 'M' || romanNumber[i+1] == 'D' || romanNumber[i+1] == 'C')
{
englishNumbers -= 50;
}
else if(romanNumber[i-1] == 'M' || romanNumber[i-1] == 'D' || romanNumber[i-1] == 'C')
{
englishNumbers += 50;
}
break;
case 'x':
case 'X':
if(romanNumber[i+1] == 'M' || romanNumber[i+1] == 'D' || romanNumber[i+1] == 'C' || romanNumber[i+1] == 'L')
{
englishNumbers -= 10;
}
else if(romanNumber[i-1] == 'M' || romanNumber[i-1] == 'D' || romanNumber[i-1] == 'C' || romanNumber[i-1] == 'L')
{
englishNumbers += 10;
}
break;
case 'v':
case 'V':
if(romanNumber[i+1] == 'M' || romanNumber[i+1] == 'D' || romanNumber[i+1] == 'C' || romanNumber[i+1] == 'L' || romanNumber[i+1] == 'X')
{
englishNumbers -= 5;
}
else if(romanNumber[i-1] == 'M' || romanNumber[i-1] == 'D' || romanNumber[i-1] == 'C' || romanNumber[i-1] == 'L' || romanNumber[i-1] == 'X')
{
englishNumbers += 5;
}
break;
case 'i':
case 'I':
if(romanNumber[i+1] == 'M' || romanNumber[i+1] == 'D' || romanNumber[i+1] == 'C' || romanNumber[i+1] == 'L' || romanNumber[i+1] == 'X' || romanNumber[i+1] == 'V')
{
englishNumbers -= 5;
}
else if(romanNumber[i-1] == 'M' || romanNumber[i-1] == 'D' || romanNumber[i-1] == 'C' || romanNumber[i-1] == 'L' || romanNumber[i-1] == 'X' || romanNumber[i-1] == 'V')
{
englishNumbers += 1;
}
break;
default:
return 0;
}//end switch
}//end for
return englishNumbers;
}
int romanNumeralType::getDecimal()
{
return englishNumbers;
}
void romanNumeralType::printRoman() const
{
cout << "The Roman Numeral is: " << romanNumber;
}
void romanNumeralType::printDecimal() const
{
cout << "The Decimal is: " << englishNumbers;
}
Any help at all would be greatly appreciated!

We have 0 <= i < romanNumber.length(), but you are getting access to romanNumber[i-1] and romanNumber[i+1]. So it is possible to try to get access to romanNumber[-1] or to romanNumber[romanNumber.length()] - it is forbidden.
So, you have to add checks. For example, before if(romanNumber[i+1] == 'M') it is necessary to check that i+1<romanNumber.length(). And before if(romanNumber[i-1] == 'M') it is necessary to check that i > 0.

I think this is happening because some of your code looks at array indexes ahead of the current index, e.g. i+1. When the end of the array is reached, i+1 will not be a valid element of the array, giving you an error.

Related

how to make button stop working once timer is over

i have created a 50 second timer. Once the timer reach zero a pop view will appear displaying the score and the button on the application should stop working but i am not sure how to make the button stop being clickable
equal.setOnClickListener{
++total
if(ans == ans4 || ans1 == ans4 || ans2 == ans4 || ans3 == ans4 || ans == ans5 || ans1 == ans5 || ans2 == ans5 || ans3 == ans5
|| ans == ans6 || ans1 == ans6 || ans2 == ans6 || ans3 == ans6){
answer.setText("Correct")
answer.setTextColor(Color.GREEN)
++correct
score.setText("Score: $correct/$total")
} else {
answer.setText("Wrong")
answer.setTextColor(Color.RED)
score.setText("Score: $correct/$total")
}
}
val timer = object: CountDownTimer(50000, 1000) {
override fun onTick(millisUntilFinished: Long) {
countTimer.setText("Remaining: " + millisUntilFinished / 1000);
if (correct >= 5){
countTimer.setText("Remaining: " + (millisUntilFinished + 10000 ) / 1000);
}
}
override fun onFinish() {
popup()
}
}
timer.start()
}
fun popup(){
var popupView: View = layoutInflater.inflate(R.layout.score, null)
var gameover_textView = popupView.findViewById<TextView>(R.id.endMessage)
gameover_textView.setText("Score: $correct/$total ")
var popupwindow = PopupWindow(this)
popupwindow.contentView = popupView
popupwindow.showAtLocation(popupView, Gravity.CENTER, 0, 100)
popupView.setOnClickListener{
popupwindow.dismiss()
}
}
equal.setClickable(false);
equal.setClickable(true);
//according to the requirement

Simple removeVowel function not changing input string

I'm trying to make a simple function in dart to test on which should remove all vowels from an input string but its seems my code never changes the from the original input. Could anyone help me with this? thanks
String removeVowel( str) {
var toReturn = "";
for (var i = 0; i < str.length; i++) {
var temp = str.substring(i,i+1);
if (temp != 'a' || temp != 'e' || temp != 'i' || temp != 'o' || temp!= 'u')
{
toReturn = toReturn + temp;
}
}
return toReturn;
}
and what my tests shows:
00:02 +0 -1: dog --> dg [E]
Expected: 'dg'
Actual: 'dog'
Which: is different.
Expected: dg
Actual: dog
^
Differ at offset 1
Good first try but there is a much easier way of doing this.
replaceAll should do the trick
String removeVolwels(String s){
return s.replaceAll(RegExp('[aeiou]'),'');
}
https://api.flutter.dev/flutter/dart-core/String/replaceAll.html
To make your code work you should change the || to &&
String removeVowel( str) {
var toReturn = "";
for (var i = 0; i < str.length; i++) {
var temp = str.substring(i,i+1);
if (temp != 'a' && temp != 'e' && temp != 'i' && temp != 'o' && temp!= 'u')
{
toReturn = toReturn + temp;
}
}
return toReturn;
}

How do I get a for loop to only disply the outputs one time while using substring

The loop keeps repeating the output for the entire span of the word.
I tried initiating the console.write on the inside and outside the loop. I also tried changing the values of the incrementor and the substring.
Console.WriteLine("Enter a word.");
string userWord = Console.ReadLine();
Console.WriteLine();
Console.WriteLine("You wrote {0}", userWord);
Console.WriteLine();
userWord.ToLower();
char[] wordArray = userWord.ToArray();
for (int i = 0; i <= wordArray.Length; i++)
{
string theLetter = userWord.Substring(i, 1);
//theLetter = theLetter.ToLower();
string rebuilt = new string(wordArray);
if (wordArray[i] == 'a' || wordArray[i] == 'e' || wordArray[i] == 'i' || wordArray[i] == 'o' || wordArray[i] == 'u')
{
wordArray[i] = '$';
}
Console.WriteLine("Your word is now: {0}", rebuilt);
Console.WriteLine("The total number of letters in your word is {0}", userWord.Length);
}
Console.ReadLine();
the console.write should display it's output only once.
You would need to move your Console.WriteLine outside the loop. Also, your loop condition needs to be changed to avoid the ArgumentOutOfRangeException.
for (int i = 0; i < wordArray.Length; i++)
There is one more error in your code. You are converting userWord to lower case, but you are not storing the result.
userWord.ToLower();
Above line needs to be replaced with
userWord = userWord.ToLower();
Complete Code
Console.WriteLine("Enter a word.");
string userWord = Console.ReadLine();
Console.WriteLine();
Console.WriteLine("You wrote {0}", userWord);
Console.WriteLine();
userWord = userWord.ToLower();
char[] wordArray = userWord.ToArray();
for (int i = 0; i < wordArray.Length; i++)
{
if (wordArray[i] == 'a' || wordArray[i] == 'e' || wordArray[i] == 'i' || wordArray[i] == 'o' || wordArray[i] == 'u')
{
wordArray[i] = '$';
}
}
var rebuildWord = new string(wordArray);
Console.WriteLine("Your word is now: {0}", rebuildWord);
Console.WriteLine("The total number of letters in your word is {0}", userWord.Length);
Just for your information, you could achieve the same using Regex as well.
Console.WriteLine("Enter a word.");
string userWord = Console.ReadLine();
Console.WriteLine();
Console.WriteLine("You wrote {0}", userWord);
Console.WriteLine();
var rebuildWord = Regex.Replace(userWord,#"[aeiouAEIOU]","$");
Console.WriteLine("Your word is now: {0}", rebuildWord);
Console.WriteLine("The total number of letters in your word is {0}", userWord.Length);
This is just simple. You should check if the loop is in final iteration before printing.
Console.WriteLine("Enter a word.");
string userWord = Console.ReadLine();
Console.WriteLine();
Console.WriteLine("You wrote {0}", userWord);
Console.WriteLine();
userWord.ToLower();
char[] wordArray = userWord.ToArray();
for (int i = 0; i <= wordArray.Length; i++)
{
string theLetter = userWord.Substring(i, 1);
//theLetter = theLetter.ToLower();
string rebuilt = new string(wordArray);
if (wordArray[i] == 'a' || wordArray[i] == 'e' || wordArray[i] == 'i' || wordArray[i] == 'o' || wordArray[i] == 'u')
{
wordArray[i] = '$';
}
if(i==userWord.Length)
{
Console.WriteLine("Your word is now: {0}", rebuilt);
Console.WriteLine("The total number of letters in your word is {0}", userWord.Length);
}
}
Console.ReadLine();

Java, String index out of bounds in while loop

public class Solution {
public static void main(String[] args) {
System.out.println(romanToInt("DCXXI"));
}
public static int romanToInt(String s) {
int ln = s.length()-1;
int ans = 0;
int i=0;
while (i <=ln){
if (s.charAt(i) == 'M'){
ans += 1000;
}else if (s.charAt(i) == 'D'){
ans += 500;
}else if (s.charAt(i) == 'C' && s.charAt(i+1)=='D'){
ans += 400;
i=i+1;
}else if (s.charAt(i) == 'C' && s.charAt(i+1)=='M'){
ans += 900;
i=i+1;
}else if (s.charAt(i) == 'C'){
ans += 100;
}else if (s.charAt(i) == 'L'){
ans += 50;
}else if (s.charAt(i) == 'X' && s.charAt(i+1)=='L'){
ans += 40;
i=i+1;
}else if (s.charAt(i) == 'X' && s.charAt(i+1)=='C'){
ans += 90;
i=i+1;
}else if (s.charAt(i) == 'X'){
ans += 10;
}else if (s.charAt(i) == 'V'){
ans += 5;
}else if (s.charAt(i)=='I' && s.charAt(i+1)=='V'){
ans += 4;
i=i+1;
}else if (s.charAt(i)=='I' && s.charAt(i+1)=='X'){
ans += 9;
i=i+1;
}else if (s.charAt(i)=='I'){
ans += 1;
}
i++;
System.out.printf("Current sum is: %s and current pointer i is: %s \n",ans, i);
}
return ans;
}
}
I keep getting error message
java.lang.StringIndexOutOfBoundsException: String index out of range:
5
But I couldn't find where I did it wrong. Can someone help me?
Output:
This is D
Current sum is: 500 and current pointer i is: 1
This is C
Current sum is: 600 and current pointer i is: 2
This is X
Current sum is: 610 and current pointer i is: 3
This is X
Current sum is: 620 and current pointer i is: 4
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 5
at java.lang.String.charAt(Unknown Source)
at Solution.romanToInt(Solution.java:65)
at Solution.main(Solution.java:9)
You set
int ln = s.length()-1;
and use
while (i <=ln){....}
then get
s.charAt(i+1)
so it is possibly i+1 >= s.length();
then s.charAt(i+1) will throw Exception
The problem here is that when you are at the last character of the string provided, you are testing, sometimes, string.charAt(i+1) that causes your IndexOutofBound exceptions.
These two "else if" cases caused the exception:
}else if (s.charAt(i+1)=='I' && s.charAt(i+1)=='V'){
....
}else if (s.charAt(i+1)=='I' && s.charAt(i+1)=='X'){
....

How do you use the for loop in this code?

def binary_string(s):
Write a function that takes a string, converts it to a binary string
where vowels are replaced by 0 and consonants are replaced by 1.
The function should return the binary string.
binary_string("Karen")
'10101'
binary_string("Hello World!")
'10110 10111!'
if __name__ == '__main__':
import doctest
doctest.testmod(verbose = True)
Try something like this. Assuming the name of your string variable is "stringVar".
string binaryString="";
for(int i=0;i<stringVar.Length();i++)
{
if(stringVar == 'a' || stringVar == 'A' || stringVar == 'e') //and so on
{
binaryString[i] = '0';
}
else
{
binaryString[i] = '1';
}
}//end for loop.
print(binaryString);
This should give you the result you are looking for. This is the basic functionality. The rest depends on the language you are coding in.
Hope this helps.
Since you have not specified language in which you want solution, so i am assuming it to be java(from my side ). Although, algorithm will be valid for all languages.
code
public class SO {
public static void main(String[] args) {
String s = "Karen";
char[] arr = s.toCharArray();
StringBuilder binary = new StringBuilder();
for (char c : arr) {
if(Character.isAlphabetic(c)){
if (isVowel(c)) {
binary.append("0");
}else{
binary.append("1");
}
}else{
binary.append(c);
}
}
System.out.println(binary);
}
private static boolean isVowel(char c) {
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
return true;
}
return false;
}
}
output
When input is
String s = "Karen";
then output is
binary = 10101
and
When input is
String s = "Hello World!";
then output is
binary = 10110 10111!

Resources