Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/29/2022 in all areas

  1. pixelsearch

    Sort question in C++

    Hi everybody, After reading a bit about Vectors in C++, I could quickly sort a string column in a 2D array (example made with an AutoIt 2D array of 100.000 rows and 6 cols, also tried 500.000 rows). Here are the corresponding codes : AutoIt code : #include <Array.au3> ; #include <WinAPIDiag.au3> #include "RandomArray.au3" ; LarsJ $hDLL = DllOpen(@ScriptDir & "\rrr_03.dll") If $hDLL = -1 Then Exit Msgbox(0, "DllOpen", "error occured") Global $g_iRows = 100000, $g_iCols = 6, $g_iSort_Col = 0, $g_aArray ; only col 0 is string _Generate_All($g_aArray) Local $aBackup = $g_aArray ; extremely fast ! _ArrayDisplay($g_aArray, "UNsorted", Default, Default, Default, _ "Strings|Integers*|Floats*|Dates*|Times*|R/C*") ;==================== $hTimer = TimerInit() Local $sDelim = Chr(1), $sData = "" For $i = 0 To $g_iRows - 1 $sData &= $g_aArray[$i][$g_iSort_Col] & $sDelim Next ConsoleWrite("Preparing concatenated string = " & Int(TimerDiff($htimer)) & " ms" & @crlf) ;==================== $hTimer = TimerInit() $iBufferSize = StringLen($sData) $tStruct = DllStructCreate("char[" & $iBufferSize & "]") If @error Then Exit Msgbox(0, "DllStructCreate", "error " & @error) DllStructSetData($tStruct, 1, $sData) If @error Then Exit Msgbox(0, "DllStructSetData", "error " & @error) ConsoleWrite("Writing structure = " & Int(TimerDiff($htimer)) & " ms" & @crlf) MsgBox(0, "Pointer of struct", DllStructGetPtr($tStruct) & " Buffer size = " & $iBufferSize) $tStruct2 = DllStructCreate("int[" & $g_iRows & "]") ; will be filled by dll If @error Then Exit Msgbox(0, "DllStructCreate 2", "error " & @error) ;==================== $hTimer = TimerInit() $aRet = DllCall($hDLL, "int:cdecl", "StringSort2D", "ptr", DllStructGetPtr($tStruct), _ "ptr", DllStructGetPtr($tStruct2), "str", $sDelim, "int", $g_iRows) If @error Then Exit Msgbox(0, "DllCall StringSort2D", "error " & @error) ConsoleWrite("DllCall = " & Int(TimerDiff($htimer)) & " ms" & @crlf) _ArrayDisplay($aRet, "$aRet") ; _WinAPI_DisplayStruct($tStruct2, "int[" & $g_iRows & "]", "$tStruct2") ;==================== $hTimer = TimerInit() For $i = 0 To $g_iRows - 1 $iIndex = DllStructGetData($tStruct2, 1, $i + 1) ; row index before sorting If $i <> $iIndex Then For $j = 0 To $g_iCols - 1 $g_aArray[$i][$j] = $aBackup[$iIndex][$j] Next EndIf Next ConsoleWrite("Generating sorted 2D array = " & Int(TimerDiff($htimer)) & " ms" & @crlf) _ArrayDisplay($g_aArray, "sorted (col " & $g_iSort_Col & ")", Default, Default, Default, _ "Strings|Integers*|Floats*|Dates*|Times*|R/C*") _StringSplitFree($tStruct) _StringSplitFree($tStruct2) DllClose($hDLL) ;============================================= Func _Generate_All(ByRef $g_aArray) ; LarsJ ConsoleWrite("$g_iRows = " & $g_iRows & " $g_iCols = " & $g_iCols & @CRLF) $g_aArray = FAS_Random2DArrayAu3($g_iRows, "sifdtr", "abcdefghijklmnopqrstuvwxyz") EndFunc ;==>_Generate_All ;============================================= Func _StringSplitFree(ByRef $tStruct) ; Funkey DllCall("msvcrt.dll", "none:cdecl", "free", "ptr", DllStructGetPtr($tStruct)) If @error Then Exit Msgbox(0, "DllCall Free", "error " & @error & " occured") $tStruct = 0 EndFunc ;==>_StringSplitFree C++ code // build options OF THE PROJECT : check line C++1z (C++17) or these errors appear : // error: 'to_string' was not declared in this scope // error: 'stoi' was not declared in this scope #include <algorithm> // sort #include <string.h> // strtok #include <string> // string #include <vector> // vector using namespace std; bool sortcol(const vector<string>& v1, const vector<string>& v2) { return v1[0] < v2[0]; // [0] sort on col 0, [1] on col 1 etc... (not in this dll) // To sort descending : // return v1[0] > v2[0]; } extern "C" __declspec(dllexport) int StringSort2D(char* structure, int* structure2, char* sdelim, int irows) { vector<vector<string> > vect(irows, vector<string>(2)); // irows and 2 cols int i = 0; char* p; p = strtok(structure, sdelim); // split string into tokens (returns a pointer). // End of the token (delimiter) is automatically replaced by a null-character // https://www.cplusplus.com/reference/cstring/strtok/ while ((p != NULL) && (i < irows)) { vect[i][0] = p; // string (col 0 will be sorted) vect[i][1] = to_string(i); // row (to remember initial index before sorting) p = strtok(NULL, sdelim); i++; } sort(vect.begin(), vect.end(), sortcol); // sort on column 0 (string) in this dll for(i = 0; i < irows; ++i) { *(structure2 + i) = stoi(vect[i][1]); // index of sorted string [i][0] ... before sorting } // this should release memory used by the vector (to be confirmed) : // https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize // http://www.cplusplus.com/reference/vector/vector/clear/ <= recommeneds swap() // http://www.cplusplus.com/reference/vector/vector/swap-free/ vector<vector<string>>().swap(vect); return 0; } I kept a part of the flowchart used for 1D array (see precedent post) but had to adapt it for 2D, by adding this : * Create a 2nd structure (int) in AutoIt to be filled by the Dll during DllCall(). This structure will contain the index (row) of each sorted string ... before it was sorted. Here is an example based on 10 strings : As you can see in the structure pic (the 2nd pic with its 1st line in green) the value of the 1st line in the structure is 2. It means that the 1st string sorted ("axso..." in the sorted pic) HAD an index of 2 in the unsorted pic. This goes for all the other sorted strings. Same explanation for another string : the last string sorted ("trll..." in the sorted pic) HAD an index of 0 in the unsorted pic. This index in the structure will be used to grab the correct values of all the other columns in a backup of the initial array ($aBackup), pointing to the correct row. So in the C++ code, the 2D vector has only 2 columns : - a column for the unsorted strings - a column for the index (row) of the string in the Autoit array (which is 0, 1, 2, 3... before the sort) After the sort is done on the string column (in the Dll), the strings will be sorted in the 1st column and their "index before sorting" will be found unaltered in the other column, which will fill the index structure. There are certainly other ways to achieve this but this is what I found. The next step should be to create a udf to take care of all cases (1D, 2D, col to be sorted, numeric or alphabetic sort, asc or desc) and to separate functions in the dll (all sorting functions should be based on vectors in the Dll, even if it's a 1D array in AutoIt) If something is ready one day, I'll post it here. Meanwhile, I hope the code will be helpful for some users. The hardest part I faced ? Find the C++ code to declare a 2D vector of strings as "easily" as we declare a 2D array in AutoIt vector<vector<string> > vect(irows, vector<string>(2)); // irows and 2 cols Edit 10 february 2022 : Though the preceding script works fine, it will soon be replaced with C++ code based on a Vector of structs (in a future post of this thread)
    1 point
  2. @Jos' ok,i will make sure of that next time.😉
    1 point
  3. Additional comment on your requirement. In case of .txt file, it is not recommended to go thru Notepad (or any other text editor) for automation. You can easily read, write and delete lines with File* functions. I would strongly suggest you invest your time learning those functions instead of trying to automate Notepad. Let us know if you need help with your script if you face an issue, we will gladly be able to help assuming you provide script and data. It is quite important that you make your script runable to us in order to get proper help. BTW, welcome to the forum !
    1 point
  4. grooveman, You are by no means the first to have made this comment - and the answer is always the same: The forum ethos is to help you get your code running as you wish, but also to get you to understand why so that you have a better chance of getting it right next time. Think of the old saying: "Give a man a fish, you feed him for a day; give a man a net and you feed him forever". We try to be net makers and repairers, not fishmongers. We do not expect people to "bust a gut", but (in most cases) neither are we prepared to just "barf up code" (as one of my US colleagues puts it). There are several websites where you can pay to get code written to spec - we are a bunch of enthusiastic volunteers who want to help people along the road to becoming proficient coders by getting them to do some of the work themselves. No-one here minds (or laughs at) an amateurish, non-functioning script - all we want to see is that the poster has made some attempt to use the Help file to make a start. I hope that you find that explanation sufficient. And thank you for the restrained manner in which you expressed yourself above - we try to run a civilised forum and polite comments such as yours are always welcome. And as to your questions - I am sure you can guess the answer I am about to give you: What have you tried that has not worked to your satisfaction? Which functions does the Help file suggest might be of use? I suggest that a couple which might be include: FileRead (to get the text into a variable) and _StringBetween (to extract the required data from within the variable). Sight of a sample (suitably redacted) text would also be useful if you require further help. Over to you! M23
    1 point
  5. Jos

    IP address

    .. else it is one of these: @IPAddress1-@IPAddress4.
    1 point
  6. Thanks to @jpm this feature request is completed. https://www.autoitscript.com/trac/autoit/ticket/2443#comment:3 The only one thing to do is to wait for @Jon when he will have spare time to take a look at this. Do not ask when, just wait, we all are here volonteers.
    1 point
  7. jchd

    [HELP] List view Sqlite

    Before coding anything in AutoIt, stabilize your database and refine the queries you'll be using in your application(s) by using a good third-party SQLite manager. I warmly recommend SQlite Expert (freeware will do, v3 or v4). The site is currently down but you can download it from a lot of places or I can place one version on my dropbox site (v3.5.96.2513 for instance). EDIT: I just notified my friend Bogdan (SQLite Expert author) and the website in online again.
    1 point
  8. @BartW, OP Don't simply surround litteral text values with single quotes: that's not enough to protect you from SQL errors at runtime. Why? Because if a litteral itself contains a single quote, it will terminate the litteral. Embedded single quotes should be doubled. UPDATE mytable set mycolumn = 'O'Connor' where ... <--- Syntax error after 'O' UPDATE mytable set mycolumn = 'O''Connor' where ... <--- will work You should wrap your string litterals using _SQLite_Escape (or the much faster _SQLite_Fast_Escape() offered with the last beta). For brevity, I use the following equivalent: Func X($sValue) Return(StringReplace($sValue, "'", "''")) EndFunc And then: $sName = "O'Connor" _SQLite_Exec($hDB, "UPDATE mytable set mycolumn = " & X($sName) & " where ...") BTW doing so also protects you from SQL injection attacks, even if such attack is improbable in an embedded DB context. Anyway, it's a sane habit to grab. While I'm at it, you must know you need to use square brackets around schema names when they may otherwise lead to SQL error: SELECT [isn't that a strange name for a ÁÇÌþæ÷Ĉ column?] FROM [my table has a long name with spaces] WHERE [where] LIKE 'abc%' SQLite also accepts double quotes instead of square brackets: SELECT "Isn't that a strange name for a ÁÇÌþæ÷Ĉ column?" FROM "my table has a long name with spaces" WHERE "where" LIKE 'abc%' While SQLite will do its best to disambiguate wrongly quoted statements, you should avoid mixing roles of single- and double-quotes.
    1 point
  9. ControlClick ( "title", "text", controlID [, button [, clicks [, x [, y ]]]] )
    1 point
  10. One way to test the idea. Run('calc') Sleep(1000) WinWait('Calculator') Sleep(1000) ; Hide window with next line WinSetState('Calculator', '', @SW_HIDE) ControlClick('Calculator', '', '6') ControlClick('Calculator', '', '+') ControlClick('Calculator', '', '6') ControlClick('Calculator', '', '=') Sleep(1000) ; Show window with next line WinSetState('Calculator', '', @SW_SHOW)
    1 point
×
×
  • Create New...