Given a String "Hello" in C, how would a method look that returns the "H" in the String.
Then once I've determined how to do that, I'd like to take it a step further and remove the first character from the initial String so that the next time that I read it "Hello" becomes "ello", and when I call the read method again it will return the "e"?
I know how to do this in other languages, like Java but I'm not as proficient in C so I'm really struggling with this concept.
Here's how I would do this in java.
public class Program1 {
private String expression = "-(1+3)*4/6";
public String cut_string(String word)
{
String temp = word.substring(1, word.length());
return temp;
}
public char readToken()
{
if(expression.length() > 1)
{
char token = expression.charAt(0);
expression = cut_string(expression);
return token;
}else {
System.out.print("BROKEN AT READ TOKEN");
return ' ';
}
}
public String getExpression()
{
return expression;
}
public static void main(String [] args)
{
Program1 thing = new Program1();
System.out.println("The token was: " + thing.readToken()
+ "\n" + "The remaining String is: "
+ thing.getExpression());
System.out.println("The token was: " + thing.readToken()
+ "\n" + "The remaining String is: "
+ thing.getExpression());
System.out.println("The token was: " + thing.readToken()
+ "\n" + "The remaining String is: "
+ thing.getExpression());
}
}
The output would be as follows:
The token was: -
The remaining String is: (1+3)*4/6
The token was: (
The remaining String is: 1+3)*4/6
The token was: 1
The remaining String is: +3)*4/6
Coming from Java, you should bear in mind that a "string" in the Java sense is not a native concept to C. In C, you deal explicitly with arrays of characters instead of more abstract data types (unless you build them yourself). Think of them as similar to a char[] in Java.
Returning the first character of a string, then, is simply the same as returning the first element of the array that is the string:
char first_character(char *string) {
return(string[0]);
}
Changing the program's state, on the other hand, to "remove" the first character of the string, may be completely superfluous in C, depending on how you want to do it. You do, of course, have the option of actually modifying the string by moving all elements back one position, for instance like this:
void remove_first_char(char *string) {
int i;
for(i = 0; string[i] != 0; i++)
string[i] = string[i + 1];
}
(Note, however, that string literals are often allocated in read-only memory and cannot be modified.)
But, depending on your context, you could also quite simply modify the pointer that you might be using to just point to the second character instead.
I'd prefer to avoid global variables (especially in a case like this where it's being modified), but since you seem willing to put up with that, it can be pretty trivial:
char expr[] = "-(1+3)*4/6";
char *expression = expr;
char read_token() {
return *expression++;
}
int main() {
char ch;
while (ch=read_token()) {
printf("next token: %c\n", ch);
printf("The remaining string is: %s\n", expression);
}
}
To encapsulate things a little better, I'd consider something more like this though:
#include <stdio.h>
typedef struct {
char *expression;
} program1;
char read_token(program1 *p) {
return *p->expression++;
}
int main() {
program1 p = { "-(1+3)*4/6" };
char ch;
while (ch = read_token(&p)) {
printf("next token: %c\n", ch);
printf("The remaining string is: %s\n", p.expression);
}
}
At least in my opinion, avoiding globals (among other things) more than makes up for the extra length.
In C, strings are stored as an array of characters.
char myStr[] = "String";
You can access any character by using an array index
char myChar = myStr[0];
printf("%c\n", myChar);
Related
A class words defines a recursive function to perform string related operations. The class details
are given below:
Class name : words
Data members/instance variables
text : to store string.
w : integer variable to store total words.
Member functions/methods
words( ) : constructor to store blank to string and 0 to integer data.
void Accept( ) : to read a sentence in text. Note that the sentence may contain more
than one blank space between words.
int FindWords(int) : to count total number of words present in text using Recursive
Technique and store in ‘w’ and return.
void Result( ) : to display the original string. Print total number of words stored in
‘w’ by invoking the recursive function.
I tried this code
public static int CountWords(String str) {
int c = 0;
int i = str.indexOf(" ");
if (str.isEmpty()) {
return 0;
}else
if (i == str.indexOf(" ")) {
return c++;
}
//str.substring(0,str.indexOf(" ")-1);
c++;
return c + CountWords(str.substring(i + 1));
}
but i need to return an integer value and i am confused with that..
In your code, the last return statement is inaccessible. Reason: you have put an if-else block and have put return in both the cases. So the function actually gets returned from the if-else block itself (within else, the condition of if is always true since you assigned the very value i.e. str.indexOf(" ")).
I have written down the code according to the question you gave above...
public int findWords(int i){
if(i > text.lastIndexOf(" "))
return 1;
i = text.substring(i).indexOf(" ") + i;
if(i < 0)
return 1;
if(text.substring(i).equals(null))
return 0;
return( findWords(i+1) + 1);
}
Hope you find it well working.
Your function already is returning a integer, it just happens to always be 0.
This is due to
else if (i == str.indexOf(" ")) {
return c++;
}
Always being true and c++ only updating after the return statement was passed.
This happens because you already set i to be the indexOf(" ") and due to the implementation of incrementation using int++. Also, keep in mind hat you need to increase the number of words by 2 here, since you're ending the function between two words.
Therefore, use this instead:
else if (i == str.lastIndexOf(" ")) {
return c+2;
}
You should see that now the function is returning the correct amount of words.
Whenever I run my code it returns this error message:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 5
at java.lang.String.charAt(Unknown Source)
at codes.Main.main(Main.java:10)
Here is my code:
package codes;
public class Main {
public static void main(String[] args) {
String cord1 = "Name: x=23 y=60 z= 600";
String cord2 = "Name: x=200 y=20 z= 300";
int c1 = cord1.length();
String mychar = String.valueOf("cord1".charAt(0));
for (int a = 0; a < c1; a++){
mychar = String.valueOf("cord1".charAt(a));
if (mychar == ":"){
break;
}else{
cord1.substring(a);
}
}
}
}
There are multiple things wrong in your code..
mychar == ":" should be mychar.equals(":") instead. Since Strings are immutable, we need to use the .equals to compare them instead of == (<- this checks if the references are equal instead of the String-values).
"cord1".charAt should be your variable cord1.charAt.. By using "cord1" you basically create a new String with the value cord1.
cord1.substring(a); doesn't change the cord1 value, but returns a new String. So you'll have to save this String result, or print it, and then stop the loop with a break.
Using cord1 = cord1.substring(a) would shorten the String itself. Since you still loop in the range [0, c1) where c1 was the original String, we would still get a StringIndexOutOfBoundsException. Instead, you don't need the else-case and need both the cord1 = cord1.substring(a) and break inside the if-case. (Also, I assume you want to remove the : itself as well, so you'll have to use .substring(a+1) instead.)
Also, why use String.valueOf( char ) instead of just using the char themselves? Not really a requirement, but the String.valueOf is kinda redundant here, and makes the code less readable.
Putting it all together:
public class Main {
public static void main(String[] args) {
String cord1 = "Name: x=23 y=60 z= 600";
System.out.println("cord1 before:\t" + cord1);
int c1 = cord1.length();
char mychar = cord1.charAt(0);
for (int a = 0; a < c1; a++){
mychar = cord1.charAt(a);
if (mychar == ':'){
cord1 = cord1.substring(a+1);
break;
}
}
System.out.println("cord1 after:\t" + cord1);
}
}
Which will result in cord1 having the value " x=23 y=60 z= 600" (note the leading space) in the end.
Try it online.
Here is a much simpler alternative with the same result:
String cord1 = "Name: x=23 y=60 z= 600";
String cord1ExcludingName = cord1.replaceFirst("^.*:","");
Try it online.
^ : Only look at the start of the String for:
.* : Zero or more of any character,
: : followed by a `:`
Which will be replaced with "" (an empty String), so they're basically removed.
Use equals instead of "=="
Like this
if (mychar.equals(":")){
break;
You need to use equals method because you are working with a string. Whenever you work with string u must compare them with the method equals.
If you used
char myChar = .....
Your code would work. You can compare chars with "=="
String.valueOf("cord1".charAt(0)) means you are looking into the 0th character of string "cord1" which has a highest index of 4, that is why it is giving out of bound exception at 5.
What you have to do is String.valueof(cord1.charAt(0)). This will consider the string in the variable cord1.
My goal is to return a string that is made up of characters that are 1 before and 1 after each character in the given string in the ASCII table.
For example, dog should return cenpfh.
public String encrypt(String s) {
if (s.length() == 1) {
String one = "";
one += (s.charAt(0)-1) + (s.charAt(0)+1);
return one;
} else { .. }
}
This is the code I have so far, and I have no idea how to continue. This doesn't even work for a single character, for example, "172" is returned for "V". Could anyone point me in the right direction? Really stumped right now.
If you have to use recursion, you can try something like that:
public static String encrypt(final String s) {
if (s.length() == 1) {
final char c = s.charAt(0);
return new String(new char[] {(char) (c - 1), (char) (c + 1)});
} else {
return encrypt(s.substring(0, 1)) + encrypt(s.substring(1));
}
}
the main idea here:
if input length is 1 symbol - we know what to do and just perform "encryption"
if input length is more than 1 symbol - we split string into "first symbol" and "rest of the string" and call itself on both parts
This is fairly tricky stuff for a beginner, but it's good stuff to encounter early and understand.
"" + 172
results in the string "172"
"" + 'V'
results in the string "V".
V and 172 are both represented internally as the same number, so what's the difference? The difference is that the compiler keeps track of the type of the value. 'V' has a type of char. 172 has a type of int.
When you perform an expression using a mixture of types, the compiler has to decide what the type of the result is. This will influence how that result is handled by routines such String concatenation.
As it happens when you subtract an int from a char, the type of the result is an int (the Java spec tells you this).
You can get around it by casting the type to something else.
(char) 172 is 'V'
(int) 'V' is 172.
So:
one += (char) (s.charAt(0)-1) + (char)(s.charAt(0)+1);
Recursion is a separate topic. Recursion works for handling sequences (a String is a sequence of characters) when you can do a chunk of work on a part of the sequence, leaving you with a new, shorter sequence, that you can do the same job on -- until finally you have the simplest case, which you simply return.
The simplest case, the one where the method returns without recursively calling itself, is called the terminating case. You need at least one terminating case, otherwise the recursive method will keep calling itself until Java runs out of memory for storing method states.
You have chosen your terminating case as being a one char string. I would instead pick a zero length string:
public void encrypt(String s) {
if("".equals(s)) {
return "";
} else {
// do something with a string that's guaranteed >1 char
}
Now you just have to work out how to replace that comment, by using up the guaranteed one char, and calling encrypt() to handle what's left.
public void encrypt(String s) {
if("".equals(s)) {
return "";
} else {
return encodeOneChar(s.charAt(0)) +
encrypt(x.substring(1));
}
}
That's it:
when called with an empty string, encode() returns an empty string.
when called with a non-empty string, encode processes the first char
and calls itself to deal with a string that's one shorter.
Some languages, like Haskell, make recursion easier to understand, by representing the cases as pattern matching statements.
encrypted "" == ""
encrypted s == encryptChar(head(s)) + encrypted(tail(s))
(that's not real Haskell, but it illustrates the pattern.)
Recursion isn't quite as easy to read in Java, but the pattern is still there. if(terminating case) { return answer for terminating case } else { calculate something, call self, return combined result }
I'll leave you to implement private String encodeOneChar(char c)
Note that recursion isn't a good solution to your actual task in Java -- except in the sense that your goal is to understand recursion.
There is no recursion needed. Just iterate over input chars and collect result in a StringBuilder:
public static String encrypt(String s) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
sb.append((char)(c - 1)).append((char)(c + 1));
}
return sb.toString();
}
Note that explicit cast to char is required here, because s.charAt(i) - 1 evaluates to int and without cast is processed by overloaded append(int i) method.
Okay, recursion. Here I split input into 2 halves and process each by using the same encryptRecursively() method, then join results. Each part, when passed to the method, is again split into 2 parts, etc, until size becomes 0 or 1 (thus we get a very simple implementation of Divide and Conquer):
public static String encryptRecursively(String s) {
if (s.isEmpty())
return "";
else if (s.length() == 1) {
char c = s.charAt(0);
return new String(new char[] { (char)(c - 1), (char)(c + 1) });
} else {
int mid = s.length() / 2;
return encryptRecursively(s.substring(0, mid)) // process first half of input
+ encryptRecursively(s.substring(mid)); // second half
}
}
You don't need a recursion but a simple for-loop through all chars in the word. You get the value of char with s.charAt(...), but you have to convert it back to char for the desired resut. Append them to StringBuilder and return its String as the output of the method:
public static String encrypt(String s) {
StringBuilder sb = new StringBuilder();
for (int i=0; i<s.length(); i++) {
char a = (char)(s.charAt(i)-1);
char b = (char)(s.charAt(i)+1);
sb.append(a).append(b);
}
return sb.toString();
}
Here is the recursion method as demanded:
public static String encrypt(String s) {
if (s.length() == 1) {
StringBuilder sb = new StringBuilder();
char a = (char)(s.charAt(0)-1);
char b = (char)(s.charAt(0)+1);
return sb.append(a).append(b).toString();
} else {
return encrypt(s.substring(0, 1)) + encrypt(s.substring(1, s.length()));
}
You can try this:
one += (char)(((int)s.charAt(0))-1);
one += (char)(((int)s.charAt(0))+1);
Input:
V
Output:
UW
I am very new to Java and as a starter I have been offered to try this at home.
Write a program that will find out number of occurences of a smaller string in a bigger string as a part of it as well as an individual word.
For example,
Bigger string = "I AM IN AMSTERDAM", smaller string = "AM".
Output: As part of string: 3, as a part of word: 1.
While I did nail the second part (as a part of word), and even had my go at the first one (searching for the word as a part of the string), I just don't seem to figure out how to crack the first part. It keeps on displaying 1 for me with the example input, where it should be 3.
I have definitely made an error- I'll be really grateful if you could point out the error and rectify it. As a request, I am curious learner- so if possible (at your will)- please provide an explanation as to why so.
import java.util.Scanner;
public class Program {
static Scanner sc = new Scanner(System.in);
static String search,searchstring;
static int n;
void input(){
System.out.println("What do you want to do?"); System.out.println("1.
Search as part of string?");
System.out.println("2. Search as part of word?");
int n = sc.nextInt();
System.out.println("Enter the main string"); searchstring =
sc.nextLine();
sc.nextLine(); //Clear buffer
System.out.println("Enter the search string"); search = sc.nextLine();
}
static int asPartOfWord(String main,String search){
int count = 0;
char c; String w = "";
for (int i = 0; i<main.length();i++){
c = main.charAt(i);
if (!(c==' ')){
w += c;
}
else {
if (w.equals(search)){
count++;
}
w = ""; // Flush old value of w
}
}
return count;
}
static int asPartOfString(String main,String search){
int count = 0;
char c; String w = ""; //Stores the word
for (int i = 0; i<main.length();i++){
c = main.charAt(i);
if (!(c==' ')){
w += c;
}
else {
if (w.length()==search.length()){
if (w.equals(search)){
count++;
}
}
w = ""; // Replace with new value, no string
}
}
return count;
}
public static void main(String[] args){
Program a = new Program();
a.input();
switch(n){
case 1: System.out.println("Total occurences: " +
asPartOfString(searchstring,search));
case 2: System.out.println("Total occurences: " +
asPartOfWord(searchstring,search));
default: System.out.println("ERROR: No valid number entered");
}
}
}
EDIT: I will be using the loop structure.
A simpler way would be to use regular expressions (that probably defeats the idea of writing it yourself, although learning regexes is a good idea because they are very powerful: as you can see the core of my code is 4 lines long in the countMatches method).
public static void main(String... args) {
String bigger = "I AM IN AMSTERDAM";
String smaller = "AM";
System.out.println("Output: As part of string: " + countMatches(bigger, smaller) +
", as a part of word: " + countMatches(bigger, "\\b" + smaller + "\\b"));
}
private static int countMatches(String in, String regex) {
Matcher m = Pattern.compile(regex).matcher(in);
int count = 0;
while (m.find()) count++;
return count;
}
How does it work?
we create a Matcher that will find a specific pattern in your string, and then iterate to find the next match until there is none left and increment a counter
the patterns themselves: "AM" will find any occurrence of AM in the string, in any position. "\\bAM\\b" will only match whole words (\\b is a word delimiter).
That may not be what you were looking for but I thought it'd be interesting to see another approach. An technically, I am using a loop :-)
Although writing your own code with lots of loops to work things out may execute faster (debatable), it's better to use the JDK if you can, because there's less code to write, less debugging and you can focus on the high-level stuff instead of the low level implementation of character iteration and comparison.
It so happens, the tools you need to solve this already exist, and although using them requires knowledge you don't have, they are elegant to the point of being a single line of code for each method.
Here's how I would solve it:
static int asPartOfString(String main,String search){
return main.split(search, -1).length - 1;
}
static int asPartOfWord(String main,String search){
return main.split("\\b" + search + "\\b", -1).length - 1
}
See live demo of this code running with your sample input, which (probably deliberately) contains an edge case (see below).
Performance? Probably a few microseconds - fast enough. But the real benefit is there is so little code that it's completely clear what's going on, and almost nothing to get wrong or that needs debugging.
The stuff you need to know to use this solution:
regex term for "word boundary" is \b
split() takes a regex as its search term
the 2nd parameter of split() controls behaviour at the end of the string: a negative number means "retain blanks at end of split", which handle the edge case of the main string ending with the smaller string. Without the -1, a call to split would throw away the trailing blank in this edge case.
You could use Regular Expressions, try ".*<target string>.*" (Replace target string with what you are searching for.
Have a look at the Java Doc for "Patterns & Regular Expressions"
To search for the occurrences in a string this could be helpful.
Matcher matcher = Pattern.compile(".*AM.*").matcher("I AM IN AMSTERDAM")
int count = 0;
while (matcher.find()) {
count++;
}
Here's an alternative (and much shorter) way to get it to work using Pattern and Matcher,or more commonly known as regex.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CountOccurances {
public static void main(String[] args) {
String main = "I AM IN AMSTERDAM";
String search = "AM";
System.out.printf("As part of string: %d%n",
asPartOfString(main, search));
System.out.printf("As part of word: %d%n",
asPartOfWord(main, search));
}
private static int asPartOfString(String main, String search) {
Matcher m = Pattern.compile(search).matcher(main);
int count = 0;
while (m.find()) {
count++;
}
return count;
}
private static int asPartOfWord(String main, String search) {
// \b - A word boundary
return asPartOfString(main, "\\b" + search + "\\b");
}
}
Output:
As part of string: 3
As part of word: 1
For the first part of your Exercise this should work:
static int asPartOfWord(String main, String search) {
int count = 0;
while(main.length() >= search.length()) { // while String main is at least as long as String search
if (main.substring(0,search.length()).equals(search)) { // if String main from index 0 until exclusively search.length() equals the String search, count is incremented;
count++;
}
main = main.substring(1); // String main is shortened by cutting off the first character
}
return count;
You may think about the way you name variables:
static String search,searchstring;
static int n;
While search and searchstring will tell us what is meant, you should write the first word in lower case, every word that follows should be written with the first letter in upper case. This improves readability.
static int n won't give you much of a clue what it is used for if you read your code again after a few days, you might use something more meaningful here.
static String search, searchString;
static int command;
Was just wondering if I was using nested if statements to much. I've been looking around and it seems that people try to not use them. Also does the code look messy in any way? Anyways here it is:
import java.util.Arrays;
public class Main {
private String user_input = "";
private int max_score = 6;
private int sum;
private void check_scores(String scores){
user_input = scores;
String[] temp;
// Check if user_input is valid
// ^ Match with beginning of line | [0-9] Allow 0-9 | , Allow comma | + Match one or more | $ Match End of line
if (user_input.matches("^[0-9,]+$")) {
// Check if string starts with an ,
if(user_input.charAt(0) == ',') {
// If it does parse and substring to remove them
// otherwise the following regex leaves one behind
int i = 0;
while (!Character.isDigit(user_input.charAt(i))) i++;
int j = user_input.length();
user_input = user_input.substring(i,j);
}
// (.) Match any character) | \1 If it is followed by itself | + Match one or more | $1 replace by the first captured char.
user_input = user_input.replaceAll("(.)\\1+", "$1");
System.out.println(user_input);
// Split at the ',' and put each number in it's own cell in the array
temp = user_input.split(",");
System.out.println(Arrays.toString(temp));
// Check if temp is equal to max_scores
if (temp.length == max_score){
int[] ui_array = new int[temp.length];
// Parse String[] into int[]
for (int i = 0; i < temp.length; i++){
try {
ui_array[i] = Integer.parseInt(temp[i]);
} catch (NumberFormatException nfe) {}; // If triple checking isn't enough...
}
System.out.println("temp array(String): " + Arrays.toString(temp));
System.out.println("ui_array(int): " + Arrays.toString(ui_array));
// Add up all elements in ui_array
for (int j = 0 ; j < ui_array.length; j++) {
sum += ui_array[j];
}
System.out.println("Scores sum:" + sum + " Number of scores:" + ui_array.length + " Number of ends:" + ui_array.length/6);
}
else {
System.out.println("You have " + temp.length + " scores. Acceptable amount is " + max_score);
}
}
else {
System.out.println("Invalid Input. (Only #'s and ,'s allowed)");
}
}
public static void main(String[] args) {
Main main = new Main();
main.check_scores("1,M,7,10,,4,8,");
main.check_scores("1,6,7,10,,4,8,,,,,,,1,2,6,10,2,10");
main.check_scores(",,,,,,,1,2,6,10,2,10");
main.check_scores("10,2,1,5,7,1");
main.check_scores("6,2, ,,5,6,1");
}
}
I have just been wondering for a while what people think about how I go about doing things.
A few things I would note:
Personally, I think something like
public void method()
{
}
Is much more readable than
public void method() {
}
Particularly when you have methods that contain other structures. I'm sure some may not mind either, but I've never heard of someone saying the first isn't readable, while plenty have complained about the second. Sorry about the first one not being formatted correctly, but SO would not allow it.. it seems the site admins disagree with me on this one.
It is a standard to name variables such as someVariableName rather than some_variable_name. The first word should be lower case, all others capital, and they should be contiguous. The same is true for methods.
In your check_scores(String) method you have user_input = scores;, yet with your implementation there is no need for a global variable or to assign the passed variable elsewhere, so this is a waste of memory. Actually, since none of your class variables are used outside of the scope of this method, you should probably declare all of them inside the method.
I understand that this is a trivial example, but to go with the idea of object oriented programming, your Main class should probably be in a separate file and be run by creating an object in your main method in a driver class instead.
Also, as you mentioned, nesting several statements, when not necessary, can be sloppy since it will quickly become hard to read and follow.