Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Rodimus Prime

macrumors G4
Original poster
I have been coding a project for class am on one small part of the project that I can not figure out how to do.

The problem I am having is trying to figure out how to take string and pull numbers out of it and skip the other chars.
For example the user would enter "5 - 20"
I would take that and have pull out an int 5 and and int 20.

I just can not figure how to do it. If it was just one number it would be easy but pulling 2 different numbers out of the string is what is killing me.

Any help would be great.
 
Java has some pretty strong string processing abilities in its standard library (not sure which version they came in though) a quick browse of the Javadocs for Java 6 should highlight the specific classes you'll want.
 
Reading a line of text from left to right. What are the possible cases you might encounter? Think of this as a state machine
 
If one number is easy, then I assume you're using a Scanner object to do it. If so look into the methods
nextInt
hasNextInt
skip
 
This is a "class project" so I think the method of deconstruction the input into a number of states is the point. While there are many useful APIs that could help, I don't think that would be the point of the lesson.

Here are some more hints about the states:
s0 -> first char is a non-number
s1 -> first char is a number
s2 -> previous char is a number, current char is a non-number
s3 -> previous char is a number, current char is a number

Constructing a state machine via switch statements may be the point of the exercise. I would wager that the next exercise would be to take this and do it via regex.
 
a way to do it in C

I haven't meant to write our friend's program. My function is in C, not in Java, and that function isn't object-oriented.
Code:
/* Create a list of any integers you find in the text. */

static int get_integers_from(const char text[], int integers[], const int list_capacity)
{
  register int how_many = 0, next_integer;

  while (sscanf(text, "%d", &next_integer) == 1 && how_many < list_capacity)
    integers[how_many++] = next_integer;
  return how_many;
}
 
Bill,

While the syntax for C and Java are similar the APIs are a bit different. In particular there is no direct equivalent to scanf/printf; but those functions are also discouraged in cpp and for good reason.

Also, I would encourage you to review that alarmingly dangerous snippet of code you presented. I'm sure there are some implied safeguards but our impressionable friends being novice programmers may not realize that.
 
Thanks for the warning, mrbash. I shouldn't have posted that snippet, partly because I hardly know C. What's frighteningly dangerous about the function I thought up while I wrote its post? I certainly don't want to teach our friends any bad programming-techniques. I didn't know that I wrote dangerous code.

Anyhow your comment about my alarmingly dangerous snippet reminds that whatever is dangerous about my function, C's permissiveness is probably partly to blame for the danger.

Let me try to explain my function a little. Sscanf reads numbers, strings, characters, and maybe even data of other types, from strings. I compare sscanf's value to one because when that value is one, that means that the computer has just read one integer from the string. If that function's value is not one, and if no runtime error has occurred, a function value other than one should mean that the computer can't find any, or perhaps any more, integers in the string.

I don't know C++, and I haven't learned Java. Nowadays, I do functional programming.

Bill
Also, I would encourage you to review that alarmingly dangerous snippet of code you presented. I'm sure there are some implied safeguards but our impressionable friends being novice programmers may not realize that.
 
I won't code it for you, but here's a way of thinking about your problem that might help. 🙂

1. Create temporary strings called result_1 and result_2 to store your results.

2. Read the input string character by character.

3. If the current character is a number, append it to result_1.

Otherwise, if the current character is non-numeric, do nothing and read the next character.

4. After dealing with the non-numeric characters in the middle of the input string, if the next character is a number, append it to result_2. Continue until there are no characters left.

5. Convert result_1 and result_2 from strings to integers.

Tip:
Use the parseInt method from the Integer class to turn Strings into integers.
Example:
Code:
String someString = "23";
int result = Integer.parseInt(someString);
System.out.println(result);    // will print 23.
If someString is not a number, parseInt will throw a NumberFormatException, which is probably out of the scope of your assignment, but, give us an update on how you're doing.
 
The OP will probably be best served with an explanation of a solution rather than code that they can cut/paste.

What's frighteningly dangerous about the function I thought up while I wrote its post?

The array you provide as a parameter is assumed to be allocated before hand, but no check is made to ensure that it is. Further, there is no indication of the size of the array that you presume to be allocated. This is very much playing Russian Roulette.

While you could provide an implementation like:
(let ((inputstr (read)))
(def integerlist '())
(let ((pos 1))
(loop
(when (> pos (length inputstr) )
(multiple-value-setq (integer pos) (parse-integer inputstr :start pos :junk-allowed t) )
(push integer integerlist)
)
)
)
integerlist
)

He may be better served with an explanation of how a function like the one below could be used to construct a list of integers:
(parse-integer inputstring :start 0 :junk-allowed t)

That whole "give a man a fish" VS "teach a man to fish" thing.
 
I'm sorry I wrote the function. In fact, I'm not even sure why I wrote it. Since our friend is programming in Java, a language that doesn't have a sscanf function, my code probably wouldn't have helped, even if it were safe.

My only excuse for assuming that the parameter's memory is already allocated is that, in some C books I've read, authors have assumed the same thing in some functions they wrote in those books. They used the array notation instead of pointer notation because they thought array notation more readable than pointer notation. I should replace the array notation with pointer notation and check whether the computer has allocated memory for the array. But again, I merely imitated what some authors wrote.

I wasn't trying to do anyone's else's homework for him.



mrbash10279476 said:
The array you provide as a parameter is assumed to be allocated before hand, but no check is made to ensure that it is. Further, there is no indication of the size of the array that you presume to be allocated. This is very much playing Russian Roulette.

mrbash10279476 said:
He may be better served with an explanation of how a function like the one below could be used to construct a list of integers:

I'll write another code fragment, partly because it doesn't extract integers from a string. To create a list of integers that come from another list that may or may not contain any integer, in Scheme, I would write something like this:

Code:
(define (integers-from this-list)
         (filter integer? this-list))

Scheme's memory management is automatic. So this Scheme function isn't dangerous.
 
Take a look at the class java.io.StreamTokenizer

Tell you truth I end up doing something like that.

I first had it replace the '-' with a " " then I used the tokenizer. I put the space in there to make sure it had a break point. Fro
There I used a loop and a had a try catch function to check to see if it was a integer.
I know what I did was more of a brute force method so I would meet the requirements of the project but it still felt very messy to me.

Not my favorite way of doing things and I personly feel it is bad pratice to do thing that way but I was out of time so I went that way.

I have to say thank you all for the help and pointing me in the right direction.
 
Tell you truth I end up doing something like that.

I first had it replace the '-' with a " " then I used the tokenizer. I put the space in there to make sure it had a break point. Fro
There I used a loop and a had a try catch function to check to see if it was a integer.
I know what I did was more of a brute force method so I would meet the requirements of the project but it still felt very messy to me.

Not my favorite way of doing things and I personly feel it is bad pratice to do thing that way but I was out of time so I went that way.

I have to say thank you all for the help and pointing me in the right direction.

You could have created a StringTokenizer where the delimiters contained '-' and space. That would be a little simpler because you wouldn't need to call replace().

A try/catch is a perfectly good way to catch errors. That's what it's for.

If you want additional comments on your code, you'll have to post it.
 
You could have created a StringTokenizer where the delimiters contained '-' and space. That would be a little simpler because you wouldn't need to call replace().

A try/catch is a perfectly good way to catch errors. That's what it's for.

If you want additional comments on your code, you'll have to post it.

I was and still am my iPod touch and do not have direct access to my code. That delimited sounds like a better way of doing it. I was reading the API and they are saying that something like split should of been used and the tokenizer is legacy code. I mix and match examples I was finding online and modifided them to work with what I needed. The tokenizer but pointed me in the right direction to look for something that would work. Heck it gave me another used for my try catch method I had programed in for another part of my program.
I learning quickly why some bugs are left because even in my 500 lines of code I know how mich I struggled to find some of the annoying little bugs.
 
Now that the original issue is resolved, I guess there is no harm in presenting a solution.

RegEx is the way to go, as I mentioned in my original post.

Code:
System.out.println("Enter some text: ");
try{
    String input = new BufferedReader( new InputStreamReader(System.in)).readLine();

/*** LOOK HERE ******/
    String [] parts = input.split("-");
    java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\d+");
    for(String part : parts) {
        part = part.trim();
        if( p.matcher(part).matches() )
            System.out.println(part);
    }
/*** END ******/
}catch(IOException ex){
    ex.printStackTrace();
}
 
Thank you again, mrbash, for warning me about what I assumed when I wrote the C function that collected integers from a string. I can see why my code would have alarmed some programmers. But since I always like to back up what I say when I write about books I've used, here's a link to code from a book where the author declares a function's dummy array-arguments the way I declared mine. The answer's come from the book's second edition, but I used its first edition instead.

http://knking.com/books/c2/answers/c13.html

Bill
 
Thank you again, mrbash, for warning me about what I assumed when I wrote the C function that collected integers from a string. I can see why my code would have alarmed some programmers. But since I always like to back up what I say when I write about books I've used, here's a link to code from a book where the author declares a function's dummy array-arguments the way I declared mine. The answer's come from the book's second edition, but I used its first edition instead.

http://knking.com/books/c2/answers/c13.html

Bill

It's not that you used the array notation. It's that the string being parsed can contain more values than the output array has space to hold. You neglected to provide a limiting count for the size of the output array.

C's arrays are essentially unbounded on either end. Overflows and underflows do not cause detectable compile or runtime errors. They just overflow until some other damage is done, sufficient to crash the program or destroy other values. Look at the difference between lib functions strcat(), strncat(), strlcat().
 
Thank you for the excellent points, my friend. See what I get for programming mostly in languages much higher-level than C? I ignore details I should have considered. To bad I didn't remember how dangerous the gets() function can be. I'll think much more thoroughly before I write another C function.
It's not that you used the array notation. It's that the string being parsed can contain more values than the output array has space to hold. You neglected to provide a limiting count for the size of the output array.

C's arrays are essentially unbounded on either end. Overflows and underflows do not cause detectable compile or runtime errors. They just overflow until some other damage is done, sufficient to crash the program or destroy other values. Look at the difference between lib functions strcat(), strncat(), strlcat().
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.