ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
(NOTE: This is not a homework question - I'm not even in school!)
I'm writing a program in Lisp that takes a string of commands from the user and interprets them. Here's the problem: I would like to break up the string, and store each portion into a list. What separates each element in the string is a whitespace (of course). I've taken several approaches to try and get my desired result, but to no avail.
Method #1:
Scan through the string, and collect all letters from the beginning of the string to the first whitespace, store the characters, and replace them in the main string, with null characters.
This falls apart after the first whitespace. Because the null characters, although they don't display, are still taking up space in the string. So, all I would see is " yadda yadda yadda". That space you see isn't the first element of the string. There are 5 #\null characters that are taking the place of the first "yadda" - assuming there were 4 yadda's passed.
Method #2:
Instead of dealing with a string, deal with the individual characters.
Code:
(let ((command (prompt "> ")) ;Prompt for the command
(cmd (loop for c across command collecting c)) ;Break up the command char by char
(buf nil) ;buffer variable
(cmdbuf nil)) ;command buffer variable
(dotimes (i (length cmd)) ;iterate as many times as the length of the cmd list of chars
(if (not (eql (elt cmd i) #\Space)) ;if the current list element isn't whitespace
(push (elt cmd i) buf)) ;add it to the buffer variable
(if (eql (elt cmd i) #\Space) ;if the current element IS a whitespace
#'(lambda ()
(nreverse buf) ;reverse the elements in the list (because push adds a new element to the front of the list
(push buf cmdbuf) ;push the reversed buffer variable to the command buffer variable
(setf buf nil))))) ;null out the buffer variable
This just gives me complete jibberish stored in a list.
I don't know what else I could try.
EDIT: Even if you don't know Lisp, could you possibly suggest some other algorithm I could try?
Scan through the string, and collect all letters from the beginning of the string to the first whitespace, store the characters, and replace them in the main string, with null characters.
Destroying data structures makes me sad. I used recursion instead.
Yeah, kind of a crappy way to do it, I know. I was going to rewrite it into one elegant function, but I also wanted to answer you quickly. The problem is that HELPER needs whitespace at the beginning of the string to parse it correctly, so SPLIT-BY-SPACE will add it where necessary. Also, SPLIT-BY-SPACE will take care to remove any extra empty strings (caused by multiple continuous occurrences of spaces in the string) that may occur in the resulting list.
EDIT: Fix type error in (> start 0) when sending SPLIT-BY-SPACE an empty string.
Last edited by taylor_venable; 12-15-2006 at 03:58 PM.
Reason: Bug fix in code.
Thanks alot for the reply, taylor_venable.
I wasn't expecting anyone to reply, let alone with an actual code example. When I get home (from work), I'll definitely give the code a shot, and see if I can roll it all into one nice function.
I'll post the results tomorrow.
I haven't had a chance to try that code out yet, but I'm definitely going to send props out to both of you in the documentation for this project of mine, and I'll more than certainly post my results when I finally get a chance to try the code out.
The project I'm working on is - probably "stupid" or has already been done, but I consider it worth my time nonetheless - a shell for dynamic networking configuration. I call it Wish (Wireless Shell). It's pretty much been a project that I'm doing for my friend (and as a good excuse to flex my Lisp muscle) who had ALOT of problems keeping his wireless settings active (they'd be released and reset upon every suspend/halt/reboot). Pretty much, the shell takes up one of the TTYs (I'm aiming for TTY6), and it just sits there waiting for commands. It allows you to modify networking settings on the fly, and will re-update your connections with a magical command. Mainly, the big plus I can see for it, is modifying network settings on the fly, through a simple interface, with simple command structures (thus the reason why I need to parse strings).
String-parsing is definitely one of those exercises that will consume every ounce of programmer creativity that you throw at it. This despite the fact that the total amount of time that the hardware spends doing it is less than a few microseconds even on a very bad day.
"If it works, FISI." (FISI = " It, Ship It")
(Hey, the fact that you succeeded in doing string-parsing in Lisp at all oughta win you some kind of prize... )
tuxdev:
Thanks for that.
I can't help but think that I've heard "netsh" thrown around somewhere before. But, I definitely like the sound of "nesh." All else fails, I'll take a Ukrainian word for something, and anglicize it.
sundialsvcs:
hahahahahahaha. I don't get, why Lisp, of all languages, has such poor string-parsing. What I did for the previous algorithms I tried, was take some of my old QBASIC string parsers (from high school programming class), and translate them to Lisp (with some modifications).
taylor_venable:
Again, thank you very much for the code, and taking the time to write aforementioned code. I have one more thing to ask of you, if you could explain some of your code to me. I've only been doing Lisp for about 2 months, so I'm still a little hazy on the logical structures. I get lost from "(if end " down.
I've been out for a couple days and not looked over this in about a week, so I apologize for the delayed response. But I've now found some bugs in the code I originally provided, so I rewrote it to work a lot better. First let me try to answer your question, though, and explain how it works.
The function builds the list of parsed strings recursively from the end back to the beginning. The (if end ...) part looks to find if we've found another space ahead. If so, we know there are possibly other strings ahead to be parsed out, and we CONS the string we just found (SUBSEQ gives you a subset of a sequence -- in this case we use start and end to extract the string) onto the result of parsing the rest of the input. If there aren't any more spaces ahead, we presume that we've arrived at the last string, which we use to form a brand new list, and return it. (As this list is returned from the recursion, previous strings get added to the beginning, eventually forming the entire list of parsed strings.)
Unfortunately, these functions have some bugs. One is that it fails (throws an error) when passed the null string; I think it should return NIL instead. Another is that it stores up unnecessary null strings in the list when multiple spaces occur side-by-side in the input string; these must be removed later, which is inefficient. So to that end, I tried to write a clearer, less buggy version. This uses two mutually-recursive functions -- one to handle the start of a parsed string, and one to handle the end of a parsed string. There is no initial setup required and no cleanup to do afterwards, which is what was necessary in the previous code I wrote. So without further ado, here it is:
It's a bit longer, but should be a little easier to understand. It's still limited to using the space as the delimiter, but you could fix that pretty easily by extending the function to accept a string of possible delimiters instead. Then you've basically got the Lisp version of strtok and StringTokenizer! Anyway, I've got some preliminary code that'll handle that; I'll post it back here if you like.
By the way, you need to invoke SPLIT-BY-SPACE here. Here's some examples:
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.