Sign in to follow this  
Followers 0
bitshadow

to all the autoit gurus

13 posts in this topic

hi y'all.

this might not be the best alogrithm to do this and there might be a more succint way of doing this. however i have the following funciton

Func LoadFile($fp,$nums)
    ;create an array of records so we can have each number in the struct how to make it global?
    Dim $RECORD[$nums]
    
    ;what line we on
    $recordNum=0
    ;what phone digit we on
    $phoneDigit=0
    
    ;create an array of valid numbers
    Dim $VALIDNUMS[10]
    for $ndx  = 0 to 9
        $VALIDNUMS[$ndx] = $ndx
        ;MsgBox(0,"Valid Number Init ",  $VALIDNUMS[$ndx])
    Next
    
    ;create and initialize  an array of structs of recordnum size
    For $record_num = 0 to $nums-1
        $RECORD[$record_num] = doopsCreateStruct()
    Next
    
    ;copy every character from the file to a record EX: RECORD[line_num].phoneNum[digit] = num
    While 1
        ;read in 1 character at a time from the file till EOF
        $char = FileRead($fp,1)
        ;if its the EOF
        If @error = -1  Then ExitLoop
        
        ;check if number is a valid digit only put in the numbers
        For $x = 0 to 9 
            ;only add the valid digits
            If $char = $VALIDNUMS[$x] Then
             ;add the character to the phone number: read RECORD[num].phoneNumber[digit] = "number"
             DllStructSetData($RECORD[$recordNum],$phoneNum[$phoneDigit],$char)
             MsgBox(0,$VERSION,"CHARACTER INPUTED: " & $char)
             ;advance to next phone digit to check
             $phoneDigit+=1
           EndIf
        Next; check against the next number

        If @CRLF  Then
             MsgBox(0,$VERSION,$phoneNum[0])
            ;reset the phone number sequence
            $phoneNum[$phoneDigit] = 0
            ;go to the next record
            $recordNum+=1
            
        EndIf
        
        MsgBox(0,$VERSION, "ERROR: " & @error & " reading char: " &$char)
        
    WEnd
    
    
MsgBox(0,$VERSION,"DONE ALLOCATING PHONE NUMBERS TO STRUCTS")
EndFunc

it iterates through the file given as an argument and reads character by character allocating its contents to a array of structs. for some reason though i dont seem to be reading in any characters. i know its someting in my while loop. can someone tell me whats going on. thank you.

Share this post


Link to post
Share on other sites



doopsCreateStruct() function is missing.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

FileRead a file in a loop one char at a time is a horrible idea from performance, efficience, sanity and any other standpoint. Other ideas, such as checking if a char is numerical by running it through a "For $x = 0 To 9" loop and even having a special array for that, are pretty whacky too.

Forget about the question why it doesn't seem to be reading any characters, just rewrite everything from scratch, and don't forget to refer to the helpfile while doing it, you might find a lot of interesting stuff in there, such as StringIsDigit(), StringMid(), StringSplit(), StringRegExp(), and so on.

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

FileRead a file in a loop one char at a time is a horrible idea from performance, efficience, sanity and any other standpoint. Other ideas, such as checking if a char is numerical by running it through a "For $x = 0 To 9" loop and even having a special array for that, are pretty whacky too.

Forget about the question why it doesn't seem to be reading any characters, just rewrite everything from scratch, and don't forget to refer to the helpfile while doing it, you might find a lot of interesting stuff in there, such as StringIsDigit(), StringMid(), StringSplit(), StringRegExp(), and so on.

i appreciate the replies guys and i'll be sure to "refactor" when i get a chance, what i would like to know now though is the cause of the problem.

the doopsCreateStruct() seems to be working fine - at least its allocating. its late where i'm at but what does that have to do with not capturing from the file?

thanks for your replies.

Share this post


Link to post
Share on other sites

It's bad practice to use variables named so similar: $recordNum and $record_num

It's also smarter to use something like _FileReadToArray() to get the file into your program. StringRegExp() can quickly format phone numbers in one line rather than looping through every possible digit for each character in the string.

We can't debug without seeing the code for doopsCreateStruct() and an example portion of your text file.

Share this post


Link to post
Share on other sites

We can't debug without seeing the code for doopsCreateStruct() and an example portion of your text file.

Thanks for your replies guys and excuse my autoit ignorance. i just picked it up a couple days ago. the text file is just a list of phone numbers formatted like so:
1234567890
(123) 456 7890
456 7899093

the doopscreateStruct() is as follows. i'm coiming from a c background, so i'm sure "i'm still thinking in C"

Func doopsCreateStruct()
#cs
the ideal situation as in c - would be to do this:

typedef struct{
    char flag
    char phoneNum[$DIGITS]
    }doops_t
    
then allocate an array of structs like so:

doops_t records[NUM_OF_RECORDS]

and call like so:

    while !EOF:
        records[NUM].phone_number[digit] = "digit"
    record[NUM].flag = "flag"
    
however seems autoitv3 doesn't allow array of structs so the workaround:
#ce

;struct members can't have "variable_name", contstants in the array, no 2D arrays and no arrays of struts? 
$vars ="char flag ;char phoneNum[14]"

;create doops_t structure
$record = DllStructCreate($vars)
if @error Then
    MsgBox(0,$VERSION,"unable to create  structure ERROR: " &@error)
Else
    ;MsgBox(0,$VERSION, "STRUCT  CREATED SUCCESFULLY SIZEOF STRUCT: " & DllStructGetSize($record) & " bytes")
EndIf
    
Return $record
EndFunc

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Take a look at this.

#include <File.au3>

Dim $fileArray

$fileName = "phone.txt"

;Read file to array
_FileReadToArray($fileName, $fileArray)

;Loop through all array elements
For $X = 1 to $fileArray[0]
    
    ;Ignore blank lines in the file
    If $fileArray[$X] <> "" Then
        
        ;Strip all non-numeric characters from string
        $result = StringRegExpReplace($fileArray[$X], "\D", "")
        ConsoleWrite("Before: " & $fileArray[$X] & " After: " & $result & @CRLF)
        
        If StringLen($result) = 11 Then
            ;Country code is present
            $resultFormat = StringRegExpReplace($result,"(\d{1})(\d{3})(\d{3})(\d{4})","$1 ($2) $3-$4")
            ConsoleWrite("Formatted: " & $resultFormat & @CRLF)
        ElseIf StringLen($result) = 10 Then
            ;Country code not present
            $resultFormat = StringRegExpReplace($result,"(\d{3})(\d{3})(\d{4})","($1) $2-$3")
            ConsoleWrite("Formatted: " & $resultFormat & @CRLF)
        Else
            ;Phone number invalid
            ConsoleWrite("Invalid number: " & $fileArray[$X] & @CRLF)
        EndIf
        ConsoleWrite(@CRLF)
    EndIf
Next

phone.txt:

CODE
1-(419)-555-1234

1-419-555-1234

14195551234

1.419.555.1234

(419)-555-1234

419-555-1234

4195551234

419.555.1234

Console output:

CODE
Before: 1-(419)-555-1234 After: 14195551234

Formatted: 1 (419) 555-1234

Before: 1-419-555-1234 After: 14195551234

Formatted: 1 (419) 555-1234

Before: 14195551234 After: 14195551234

Formatted: 1 (419) 555-1234

Before: 1.419.555.1234 After: 14195551234

Formatted: 1 (419) 555-1234

Before: (419)-555-1234 After: 4195551234

Formatted: (419) 555-1234

Before: 419-555-1234 After: 4195551234

Formatted: (419) 555-1234

Before: 4195551234 After: 4195551234

Formatted: (419) 555-1234

Before: 419.555.1234 After: 4195551234

Formatted: (419) 555-1234

EDIT: Kicked code up a notch

Edited by weaponx

Share this post


Link to post
Share on other sites

a cursory glance says you obviously have more experience with autoit. i see some regualr expressions in there and some string functions and of course familiarity with some module i don't know about yet.

i'll check it out, however i do want to figure out what the logic error is in my code, otherwise i won't learn anything and i'll just have it done for me.

i've amalgamated my code into one function here. its supposed to take the contents of a file with phone numbers, put it in a array of structs so i can operate on them. however, my while loop seems to be executing prematurely and i'd like to know whats up. any help would be appreciated.

Func LoadLeadFile($fp,$nums)
#cs
the ideal situation as in c - would be to do this:

typedef struct{
    char flag
    char phoneNum[$DIGITS]
    }doops_t
    
then allocate an array of structs like so:

doops_t records[NUM_OF_RECORDS]

and call like so:

    while !EOF:
        records[NUM].phone_number[digit] = "digit"
        record[NUM].flag = "flag"
#ce

    ;struct members can't have "variable_name"
    $vars ="char flag ;char phoneNum[14]"

    ;create an array to hold records so we can have each number in the struct
    Dim $RECORD[$nums]
    
    ;initialize  an array of structs of recordnum size
    For $structNum = 0 to $nums-1
        $RECORD[$structNum] = DllStructCreate($vars)
        if @error Then
            MsgBox(0,$VERSION,"UNABLE TO CREATE STRUCT " & $structNum  & " ERROR: " &@error)
        Else
            MsgBox(0,$VERSION, "STRUCT " & $structNum & " CREATED SUCCESFULLY " & @CRLF & _
                    "SIZEOF STRUCT: " & DllStructGetSize($RECORD[$structNum]) & " bytes")
        EndIf
    Next
    
    ;create and initialize an array of valid numbers
    Dim $validNum[10]
    for $ndx  = 0 to 9
        $validNum[$ndx] = $ndx
        MsgBox(0,"Valid Number Init ",  $validNum[$ndx])
    Next
    
    ;current record
    $recordNum=0
    ;current phone digit we on
    $phoneDigit=0
    
    ;copy every character from the file to a record EX: RECORD[line_num].phoneNum[digit] = num
    ;while loop isn't executing seems to reach EOF quick then exits can we rewind file?
    While 1
        ;read in 1 character at a time from the file till EOF
        ;this is reading till eof without branching
        $char = FileRead($fp,1)
        ;if its the EOF
        If @error = -1  Then 
            ExitLoop
        Else
            MsgBox(0, "Char read:", $char)
        EndIf
        
        ;check if number is a valid digit only put in the numbers
        For $x = 0 to 9 
            ;only add the valid digits doesn't seem to be case sensitive
            If $char = $validNum[$x] Then
             ;add the character to the phone number: read RECORD[num].phoneNumber[digit] = "number"
             DllStructSetData($RECORD[$recordNum], "phoneNum[$phoneDigit]",$char)
             ;advance to next phone digit to check
             $phoneDigit+=1
            EndIf
        Next; check against the next number

        If @CRLF  Then
            ;reset the phone number sequence
            $phoneDigit = 0
            ;go to the next record
            $recordNum+=1
        EndIf
        
    WEnd
        
MsgBox(0,$VERSION,"EOF REACHED: " & @error)
EndFunc

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I think you are defeating the purpose of using AutoIt. Embrace the ease of use.

You are trying to bend the DllStruct* functions into Struct-like objects which only leads to frustration. Use a 2-dimensional array instead.

EDIT: Also what is this ??? "If @CRLF Then"

Another EDIT: It appears you are trying to use FileRead to get one character at a time when in reality you are getting an entire line at a time.

Using $myfile = FileOpen("mytext.txt") and FileRead($myfile, 1) will read in one line at a time, just calling FileRead("mytext.txt", 1) will always read in the first character in the file...

Edited by weaponx

Share this post


Link to post
Share on other sites

a cursory glance says you obviously have more experience with autoit. i see some regualr expressions in there and some string functions and of course familiarity with some module i don't know about yet.

i'll check it out, however i do want to figure out what the logic error is in my code, otherwise i won't learn anything and i'll just have it done for me.

i've amalgamated my code into one function here. its supposed to take the contents of a file with phone numbers, put it in a array of structs so i can operate on them. however, my while loop seems to be executing prematurely and i'd like to know whats up. any help would be appreciated.

You seem to be ignoring the answer to your question. You have already been told that you can't FileRead() in a loop with a literal file path instead of a handle. Run this, and you will see that it never moves past the first character:

$sFile = "C:\Boot.ini"
While 1
    $char = FileRead($sFile, 1)
    If @error Then ExitLoop
    ConsoleWrite("Debug: $char = " & $char & @LF)
WEndoÝ÷ ØZ)âé²¢ì"YÞyÛh)^:§jwlj÷­èZÙ^mçè­ëazZ(¦Ø^붡jweyú+¶Wy§l{"uëazZ(¥«­¢+ØÀÌØíÍ¥±ôÅÕ½ÐíèÀäÈí   ½½Ð¹¥¹¤ÅÕ½Ðì(ÀÌØí¡¥±ô¥±=Á¸ ÀÌØíÍ¥±°À¤)]¡¥±Ä($ÀÌØí¡Èô¥±I ÀÌØí¡¥±°Ä¤(%%ÉɽÈQ¡¸á¥Ñ1½½À(%
½¹Í½±]É¥Ñ ÅÕ½ÐíÕèÀÌØí¡ÈôÅÕ½ÐìµÀìÀÌØí¡ÈµÀì1¤)]¹)¥±
±½Í ÀÌØí¡¥±¤

Get the Vista out of your ears... :)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Thank you all so much that answers my question as to what was going on. correct me if i'm wrong but a windows "handle" is basically a pointer right?

you seem to be ignoring the answer to your question. You have already been told that you can't FileRead() in a loop with a literal file path instead of a handle. Run this, and you will see that it never moves past the first character:

Psalty Ds, thanks for your code illustrating what you said. i thought i understood that and thought i was passing a handle to the LoadLead() function. thus : $fp == file pointer. the file handle was supposed to be returned from this function

Func OpenFile()
$file_name = FileOpenDialog($VERSION,@DesktopCommonDir,"(*txt)","","File Name")

; if file was opened unsucessfully
if @error = 1 Then
        MsgBox(0,"","uanble to get file path try again")
        Exit
    EndIf
    
;open the file for reading  
$fp = FileOpen($file_name,0)

;Check if file opened for reading OK
If $fp = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
    
;return "file handle" that is the pointer to the file
return $fp
EndFuncoÝ÷ Ú+pjÇWyybë(jëh×6;retrieve the file pointer to open returns a pointer to the file
$filep = OpenFile()oÝ÷ ٩ݶ§¥«,yÛh¶¡§Ky§EW¥G¬¡«­¢+Ù1½1¥± ÀÌØí¥±À°ÀÌØí¹ÕµÌ
where $nums was the num of lines in the file.

i obvioulsy did not return a file handle. how can i do that or can't i - without opening the file in the LoadLeadFile scope?

Having said all that weapon x thank you for your example usage of _fileReadToArray. i've checked the _file.au3 include file as well and found a boon of functions to do what i want. its obviously a more "autoit" way of accomplishing what i want and i was sure i'd find out later, but for now i have "C" in my ears - not Vista. :)

Share this post


Link to post
Share on other sites

That method should work. You got the file handle in OpenFile(), returned it to the $filep variable, and then passed that to LoadLeadFile(). The 1-byte FileRead loop in that function should work with a file handle.

I didn't see you say that $fp was a file handle, and when I read your code, $fp looked like "file path" string to me, but I shouldn't have made that assumption.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

That method should work. You got the file handle in OpenFile(), returned it to the $filep variable, and then passed that to LoadLeadFile(). The 1-byte FileRead loop in that function should work with a file handle.

I didn't see you say that $fp was a file handle, and when I read your code, $fp looked like "file path" string to me, but I shouldn't have made that assumption.

:)

and yet on entering LoadLeadFile() EOF is obviously reached. i'm actually stumped so i'm posting the full code, you can use any text file. i will obviously recode it with the functions in the file.au3 module with the help of some string functions, however this will irk me to no end. any help is appreciated.

#cs ----------------------------------------------------------------------------
 Author: bitshadow
 function: reads a file and allocates to a struct for processing
#ce ----------------------------------------------------------------------------
;explicity let us know these are global variables
Global $DIGITS = 30
Global $VERSION = "1.0"
Global $PNUMBERS = 10
    
;retrieve the file pointer to open returns a pointer to the file
$filep = OpenFile()

;get the number of records in the file
$nums = NumOfRecs($filep);

;allocate records to struct so can compare them easily and write back to file
LoadLeadfile($filep,$nums)

Func OpenFile()
;first we'll use a FileOpenDialog then later we'll add the gui with GUICtrlCreateInput
;FileOpenDialog allows you one way to CHOOSE your file instead of typing it autoit has no STDIN or its redirected elsewhere
;it returns the full path of the file chosen - Not the actual pointer to the file - sets @error to 1 on failure

;Window title, start directory, type of file,options (see options), default name
$file_name = FileOpenDialog($VERSION,@DesktopCommonDir,"(*txt)","","File Name")

; if file was opened unsucessfully
if @error = 1 Then
        MsgBox(0,"","uanble to get file path")
        Exit
    EndIf
    
;open the file for reading: assumes it goes to that path and actually opens the File
;and returns a pointer in windows a HWND a "smart pointer"
$fp = FileOpen($file_name,0)

;Check if file opened for reading OK
If $fp = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
    
;return "file handle" to the file
return $fp
EndFunc

Func NumOfRecs($fp)
;has a pointer to the file so just go there and read it
;num of records in file first line it reads is 1 not zero
Local $num=1
    
;iterate through the file and read how many new lines this indicates number of phone numbers
;Read in lines of text until the EOF is reached check out _FileCountLines later
While 1
;returns the line it read
    $line = FileReadLine($fp)
;ConsoleWrite("line number: " & $num & " " & $line & @LF)
;keep track of how many lines read
    $num+=1
;if we reach the EOF then break
    If @error = -1 Then ExitLoop
Wend

MsgBox(0,$VERSION,"there are " & $num & " Records in the file")
;FileClose($fp);is this why we keep reaching the eof. its still opened and we're at the end so @error ==1 thus
;when called in loadlead file its still at -1 and thus end of file if we close it where is @error Then
;maybe we should have each function returns its own value and not put it on @error or SetError(0) again?
;as per documentation when entering a funtion @error is always set to 0
Return $num
EndFunc 

Func LoadLeadFile($fp,$nums)
#cs
the ideal situation as in c - would be to do this:

typedef struct{
    char flag
    char phoneNum[$DIGITS]
    }doops_t
    
then allocate an array of structs like so:

RECORD record[NUM_OF_RECORDS]

and call like so:

    while !EOF:
        record[NUM].phone_number[digit] = "digit"
        record[NUM].flag = "flag"
        
use _FileReadToArray to strip contents of text file of '\n' and put each line in a array
with each element being a line. so basically Autoit's version of what C does - kinda
#ce

;struct members can't have "variable_name" seemingly autoit thinking its a string?
    $vars ="char flag;char phoneNum[14]"

;declare an array of stucts to hold each record
    Dim $RECORD[$nums]
    
;create an array of structs to hold each record
    For $structNum = 0 to $nums-1
        $RECORD[$structNum] = DllStructCreate($vars)
        if @error Then
            MsgBox(0,$VERSION,"UNABLE TO CREATE STRUCT " & $structNum  & " ERROR: " &@error)
            Exit
        Else
        ;MsgBox(0,$VERSION, "STRUCT " & $structNum & " CREATED SUCCESFULLY " & @CRLF & _
                ;"SIZEOF STRUCT: " & DllStructGetSize($RECORD[$structNum]) & " bytes")
        EndIf
    Next
    
;create and initialize an array of valid numbers
    Dim $validNum[$PNUMBERS]
    for $ndx  = 0 to 9
        $validNum[$ndx] = $ndx
    ;MsgBox(0,"Valid Number Init ",  $validNum[$ndx])
    Next
    
;current record
    $recordNum = 1
;current phone digit we on
    $phoneDigit = 0
    
;copy every character from the file to a record EX: RECORD[line_num].phoneNum[digit] = num
;while loop seems to reach EOF when first time loop starts then exits can we rewind file.
    While 1
    ;read in 1 character at a time from the file till EOF
    ;this is reading till eof without branching
        $char = FileRead($fp,1)
    ;if its the EOF it'll be -1 thus not 0 thus not true
        If @error  Then 
            ExitLoop
        Else
            ConsoleWrite("line number: " & $recordNum & " " & $char & @LF)
        ;MsgBox(0, "Char read: ", $char)
        EndIf
        
    ;check if number is a valid digit only put in the numbers
        For $x = 0 to 9 
        ;only add the valid digits doesn't seem to be case sensitive
            If $char = $validNum[$x] Then
            ;add the character to the phone number: read RECORD[num].phoneNumber[digit] = "number"
             DllStructSetData($RECORD[$recordNum], "phoneNum[$phoneDigit]",$char)
            ;advance to next phone digit to check
             $phoneDigit+=1
            EndIf
        Next; check against the next number

        If $char = @LF  Then
        ;reset the phone number sequence
            $phoneDigit = 0
        ;go to the next record
            $recordNum+=1
        EndIf
        
    WEnd
        
MsgBox(0,$VERSION,"EOF REACHED: " & @error)
EndFunc
Edited by bitshadow

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0