Stringsplit -> Problems with Numbers

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
payback87
Posts: 13
Joined: 31 Aug 2016, 01:55

Stringsplit -> Problems with Numbers

Post by payback87 » 30 Sep 2016, 07:02

Hey there,
I have a settingsfile that I read in with fileopen(filename, "r"). Then I split the lines up with StringSplit.
After that I go through each line that looks as follows:

Code: Select all

FirstSetting=1
So I split each line up again, using StringSplit.
Following up on that I send Part1 and Part2 to an associative array called "settings".
(I left all the loops out, no need for that in this example code)

Code: Select all

StringSplit, Part, Line%A_Index%, =
settings[Part1]:=Part2
It's all fine, I made sure everything got read in correctly and that's no problem.

The problem occurs with handling the values of the settings array!
Say I want to do the following:

Code: Select all

a:=settings["FirstSetting"]
b:= a + 1
msgbox % b
I expect a messagebox showing the value '2'.
Instead this gives me an empty messagebox, because apparently in this case 'a' is a string and not an integer (or any number for that matter).
I'm stuck and can't get my head around it currently. It has to be easy, hasn't it?!

Glad for your help lads!

Guest

Re: Stringsplit -> Problems with Numbers

Post by Guest » 30 Sep 2016, 07:23

You probably forgot to define settings as an object. This is done below by the first line settings:=[]. OR the file can't be read.

Code: Select all

settings:=[] ; be sure to have this line in your script before you read the file and start splitting the lines if you comment this line you will get an empty message box

file:="FirstSetting=1"
StringSplit, part, file, =
settings[Part1]:=Part2
MsgBox % settings["FirstSetting"] ; shows 1

a:=settings["FirstSetting"]
b:= a + 1
msgbox % b ; shows 2
P.S. you are aware of the INIREAD and INIWRITE commands? (just checking)

User avatar
Grendahl
Posts: 170
Joined: 30 Sep 2013, 08:21

Re: Stringsplit -> Problems with Numbers

Post by Grendahl » 30 Sep 2016, 07:36

You never push the value of FirstSettings into your array.
This works:

Code: Select all

FS := 1
settings := []
settings.push(FS)
a:=settings[FS]
b:=a + 1
Msgbox % b

aaffe
Posts: 192
Joined: 16 Jan 2014, 04:23

Re: Stringsplit -> Problems with Numbers

Post by aaffe » 30 Sep 2016, 07:36

I dont know why, but this here works instead of yours:

Code: Select all

Line:="FirstSetting=1"

StringSplit, Part, Line, =


settings := Object(part1, part2)

for key, value in settings
	msgbox %key% %value%


a:=settings["FirstSetting"]
b:= a + 1
msgbox % b

payback87
Posts: 13
Joined: 31 Aug 2016, 01:55

Re: Stringsplit -> Problems with Numbers

Post by payback87 » 30 Sep 2016, 07:58

Hm, this leaves me with another problem: assigning to settings like this in a loop will always overwrite the first key value pair...

User avatar
Capn Odin
Posts: 1352
Joined: 23 Feb 2016, 19:45
Location: Denmark
Contact:

Re: Stringsplit -> Problems with Numbers

Post by Capn Odin » 30 Sep 2016, 08:41

You can try using this Class I made, currently it can not handle comments.

Code: Select all

Class InIFile{
	Sections := {}, SectionOrder := []
	
	__New(path, OrderedSections := False, OrderedKeys := False){
		this.path := path
		this.OrderedSections := OrderedSections
		this.OrderedKeys := OrderedKeys
		this.InI := FileOpen(path, "r`n", "UTF-16")
		this.LoadData()
	}
	
	LoadData(){
		keys := []
		While(!this.InI.AtEOF){
			Line := SubStr(this.InI.ReadLine(), 1, -1)
			
			if(eq := InStr(Line, "=") && Section){
				keys.Push(Line)
			}
			
			if(this.InI.AtEOF || (!eq && (SubStr(Line, 1, 1) = "[" && SubStr(Line, -0) = "]"))){
				if(Section){
					this.Sections[Section] := New InISection(Section, this.OrderedKeys, keys*)
					this.SectionOrder.Push(Section)
				}
				Section := SubStr(Line, 2, -1)
				keys := []
			}
		}
		this.InI.Close()
	}
	
	StoreData(path := False){
		this.InI := FileOpen(path ? path : this.path, "w`n", "UTF-16")
		for key, value in (this.OrderedSections ? this.SectionOrder : this.Sections) {
			(this.OrderedSections ? this.Sections[value] : value).WriteSection(this.InI)
		}
		this.InI.Close()
	}
}

Class InISection{
	Keys := {}, KeyOrder := []

	__New(Name, OrderedKeys, Keys*){
		this.Name := Name
		this.OrderedKeys := OrderedKeys
		this.ArrangeKeys(Keys)
	}
	
	ArrangeKeys(Keys){
		for index, keyValue in Keys {
			eq := InStr(keyValue, "=")
			this.Keys[SubStr(keyValue, 1, eq - 1)] := SubStr(keyValue, eq + 1)
			this.KeyOrder.Push(SubStr(keyValue, 1, eq - 1))
		}
	}
	
	WriteSection(File){
		File.WriteLine("[" this.Name "]")
		for key, value in (this.OrderedKeys ? this.KeyOrder : this.Keys) {
			File.WriteLine((this.OrderedKeys ? value : key) "=" (this.OrderedKeys ? this.Keys[value] : value))
		}
	}
}
Example of use.

Code: Select all

#Include InIFile.ahk
InI := New InIFile("filename.ini", False, True) ; the booleans determines how the sections and keys are sorted when saved as a file

for sectionName, sectionObj in InI.Sections {
	res := ""
	for key, val in sectionObj.Keys {
		res .= "`n`t" . key . " = " . val
	}
	MsgBox, % sectionName . res
}
Please excuse my spelling I am dyslexic.

just me
Posts: 9425
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Stringsplit -> Problems with Numbers

Post by just me » 30 Sep 2016, 09:05

payback87 wrote:(I left all the loops out, no need for that in this example code)
Do you remove the carriage return `r when splitting the file contents?

payback87
Posts: 13
Joined: 31 Aug 2016, 01:55

Re: Stringsplit -> Problems with Numbers

Post by payback87 » 30 Sep 2016, 09:19

just me wrote:
payback87 wrote:(I left all the loops out, no need for that in this example code)
Do you remove the carriage return `r when splitting the file contents?
Nope haven't thought of that. I'll try as soon as I'll be back to work. Thanks!

User avatar
tidbit
Posts: 1272
Joined: 29 Sep 2013, 17:15
Location: USA

Re: Stringsplit -> Problems with Numbers

Post by tidbit » 30 Sep 2016, 11:02

btw, there's "strSplit()" which already uses a real array. "stringSplit" does not.

Code: Select all

arr:=strSplit(line, "=")
msgbox, % arr[1] "=" arr[2]

also, made this a while ago, iniToArr()

Code: Select all

; Version 1.0 (Sun November 02, 2014)
; Created: Sun November 02, 2014
; Author: tidbit

; ini=%A_ScriptDir%\ini.ini
; out:=iniToArr(ini)


/*
iniToArr
   read all the sections, keys and values in a .ini file and put them in a
   2D array (object).

   iniPath = The full path to your ini file

example: out:=iniToArr(A_ScriptDir "\settings.ini")
output:
{"section1":{"key 4":"ddd"
            ,"key1":"aaa"
            ,"key2":"bbb"
            ,"key3":"ccc"}
}
*/
iniToArr(iniPath)
{
	arr:={}
	iniRead, data, %iniPath%
	loop, parse, data, `n, `r
	{
		iniRead, data, %iniPath%, %A_LoopField%
		for k in temp:=strsplit(data, ["=","`n"])
			if (temp[a_index*2-1]!="")
				arr[A_LoopField, temp[a_index*2-1]]:=temp[a_index*2]
	}
	return arr
}
rawr. fear me.
*poke*
Is it December 21, 2012 yet?

payback87
Posts: 13
Joined: 31 Aug 2016, 01:55

Re: Stringsplit -> Problems with Numbers

Post by payback87 » 01 Oct 2016, 09:31

tidbit wrote:btw, there's "strSplit()" which already uses a real array. "stringSplit" does not.

Code: Select all

arr:=strSplit(line, "=")
msgbox, % arr[1] "=" arr[2]

also, made this a while ago, iniToArr()

Code: Select all

; Version 1.0 (Sun November 02, 2014)
; Created: Sun November 02, 2014
; Author: tidbit

; ini=%A_ScriptDir%\ini.ini
; out:=iniToArr(ini)


/*
iniToArr
   read all the sections, keys and values in a .ini file and put them in a
   2D array (object).

   iniPath = The full path to your ini file

example: out:=iniToArr(A_ScriptDir "\settings.ini")
output:
{"section1":{"key 4":"ddd"
            ,"key1":"aaa"
            ,"key2":"bbb"
            ,"key3":"ccc"}
}
*/
iniToArr(iniPath)
{
	arr:={}
	iniRead, data, %iniPath%
	loop, parse, data, `n, `r
	{
		iniRead, data, %iniPath%, %A_LoopField%
		for k in temp:=strsplit(data, ["=","`n"])
			if (temp[a_index*2-1]!="")
				arr[A_LoopField, temp[a_index*2-1]]:=temp[a_index*2]
	}
	return arr
}
Oh great the info about strsplit escaped my attention! I'm sure I'll be able to get it to work :)

payback87
Posts: 13
Joined: 31 Aug 2016, 01:55

Re: Stringsplit -> Problems with Numbers

Post by payback87 » 04 Oct 2016, 00:32

tidbit wrote:btw, there's "strSplit()" which already uses a real array. "stringSplit" does not.

Code: Select all

arr:=strSplit(line, "=")
msgbox, % arr[1] "=" arr[2]
Thank you all guys, I've made it work. Nr. 1 I trimmed `r`n off each line end, Nr. 2 I used StrSplit rather than the old one. Works like a charm.
I'll make sure to check the scripts you guys posted in this thread :)

This is the function now:

Code: Select all

LoadSettings()
{
	settingsFile := fileopen("settings.ini", "r")
	Text := settingsFile.Read()
	Line:=StrSplit(Text, "`r`n")
	Loop, % Line.Length()
	{
		if (inStr(Line[A_Index], "="))
		{
			Part:=StrSplit(Line[A_Index], "=")
			value := Part[2]
			name := Part[1]
			Settings[name]:=value
		}
	}
	
	settingsfile.Close
	
	return Settings
}

Post Reply

Return to “Ask for Help (v1)”