# String Instructions — CONCAT, FIND, MID, INSERT, DELETE

Source: https://rungs.dev/docs/ladder-logic/instructions/string

> The Ladder Logic string instructions in rungs.dev join STRINGs, find text inside one, and take part of one out, for building operator messages and reading codes such as a barcode.

A `STRING` tag holds text: up to 82 characters, with `LEN` saying how many are in use. These
five instructions build text and take it apart. Use them to put an operator message together
from pieces, to find a separator in a barcode, or to pull a part number out of a longer code.

Each one runs on every scan its rung is true, and does nothing on a false rung. Each one
writes its result into its last operand. That operand may also be one it reads:
`CONCAT(Msg,Suffix,Msg)` adds `Suffix` to the end of `Msg`.

Characters are counted from **1**: in `'hello'`, `h` is character 1 and `o` is character 5.

## CONCAT — Join Two STRINGs [#concat--join-two-strings]

Joins two STRINGs, Source A then Source B, into the destination STRING.

| Name      | Type     |
| --------- | -------- |
| `sourceA` | `STRING` |
| `sourceB` | `STRING` |
| `dest`    | `STRING` |

```ladder
XIC(ShowAlarm)CONCAT(AlarmPrefix,AlarmText,DisplayLine)
```

With `AlarmPrefix` holding `'ALARM: '` and `AlarmText` holding `'Low oil'`, `DisplayLine`
becomes `'ALARM: Low oil'`. If the two hold more than 82 characters together, the result keeps
the first 82 and Studio shows a warning.

## FIND — Find Text in a STRING [#find--find-text-in-a-string]

Finds where the Search STRING first appears in the Source STRING, from the Start character on, and stores its position.

| Name     | Type                            |
| -------- | ------------------------------- |
| `source` | `STRING`                        |
| `search` | `STRING`                        |
| `start`  | `DINT`, `INT` or `SINT`         |
| `result` | `DINT`, `INT`, `SINT` or `REAL` |

```ladder
XIC(CodeReady)FIND(Barcode,Separator,1,SeparatorAt)
```

With `Barcode` holding `'AB-123'` and `Separator` holding `'-'`, `SeparatorAt` becomes `3`.
When the text is not there, the result is `0`. Upper and lower case are different characters,
so searching `'hello'` for `'H'` finds nothing.

`start` says where the search begins, and it must be a character the source has: `1` to its
`LEN`. Outside that, the result is `0` and Studio shows a warning. A typed-in `start` of `0` is
refused before the program runs.

## MID — Take Part of a STRING [#mid--take-part-of-a-string]

Copies Qty characters of the Source STRING, from the Start character on, into the destination STRING.

| Name     | Type                    |
| -------- | ----------------------- |
| `source` | `STRING`                |
| `qty`    | `DINT`, `INT` or `SINT` |
| `start`  | `DINT`, `INT` or `SINT` |
| `dest`   | `STRING`                |

`qty` comes before `start`. `MID(Barcode,3,4,PartNumber)` takes three characters, starting at
character 4:

```ladder
XIC(CodeReady)MID(Barcode,3,4,PartNumber)
```

With `Barcode` holding `'AB-123'`, `PartNumber` becomes `'123'`. If `qty` runs past the end of
the source, `MID` takes the rest and Studio shows a warning. If `start` is not a character the
source has, `dest` is left as it was.

## INSERT — Put Text Into a STRING [#insert--put-text-into-a-string]

Puts the Source B STRING into the Source A STRING at the Start character and stores the result in the destination STRING.

| Name      | Type                    |
| --------- | ----------------------- |
| `sourceA` | `STRING`                |
| `sourceB` | `STRING`                |
| `start`   | `DINT`, `INT` or `SINT` |
| `dest`    | `STRING`                |

```ladder
XIC(AddUnit)INSERT(Reading,Unit,5,Shown)
```

With `Reading` holding `'25.5'` and `Unit` holding `' C'`, `Shown` becomes `'25.5 C'`. The text
goes in before the `start` character, so `start` may be `1` to one past the end of `sourceA`,
and one past the end adds it after the last character. If the result would be longer than 82
characters, `dest` is left as it was and Studio shows a warning.

## DELETE — Take Text Out of a STRING [#delete--take-text-out-of-a-string]

Removes Qty characters of the Source STRING, from the Start character on, and stores the rest in the destination STRING.

| Name     | Type                    |
| -------- | ----------------------- |
| `source` | `STRING`                |
| `qty`    | `DINT`, `INT` or `SINT` |
| `start`  | `DINT`, `INT` or `SINT` |
| `dest`   | `STRING`                |

Like `MID`, `qty` comes before `start`:

```ladder
XIC(CodeReady)DELETE(Barcode,3,1,Suffix)
```

With `Barcode` holding `'AB-123'`, `Suffix` becomes `'123'`: the first three characters are
removed. If `qty` runs past the end, everything from `start` on is removed and Studio shows a
warning.

## A STRING with a broken LEN [#a-string-with-a-broken-len]

`LEN` can be set on its own, to a number outside `0` to `82`. A string instruction never reads
such a STRING. It leaves `dest` as it was, or stores `0` for `FIND`, and Studio shows a warning
that names the STRING.

## Common Mistakes [#common-mistakes]

- Putting text in quotes into a string instruction, such as `CONCAT(Msg,' C',Msg)`. Put the text
  in a `STRING` tag and use the tag. Text in quotes goes only in [`MOVE`](https://rungs.dev/docs/ladder-logic/instructions/move) and the
  [compare instructions](https://rungs.dev/docs/ladder-logic/instructions/compare).
- Swapping `qty` and `start` in `MID` and `DELETE`. `qty` comes first.
- Typing a `qty` or a `start` with a decimal point, such as `1.0`. They take whole numbers
  only, so type `1`.
- Counting characters from `0`. The first character is `1`.

## Related [#related]

- [MOVE](https://rungs.dev/docs/ladder-logic/instructions/move) — copy text into a STRING
- [Compare](https://rungs.dev/docs/ladder-logic/instructions/compare) — compare two STRINGs
- [String conversion](https://rungs.dev/docs/ladder-logic/instructions/string-conversion) — numbers to text and back, and letter case
- [String instructions in Structured Text](https://rungs.dev/docs/structured-text/instructions/string)