Shop OBEX P1 Docs P2 Docs Learn Events
extract number from string buffer — Parallax Forums

extract number from string buffer

phishguyphishguy Posts: 36
edited 2009-09-03 14:45 in Propeller 1
I just started using the propeller a week ago and I think it's great. I have written a program that will capture text from a serial port and log it to a sd card file. I create the file name with a format of DFLG0001.txt. I would like to be able to extract the numeric part of that string into a variable from the buffer when I do a nextfile. That way I can find the largest number used and increment the variable for the next created file. However, being quite new at spin code,·I can't figure out how to do this. Any examples for doing this would be greatly appreciated.
·

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2009-09-02 15:22
    Look at the rxDec routine in this object: obex.parallax.com/objects/31/ and at the dec routine in the FullDuplexSerial object that comes with the Propeller Tool. Although these take their input from a serial port or send their output to a serial port, the same routines with minimal modification can do the same things with characters from a string.
  • Agent420Agent420 Posts: 439
    edited 2009-09-02 15:43
    One of the things I miss most about BASIC in comparison to languages like C and Spin is it's easy to use string handling features like VAL(MID(filename$,5,4)).·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • phishguyphishguy Posts: 36
    edited 2009-09-02 16:17
    @mike
    Thanks for pointing me in the right direction. I was able to adapt the getdec routine for my purpose.
    Because I am a beginner, I was wondering if anyone could critique my code and let me know if I'm doing anything wrong or if I should be doing things in a different or better way.
    '
    CON
            _clkmode        = xtal1 + pll16x
            _xinfreq        = 5_000_000
            
      
    obj
       text : "vga_text"  
       sd: "fsrw"
       Debug: "FullDuplexSerial" 
       fmt: "format.spin"
    
    var
       byte tbuf[noparse][[/noparse]20]
       byte nbuf[noparse][[/noparse]12]
       Byte datain[noparse][[/noparse]16]
      long lastnum
       long Num  
    pub start | r, sta, bytes  ,rxbyte
        text.start(16) 
       Debug.start(5, 4, 0, 9600) 
           dira[noparse][[/noparse]7] := 0        
       text.str(string("Mounting.", 13))        
       sd.mount(0)
       text.str(string("Mounted.", 13))
       text.str(string("Dir: ", 13))
       sd.opendir
       
       repeat while 0 == sd.nextfile(@tbuf)
          text.str(@tbuf)
          num := getdec
          if num > lastnum
           lastnum := num
          text.str(string(13))
       lastnum += 1  
       text.str(string(">>> Above is the Directory",13 ,13))
       r := 0
       fmt.sprintf(@nbuf,string("DFLG%04d.txt"),lastnum)
        
       
      r := sd.popen(@nbuf, "w")
       text.str(string("Opening returned ",13))
       text.dec(r)
       text.out(13)
       text.out(13)
        
       sta := cnt
       bytes := 0
       
       num:=0 ' set variable to 0
       
       repeat while not ina[noparse][[/noparse]7]    ' button to end logging
         rxbyte:= debug.rxcheck   ' receive character
         if rxbyte <> -1
           num := 1               ' flag for data in file
           sd.pputc(rxbyte)       ' store character to file
           if rxbyte <> 10        ' strip line feed
             text.out(rxbyte)     ' display character
       'delete empty file      
       if num == 0
         sd.pputc(33) 'test
         r := sd.popen(@nbuf, "d") ' delete file
       
       '----------------------------------------
       text.str(string("File closed",13)) 
       sd.pclose
       '----------------------------------------
    PUB getDec : Value | place, ptr, x
    {{
       Accepts decimal values, such as "1234" as a number.
        
       x:= getdec     ' accept string of digits for value
    }}   
        place := 1                                           
        ptr := 5
        value :=0                                             
       ' dataIn[noparse][[/noparse]ptr] := tbuf[noparse][[/noparse]ptr]       
        'ptr++
        repeat 4                    
           dataIn[noparse][[/noparse]ptr] := tbuf[noparse][[/noparse]ptr]                             
           ptr++
        if ptr > 2 
          repeat x from (ptr-2) to 1                            
            if (dataIn[noparse][[/noparse]x] => ("0")) and (datain[noparse][[/noparse]x] =< ("9"))
              value := value + ((DataIn[noparse][[/noparse]x]-"0") * place)       
              place := place * 10                               
        if (dataIn[noparse][[/noparse]0] => ("0")) and (datain[noparse][[/noparse]0] =< ("9")) 
          value := value + (DataIn[noparse][[/noparse]0]-48) * place
        elseif dataIn[noparse][[/noparse]0] == "-"                                  
             value := value * -1
        elseif dataIn[noparse][[/noparse]0] == "+"                               
             value := value 
        
        
      
    
    
  • LeonLeon Posts: 7,620
    edited 2009-09-02 16:18
    It's easy to write a function for that sort of thing, though.

    Leon

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Amateur radio callsign: G1HSM
    Suzuki SV1000S motorcycle
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-09-02 22:52
    Are you just looking to parse the numeric section of that name? If so, the SubStr method in this object: obex.parallax.com/objects/502/ will do the trick. I also like plugging my new objects smilewinkgrin.gif !
    If you need a decimal value of the numeric string, then you may need to use the Simple Numbers object (included with the Propeller Tool). Or possibly a combination of the two is a simple/surer way to do what you are trying to do.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!
  • phishguyphishguy Posts: 36
    edited 2009-09-02 23:44
    Thanks for the advice. But, I was able to do what I needed as you can see in my above code. My serial data logs to a SD card now and I have automatic filename increment on each power up. It works quite well and my serial communication is via a Bluetooth module. So, I can now remotely log my data. I still wouldn't mind any critique of my code.
  • mparkmpark Posts: 1,305
    edited 2009-09-03 14:45
    Welcome to the wonderful world of the Propeller!

    Your code apparently does what you want it to, so that's the most important thing, but I have a few questions/comments about getDec.

    First, why do you bother copying from tbuf to DataIn?

    Second, you copy values into DataIn[noparse][[/noparse] 5]..DataIn[noparse][[/noparse]8], but then you look at DataIn[noparse][[/noparse]7]..DataIn[noparse][[/noparse]0]. DataIn[noparse][[/noparse]8] is unnecessary and DataIn[noparse][[/noparse]0..4] are unassigned.

    The "if ptr > 2" test is unnecessary, since ptr will always be 9.

    Assignments such as "value := value + something" or "place := place * 10" can be written "value += something" and "place *= 10". Saves typing, saves reading, and generates more compact code.

    Also, you could change "value := value * -1" to just "-value".
    And "value :=value" does nothing but waste time and memory. You could just drop the whole "elseif Datain[noparse][[/noparse]0] == '+'" thing.
    Are you really expecting negative numbers?
Sign In or Register to comment.