SScanf to scan strings lazarus / 21-General ---------------------------------------------------------------------- spassigl · 2021-01-04 16:08 Hi I'm using sscanf to scan a format like this Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i %d"%s"%d So a number, a string between double quotes, a number again. An example would be 200"this is a string"100 SScanf scans the numbers succesfully (I get 200 and 100) but I only get the "this" part - so string scanning breaks at the first whitespace. Is this by design? Thanks [EDIT] I corrected the format string as it had a typo ---------------------------------------------------------------------- Bart · 2021-01-04 16:19 A regex might do the job? Bart ---------------------------------------------------------------------- bytebites · 2021-01-04 17:15 Does Pascal have sscanf-function? ---------------------------------------------------------------------- winni · 2021-01-04 17:28 Quote from: bytebites on January 04, 2021, 06:15:08 pmDoes Pascal have sscanf-function? In sysutils ---------------------------------------------------------------------- howardpc · 2021-01-04 17:52 If the numbers are positive integers, and the string contains no " characters,  the OP might prefer a simple brute force parser rather than dicing with the pointer array of a sscanf. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function ParsedNumQuoteStrQuoteNumOK(const aText: String; out Num1, Num2: Integer; out TheString: String): Boolean;var  p, q1, q2: Integer;begin  num1 := -MaxInt;  num2 := -MaxInt;  TheString := '';  Result := False;  if Length(aText) < 6 then    Exit;  q1 := 0;  q2 := 0;  for p := 1 to Length(aText) do    case q1 = 0 of      True:  if aText[p] = '"' then               q1 := p;      False: if aText[p] = '"' then               q2 := p;    end;  if (q1 = 0) or (q2 = 0) or (Pos('"', Copy(aText, Succ(q2), MaxInt)) <> 0) then    Exit;  TheString := Copy(aText, Succ(q1), Pred(q2 - q1));  Result := TryStrToInt(Copy(aText, 1, Pred(q1)), Num1) and TryStrToInt(Copy(aText, Succ(q2), Length(aText)-q2), Num2);end; ---------------------------------------------------------------------- Roland57 · 2021-01-04 17:53 Quote from: spassigl on January 04, 2021, 05:08:04 pmSScanf scans the numbers succesfully (I get 200 and 100) but I only get the "this" part - so string scanning breaks at the first whitespace. Hello! I believe that there is one extra character in your pattern: %d"%s%"%d ---------------------------------------------------------------------- spassigl · 2021-01-04 20:17 Quote from: Roland57 on January 04, 2021, 06:53:14 pmQuote from: spassigl on January 04, 2021, 05:08:04 pmSScanf scans the numbers succesfully (I get 200 and 100) but I only get the "this" part - so string scanning breaks at the first whitespace. Hello! I believe that there is one extra character in your pattern: %d"%s%"%d Hi, no that was a typo ---------------------------------------------------------------------- spassigl · 2021-01-04 20:20 Yes I used a similar hack eventually and did it in two lines of code. My question was more to understand if sscanf is supposed to scan strings containing whitespaces or the behaviour I found is by design.  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i            SScanf(stp, 't@%d"%sd"%d', [@start, @str, @dur]);str := Copy(stp, Pos('"', stp) + 1, LastDelimiter('"', stp)-Pos('"', stp) - 1);  Quote from: howardpc on January 04, 2021, 06:52:29 pmIf the numbers are positive integers, and the string contains no " characters,  the OP might prefer a simple brute force parser rather than dicing with the pointer array of a sscanf. ---------------------------------------------------------------------- ASerge · 2021-01-04 20:22 Quote from: spassigl on January 04, 2021, 09:20:47 pmMy question was more to understand if sscanf is supposed to scan strings containing whitespaces or the behaviour I found is by design. SScanf does not handle double quotes, and spaces are used to separate elements. ---------------------------------------------------------------------- marcov · 2021-01-04 20:50 Quote from: spassigl on January 04, 2021, 09:20:47 pmYes I used a similar hack eventually and did it in two lines of code. My question was more to understand if sscanf is supposed to scan strings containing whitespaces or the behaviour I found is by design. Anything after a certain character is a string. So what would you expect to match %s, if not the end of the string? ---------------------------------------------------------------------- spassigl · 2021-01-05 09:33 Quote from: marcov on January 04, 2021, 09:50:13 pmQuote from: spassigl on January 04, 2021, 09:20:47 pmYes I used a similar hack eventually and did it in two lines of code. My question was more to understand if sscanf is supposed to scan strings containing whitespaces or the behaviour I found is by design. Anything after a certain character is a string. So what would you expect to match %s, if not the end of the string? It's not matching the end of the string, but the string up to the first whitespace. ---------------------------------------------------------------------- Thaddy · 2021-01-05 09:43 sscanf is a C style function and can not handle Pascal strings. It is one of many limitations to the C language and its derivatives. ---------------------------------------------------------------------- marcov · 2021-01-05 09:48 Quote from: spassigl on January 05, 2021, 10:33:17 amIt's not matching the end of the string, but the string up to the first whitespace. My point is what else you would have expected if you expect a value "d%d to follow? I think you are mixing up sscanf with regex, which does scan till the pattern after, but scanf doesn't. ---------------------------------------------------------------------- spassigl · 2021-01-05 10:11 Yes I think I mixed it up. Even in C sscanf stops at the first whitespace character, so the Pascal implementation is coherent with that. ---------------------------------------------------------------------- Warfley · 2021-01-05 11:53 Thats expected behavior for scanf (manpage): Quotes Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first. The thing is, scanf is very limited in it's implementation, it can only parse what you directly tell it to parse, and basically only implements the simplest form of an concatination automata. A solution to what you are trying to do would be the following format string: '%d"%[^"]"%d', which matches a number, followed by a " and then any string that does not contain ", then another " and after that another number. But in general is scanf not really a good solution, the pointer mechanic is made for C-Style static buffer strings, which we usually don't use in modern Pascal, it is highly insecure as you can easiely bufferoverflow while also being highly limited in terms of it's parsing capabilities. To put it nicely, nobody should ever use scanf anymore. Today we have regex, which can do more, is easier to use and does not pose a massive security risk to your application. That said, I don't know if there is already a regex implementation available that supports groups. Last time I checked (a few years ago) the implementations shipped with the FPC did not implement the group matching feature, which is why most often I wrote my own automata based parsers, but maybe there was some progress since then (because to be honest, without groups regex is pretty useless)