Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use scanf to split a string on a non-whitespace separator

I aim to scan a string containing a colon as a division and save both parts of it in a tuple.
For example:

input: "a:b"
output: ("a", "b")

My approach so far keeps getting the error message:
"scanf: bad input at char number 9: looking for ':', found '\n'".

 Scanf.bscanf Scanf.Scanning.stdin "%s:%s" (fun x y -> (x,y));;

Additionally, my approach works with integers, I'm confused why it is not working with strings.

Scanf.bscanf Scanf.Scanning.stdin "%d:%d" (fun x y -> (x,y));;
4:3
- : int * int = (4, 3)
like image 495
Simplicissimus Avatar asked Nov 29 '25 20:11

Simplicissimus


1 Answers

The reason for the issue you're seeing is that the first %s is going to keep consuming input until one of the following conditions hold:

  • a whitespace has been found,
  • a scanning indication has been encountered,
  • the end-of-input has been reached.

Note that seeing a colon isn't going to satisfy any of these (if you don't use a scanning indication). This means that the first %s is going to consume everything up to, in your case, the newline character in the input buffer, and then the : is going to fail.

You don't have this same issue for %d:%d because %d isn't going to consume the colon as part of matching an integer.

You can fix this by instead using a format string which will not consume the colon, e.g., %[^:]:%s. You could also use a scanning indication, like so: %s@:%s.

Additionally, your current method won't consume any trailing whitespace in the buffer, which might result in newlines being added to the first element on subsequent use of this, so you might prefer %s@:%s\n to consume the newline.

So, in all,

Scanf.bscanf Scanf.Scanning.stdin "%s@:%s\n" (fun x y -> (x,y));;
like image 153
kopecs Avatar answered Dec 04 '25 06:12

kopecs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!