I have written a short String reverse program in C++. I decided to write it in Java, and so I did. However, once I completed writing the program, I encountered several errors that I have tried to fix but cannot fix. One of the errors was an ArrayOutOfBounds exception. Please help me fix the errors. The C++ program worked fine. Below is the Java code. Please note that I do not want to use inbuilt functions.
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
String word;
int i = 0;
boolean inp = true;
System.out.println("Enter one or more words to be reversed:");
word = scan.nextLine();
char wordArray[] = word.toCharArray();
while(wordArray[i]!='\0')
i++;
while(inp == true){
i--;
System.out.println(wordArray[i]);
if(i==0){
System.out.println();
break;
}
}
}
}
There is no null-terminating character in Java strings; they have a length() method you should use to determine length.
Also, the while loop would be more idiomatic as:
while (true) {
...
}
Or as a simple for loop.
This is another possibility, perhaps simpler:
public String reverse(String str) {
char[] chars = str.toCharArray();
int n = chars.length;
for (int i = 0; i < n/2; i++) {
char tmp = chars[i];
chars[i] = chars[n-i-1];
chars[n-i-1] = tmp;
}
return new String(chars);
}
And although you mentioned that you don't want to use built-in functions, the most idiomatic way would be this:
public String reverse(String str) {
return new StringBuilder(str).reverse().toString();
}
strings in java are not necessarily null terminated, you should use String.length() method to find out how long it is.
Java Strings are not zero-terminated, thus the byte array created from string isn't either. You used a loop to determine the length of your array, but that loop doesn't find a byte with value 0, so it goes over the range. Use word.length() instead.
The second thing: You used System.out.println to print the character - that inserts a linebreak after each character. Is this intended?
Related
I am writing a program in java that allows a user to enter n and puts them strings into an array. Then, the program takes those strings and splits them up into single char characters and places those characters into a new char array.
An example of what I'm trying to do is below:
Input n: 3
Input strings: "Cat", "Dog", "Mouse"
Original Input Array: [Cat][Dog][Mouse]
Desired Output Array: [C][a][t][D][o][g][M][o][u][s][e]
There are a few problems that occur with my code when I run it:
I get an exception error with the line of code that takes in my input strings. Line of code: exp[i] = input.nextLine();
Netbeans IDE is telling me it can not find the symbol for the split function I'm trying to use.
I am not sure what is wrong with my code, but I feel like at least the part where I input the strings should be working. I realize I don't have any output code yet, as I am just trying to get the input part working right now. Any suggestions would be appreciated!
public class Strings {
Scanner input = new Scanner(System.in);
int n; //number of strings
String[] exp = new String[n]; //input strings
char[] tokens = new char[n]; //individual char characters
//Gather data
public void SetNumberStrings(){
n = input.nextInt();
}
public void SetExpressions(){
for (int i = 0; i < n; i++){
exp[i] = input.nextLine();
}
}
public void SplitExpressions(){
for (int i = 0; i < n; i++){
tokens[i] = exp.split(" ");
}
}
public static void main(String[] args) {
Strings exp1 = new Strings();
exp1.SetNumberStrings();
exp1.SetExpressions();
exp1.SplitExpressions();
}
}
There are multiple issues with your code:
The array initialization is not working like that. Having int n;
//number of strings as a class field, means it will be initialized
with 0, resulting in your arrays having a length of 0. To fix this
you may declare your arrays after giving a value to n.
At line tokens[i] = exp.split(" "); there is indeed a compilation
error, because you are trying to call the split method on the exp
array, but the split method is from String class. So you would need
to call exp[i].split
split method is not doing what you think it's doing. I think you
are looking for the toCharArray() method.
tokens array should have the length of all the strings that you
scanned.
There are several issues with your program. The initialisation of class member variables seems to be wrong (considering your requirement). The call to SetExpressions in main will not alter the members n, exp and tokens as you are expecting. Value of n will be 0 by default and it remains so by the time exp and tokens get initialised. Hence, when you try to assign the input strings to the elements of exp, you get java.lang.ArrayIndexOutOfBoundsException.
Further, you are trying to invoke split method on a String[] object (exp), which is wrong (a String has split() method not String[]).
If you just trying to take a string of words and convert them all into a char[], then may be you can simply concatenate all the words into a single String object, and then do a toCharArray() on that.
Hope this helps.
import java.util.Scanner;
public class Strings {
Scanner input = new Scanner(System.in);
int n; //number of strings
String[] exp; //Fix...This line was causing exception in your program We should not initialize array here because at this point we don't have the length from user
char[] tokens; //Fix...We are not confirmed of the length of token array at this point
//Gather data
public void SetNumberStrings(){
n = input.nextInt();
}
public void SetExpressions(){
exp= new String[n];
for (int i = 0; i <n; i++){
exp[i] = input.next();//.next() function should be used.
}
}
public void SplitExpressions(){
int length=0;
int l=0;
for(int i=0; i<exp.length; i++) {
length+= exp[i].length();
}//this loop will calculate the required length for character array
tokens =new char[length];//Giving length of array here
for(int i=0; i<exp.length; i++) {
for(int j=0; j<exp[i].length(); j++) {
tokens[l]=exp[i].charAt(j);//
l++;
}
}
}
public static void main(String[] args) {
Strings exp1 = new Strings();
exp1.SetNumberStrings();
exp1.SetExpressions();
exp1.SplitExpressions();
}
}
I have cleared all the problems in the code. As mentioned in comments.You had initialized all class variables in class, this is not a good programming practice.
So... I understand the idea of one main method and then being able to call multiple classes. That we can refer to one directly in order to run different scenarios. AKA use it if it is needed. Static is for one instance while main is overarching
Questions:
1. Where i have placed the bar there is a return; which is used to get me out of this instance. However, it is telling me i need a String. Which makes sense because the method and the output must match?
I have attempted:
1.to return solely the int value
2.to convert the int to string using-String.valueOf(special);
Where is the error?
import java.util.Scanner;
public class Overall{
public static void main(String[] argc){
Scanner input = new Scanner(System.in);
int i = 0;
int containsLowerCase = 0;
System.out.println(" Please give me a string that has a combination of lower, upper, digits and special characters");
String s1 = input.next();
System.out.println(s1);
}
public static String isSpecial (String input){
int special = 0;
int i =0;
for(i=0;i< input.length(); i++){
char c = input.charAt(i);
if (c=='#' || c=='$' || c== '*' || c== '&')
special++;
String.valueOf(special);
}
return special;
_________________________________________________________
^ ONLY FOCUSING ON UPPER HALF ISSUES ^
public static String print (String input){
System.out.println(s1);
}
public static int isDigit (int input){
int digit = 0;
for(i=0;i< input.length(); i++){
char c = imput.charAt(i);
if (character.isDigit(s1.charAt(i))){
isDigit++;
}
return isDigit++;
}
}
public static int isLower (int input){
int digit = 0;
for(i=0;i< input.length(); i++){
char c = imput.carAt(i);
if (character.isLowerCase(s1.charAt(i))){
isLower++;
}
}
}
public static int isUpper (int input){
int digit = 0;
for(i=0;i< input.length(); i++){
char c = imput.carAt(i);
if (character.isUpperCase(s1.charAt(i))){
isUpper++;
}
}
}
}
You return special which is an int, you need to define a new String variable and return that or simply return String.valueOf(special);.
You called the String.valueOf(int) which will convert an int to a String but you need to place the return value of that method in a String variable.
Example: String newStringVariable = String.valueOf(special);
Return String.valueOf(number)
public static String isSpecial (String input){
int special = 0;
int i =0;
for(i=0;i< input.length(); i++){
char c = input.charAt(i);
if (c=='#' || c=='$' || c== '*' || c== '&')
special++;
}
return String.valueOf(special);
I will try to mention all your mistakes, and tell you why it is wrong and what it has ro be like.
First, lets begin with your isSpecial method:
You count the number of times a special character is in your String. Most of its code is right, but I think you wanted return type of int not of String. See, the type you write before the name of the method, in this case String, is what type of Object the method will return. In your method you count the number of times a certain event happens, so you want to return that number to later calculate with that or something else.
The return statement has to be in the method body, and when it is reached, the current method takes that value and gives it back to the call of it. Afterwards the method exits, so after a return this method ended and the program continues where you called that method. Take following code:
public class Test {
public static void main (String [] args){
String testText = "This was written on 2.03.2017";
int numbers = countNumeric (testText);
System.out.println ("The text containes "+ numbers +" numbers");
}
public static int countNumeric (String text){
int count = 0;
for (int i = 0; i < text.length; i++){
if (Character.isDigit (text.charAt (i))
count++;
}
return count;
}
When executing this method, java creates a new String, then passes that String to the countNumeric method, where count is incremented by one for each digit character in the String. Then countNumeric returns the count. The program jumps back to the main method and there takes the return value of countNumeric and puts it into the variable numbers, then it prints that.
Also you seem to have a problem using String.valueOf. String.valueOf is a method, which takes a number and converts it to a string. But since you declared special as int, you cannot store a String in it (and maybe want to use it later on). So to convert a number to a String, you have to create a new variable of type String, like in this simple example:
int number = 123;
String text = String.valueOf (number);
//do something with text
So most of your errors are due to missing returns or wrong return type. Also the reurn in your isDigit method is in the for loop, so it will only look at the first character of the String.
I hope I could help you, and would suggest you to look for a good java step by step tutorial, since you don't seem very familiar with programming.
So i have been trying to make a code that counts the number of words in a string which was pretty easy. I'm running into problems when im trying to make it count the number of unique characters in a string. The program compiles and runs it doesn't display the number of Unique characters. Adding a System.out.println(countOfUniqueChars); below return doesn't work.
Here's the code:
public class Uniquechar{
public static void main(String[] args) {
String s = "Jag vet inte vad jag heter idag";
String[] parts = s.split(" ");
int wordcount = parts.length;
System.out.println("The number of words is" + wordcount);
countUniqueCharacters(s);
}
public static int countUniqueCharacters(String s) {
String lowerCase = s.toLowerCase();
char characters[] = lowerCase.toCharArray();
int countOfUniqueChars = s.length();
for (int i = 0; i < characters.length; i++) {
if (i != lowerCase.indexOf(characters[i])) {
countOfUniqueChars--;
}
}
return countOfUniqueChars;
}
Try this:
s = s.replace(" ", ""); // If you don't want to count space
char[] chars = s.toCharArray();
Set<Character> uniqueChars = new HashSet<>();
for (char c : chars) {
uniqueChars.add(c);
}
System.out.println(c.size());
Just print the method call, it prints the result.
System.out.println(countUniqueCharacters(s));
Adding a System.out.println(countOfUniqueChars); below return doesn't work.
It won't work. Because the code after return statement is unreachable. Perhaps you can do it just before return.
System.out.println(countOfUniqueChars);
return countOfUniqueChars;
You can do System.out.println(countUniqueCharacters(s)); in the main method, to output the return value of your method. After a return, you cannot add more code. I did it for you and the output is 12, so it seems to be that there is also something wrong with your algorithm.
int uniqeCharsCount = countUniqueCharacters(s);
System.out.println("The number of uniqe chars is " + uniqeCharsCount);
Output: 12
Your algorithm:
Actually you are checking every char, if this char is one more time in the string before. But you should also check if the char is anywhere in the string after the current index. You can fix it if you change your if condition to if (i != lowerCase.indexOf(characters[i]) || i != lowerCase.lastIndexOf(characters[i]))
Output of the fixed version: 3 (n, h, r)
I would recommend using a Set to retain only uniques, then count its size, instead of iterating:
public static int countUniqueCharacters(String s) {
String lowerCase = s.toLowerCase();
char characters[] = lowerCase.toCharArray();
Set<Character> uniques = new HashSet<Character>();
for (char c: characters) {
uniques.add(c);
}
return uniques.size();
}
if (i != lowerCase.indexOf(characters[i])) {
countOfUniqueChars--;
}
This is wrong. Your lowerCase string is lowercase, so any uppercase letters in characters[i] will have an index of -1 in lowerCase (will be calculated as a non-unique character). You can fix this by using indexOf(lowerCase.charAt(i));
A good way to count the number of characters would be eliminating repetitions. The ideia is get the first character, then find next occurrences and replace by nothing, once you do that you can count the unique characters.
public static int countUniqueCharacters(String s) {
String lowerCase = s.toLowerCase();
///Get the first char of lowerCase
String firstChar = lowerCase.substring(0,1);
//Take off the first char
String subS = lowerCase.substring(1);
///replace all chars equals to first char
String replacedSubS = subS.replace(firstChar, "");
/// Now, call method again to calculate size
/// of the substring with first char
// replaced by blank char
return 1+countUniqueCharacters(replacedSubS);
}
This method worked for me, take a look. You may do that in two lines, but i thought it's better be detailed here.
Adding a System.out.println(countOfUniqueChars); below return doesn't work.
That is expected behavior because return means that flow of control will be returned from method to place where this method was invoked. This means that code after return will not be executed, so in situation like
return countOfUniqueChars;
System.out.println(countOfUniqueChars);
System.out.println(countOfUniqueChars); would be dead code.
You could try printing value before you return it like
System.out.println(countOfUniqueChars);
return countOfUniqueChars;
or simply print returned value in main method like
int count = countUniqueCharacters(s);
System.out.println(count);
or using this one-liner
System.out.println(countUniqueCharacters(s));
BTW since Java 8 your code can look like
s.toLowerCase().chars().distinct().summaryStatistics().getCount()
or if you want to skip spaces you can add
s.toLowerCase().replace(" ","").chars().distinct().summaryStatistics().getCount()
public static int countUniqueCharacters(String s) {
char [] input=s.toCharArray();
Set<Character> charset=new HashSet<>();
for (int i = 0; i < input.length; i++) {
charset.add(input[i]);
}
return charset.size();
}
I am having difficulty in the following, replacing certain characters from the string
There will be two inputs, first will be character and second will be string
then I need to replace all those characters from the string with it's position
for example ,
the input and output of my program are as follows which is absolutely correct as per the requirement
Input : i this is Ignite
( Here "i" is the first input and "this is Ignite" is the second input
Output : th2s 5s 8gn11te
Input : i this is ignite and i am pratik
Output : th2s 5s 8gn11te and 20 am prat30k
The replacement should not be case-sensitive.
I had written the following program but it's having some bugs, Bugs in the sense that I am actually doing some project online and the automated sytem is not accepting the program because of some logical error.The automated system does some test cases with different inputs and check the output ( not exceptions or invalid inputs) can someone help me identify it ?
import java.util.*;
import java.io.*;
class rplc
{
public static void main(String args[])
{
String str,temp="";
char ch, ch2;
int arr[]=new int[100];
int len,i,x=0;
Scanner input=new Scanner(System.in);
ch=input.next().charAt(0);
str=input.nextLine();
str=str.replaceAll("^\\s+","");
ch2=ch;
if(Character.isUpperCase(ch))
ch2=Character.toLowerCase(ch);
else if(Character.isLowerCase(ch))
ch2=Character.toUpperCase(ch);
len=str.length();
temp=str;
for(i=0;i<len;i++)
{
if(str.charAt(i)==(int)ch || str.charAt(i)==(int)ch2)
{
arr[x]=i;
x=x+1;
}
}
x=0;
for(i=0;i<len;i++)
{
if(str.charAt(i)==(int)ch || str.charAt(i)==(int)ch2)
{
temp=str.substring(0,i);
temp=temp+(arr[x]);
temp=temp+str.substring(i+1,len);
str=temp;
len=temp.length();
x=x+1;
}
}
System.out.print(temp);
}
}
Seems like your code should work. Just in case I tried writing a simpler program:
Scanner input=new Scanner(System.in);
char ch = Character.toLowerCase(input.next().charAt(0));
String str = input.nextLine().trim().toLowerCase();
input.close();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < str .length(); i++) {
if (str.charAt(i) == ch) {
buf.append(i);
}
else {
buf.append(str.charAt(i));
}
}
System.out.println(buf.toString());
And the output seems to be same.
Perhaps your function should return the value instead of printing it?
From the comments I understand that there will be only 1 input from the user.
The following input:
i this is ignite and i am pratik
Where the first 'i' is the charcter which needs to be replaced in 'this is ignite and i am pratik'.
Modify following:
str=input.nextLine();
str=str.replaceAll("^\\s+","");
to
str = input.nextLine();
str = str.substring(1);
str = str.replaceAll("^\\s+", "");
Try Something like this,
Scanner s = new Scanner(System.in);
String Line = s.nextLine();
String ch = Line.substring(0,Line.indexOf(" ")).trim();
Line = Line.substring(Line.indexOf(" ")).trim();
String[] x= Line.split(ch);
String y="";
for(String t:x){
y=y.equals("")?t:y+y.length()+t;
}
System.out.println(y);
I did some code cleaning but the most important steps were to use a list of dynamic size instead of a fixed size array and a while-loop with dynamic termination instead of a for-loop. This is because the length of the output String will change (increase) when there a characters to be replaced at positions >9 and thus in your code the execution can stop in the middle of the result string and there are characters not being replaced.
There is even a special case, when the replaced character is a number itself. To avoid problems there I added this line
i = i + Integer.toString(list.get(pos)).length()-1;
in order to step over newly added number characters in the output String.
import java.util.*;
import java.io.*;
class rplc
{
public static void main(String args[])
{
List<Integer> list = new ArrayList<Integer>();
Scanner input=new Scanner(System.in);
char ch = input.next().charAt(0);
String str=input.nextLine().trim();
int len=str.length();
for(int i=0;i<len;i++)
{
if(str.charAt(i)==Character.toLowerCase(ch) || str.charAt(i)==Character.toUpperCase(ch))
{
list.add(i);
}
}
int pos = 0;
int i = 0;
while(i<str.length())
{
if(str.charAt(i)==Character.toLowerCase(ch) || str.charAt(i)==Character.toUpperCase(ch))
{
String start = str.substring(0,i)+Integer.toString(list.get(pos));
String end = i<=str.length() ? str.substring(i+1) : "";
i = i + Integer.toString(list.get(pos)).length()-1;
pos++;
str = start.concat(end);
}
i++;
}
System.out.print(str);
}
}
I can't see any special bugs. Could be that I lost sight of something. This is my first answer here and English is not my mother tongue, so please excuse any formal errors.
I liked the problem so I made my own answer. apologies for the dirty looking code. :)
Scanner input=new Scanner(System.in);
String firstInput=input.nextLine().charAt(0) + "";
//ensure its lower case
firstInput=firstInput.toLowerCase();
String secondInput=input.nextLine();
//ensure char in secondInput is lower cased too.
secondInput=secondInput.replaceAll(firstInput.toUpperCase(),firstInput);
String[] splitted=secondInput.split(firstInput);
String output="";
int current=0;
for(int i=0;i<splitted.length;i++){
String s=splitted[i];
current=current+ s.length();
if(i==splitted.length-1){
output=output+s;
}else{
output=output+s;
output=output+ current;
current++;
}
}
//edited part, as split doesn't split if firstinput is the last character of the string
if(secondInput.endsWith(firstInput)){
output=output+secondInput.length();
}
System.out.println(output);
String handling in Java is something I'm trying to learn to do well. Currently I want to take in a string and replace any characters I find.
Here is my current inefficient (and kinda silly IMO) function. It was written to just work.
public String convertWord(String word)
{
return word.toLowerCase().replace('á', 'a')
.replace('é', 'e')
.replace('í', 'i')
.replace('ú', 'u')
.replace('ý', 'y')
.replace('ð', 'd')
.replace('ó', 'o')
.replace('ö', 'o')
.replaceAll("[-]", "")
.replaceAll("[.]", "")
.replaceAll("[/]", "")
.replaceAll("[æ]", "ae")
.replaceAll("[þ]", "th");
}
I ran 1.000.000 runs of it and it took 8182ms. So how should I proceed in changing this function to make it more efficient?
Solution found:
Converting the function to this
public String convertWord(String word)
{
StringBuilder sb = new StringBuilder();
char[] charArr = word.toLowerCase().toCharArray();
for(int i = 0; i < charArr.length; i++)
{
// Single character case
if(charArr[i] == 'á')
{
sb.append('a');
}
// Char to two characters
else if(charArr[i] == 'þ')
{
sb.append("th");
}
// Remove
else if(charArr[i] == '-')
{
}
// Base case
else
{
sb.append(word.charAt(i));
}
}
return sb.toString();
}
Running this function 1.000.000 times takes 518ms. So I think that is efficient enough. Thanks for the help guys :)
You could create a table of String[] which is Character.MAX_VALUE in length. (Including the mapping to lower case)
As the replacements got more complex, the time to perform them would remain the same.
private static final String[] REPLACEMENT = new String[Character.MAX_VALUE+1];
static {
for(int i=Character.MIN_VALUE;i<=Character.MAX_VALUE;i++)
REPLACEMENT[i] = Character.toString(Character.toLowerCase((char) i));
// substitute
REPLACEMENT['á'] = "a";
// remove
REPLACEMENT['-'] = "";
// expand
REPLACEMENT['æ'] = "ae";
}
public String convertWord(String word) {
StringBuilder sb = new StringBuilder(word.length());
for(int i=0;i<word.length();i++)
sb.append(REPLACEMENT[word.charAt(i)]);
return sb.toString();
}
My suggestion would be:
Convert the String to a char[] array
Run through the array, testing each character one by one (e.g. with a switch statement) and replacing it if needed
Convert the char[] array back to a String
I think this is probably the fastest performance you will get in pure Java.
EDIT: I notice you are doing some changes that change the length of the string. In this case, the same principle applies, however you need to keep two arrays and increment both a source index and a destination index separately. You might also need to resize the destination array if you run out of target space (i.e. reallocate a larger array and arraycopy the existing destination array into it)
My implementation is based on look up table.
public static String convertWord(String str) {
char[] words = str.toCharArray();
char[] find = {'á','é','ú','ý','ð','ó','ö','æ','þ','-','.',
'/'};
String[] replace = {"a","e","u","y","d","o","o","ae","th"};
StringBuilder out = new StringBuilder(str.length());
for (int i = 0; i < words.length; i++) {
boolean matchFailed = true;
for(int w = 0; w < find.length; w++) {
if(words[i] == find[w]) {
if(w < replace.length) {
out.append(replace[w]);
}
matchFailed = false;
break;
}
}
if(matchFailed) out.append(words[i]);
}
return out.toString();
}
My first choice would be to use a StringBuilder because you need to remove some chars from the string.
Second choice would be to iterate throw the array of chars and add the treated char to another array of the inicial size of the string. Then you would need to copy the array to trim the possible unused positions.
After that, I would make some performance tests to see witch one is better.
I doubt, that you can speed up the 'character replacement' at all really. As for the case of regular expression replacement, you may compile the regexs beforehand
Use the function String.replaceAll.
Nice article similar with what you want: link
Any time we have problems like this we use regular expressions are they are by far the fastest way to deal with what you are trying to do.
Have you already tried regular expressions?
What i see being inefficient is that you are gonna check again characters that have already been replaced, which is useless.
I would get the charArray of the String instance, iterate over it, and for each character spam a series of if-else like this:
char[] array = word.toCharArray();
for(int i=0; i<array.length; ++i){
char currentChar = array[i];
if(currentChar.equals('é'))
array[i] = 'e';
else if(currentChar.equals('ö'))
array[i] = 'o';
else if(//...
}
I just implemented this utility class that replaces a char or a group of chars of a String. It is equivalent to bash tr and perl tr///, aka, transliterate. I hope it helps someone!
package your.package.name;
/**
* Utility class that replaces chars of a String, aka, transliterate.
*
* It's equivalent to bash 'tr' and perl 'tr///'.
*
*/
public class ReplaceChars {
public static String replace(String string, String from, String to) {
return new String(replace(string.toCharArray(), from.toCharArray(), to.toCharArray()));
}
public static char[] replace(char[] chars, char[] from, char[] to) {
char[] output = chars.clone();
for (int i = 0; i < output.length; i++) {
for (int j = 0; j < from.length; j++) {
if (output[i] == from[j]) {
output[i] = to[j];
break;
}
}
}
return output;
}
/**
* For tests!
*/
public static void main(String[] args) {
// Example from: https://en.wikipedia.org/wiki/Caesar_cipher
String string = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG";
String from = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String to = "XYZABCDEFGHIJKLMNOPQRSTUVW";
System.out.println();
System.out.println("Cesar cypher: " + string);
System.out.println("Result: " + ReplaceChars.replace(string, from, to));
}
}
This is the output:
Cesar cypher: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
Result: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD