ASCII control characters
ASCII is the American Standard Code for Information Interchange. There are 128 ASCII characters of which the first 32 and the last are 'control characters'.
- Task
Show how your language might treat control characters en bloc by using an enum, an enum like structure or other approach to associate their names with their ASCII values thereby enabling them to be retrieved or listed by name.
Technically, the 33rd character 'space' is a printable character, not a control character, though you may treat it as the latter for the purposes of this task.
- Reference
Ada
In Ada, a character type is an enumeration type with at least one literal that is a character literal. The predefined type Character
is a character type with 256 values representing the Latin-1 character set; the first 128 values of Character are the ASCII character set. However, Character is a magic enumeration type: the values which are control characters have no literals. A user of the language cannot declare such a type. This makes naming the control characters more difficult than if they had literals.
Each value of an enumeration type has an associated position number. The first value has position number zero, increasing by one for each subsequent value. These correspond to the numeric values of ASCII, and may be used to refer to the control characters using the 'Val
attribute. For example, the line-feed control character may be referred to with Character'Val (10)
. (The position number for a character can be obtained using the 'Pos
attribute.)
The predefined package Ada.Characters.Latin_1
contains constants that give names to all the ASCII control characters (and many other characters as well). The first few are
NUL : constant Character := Character'Val (0);
SOH : constant Character := Character'Val (1);
STX : constant Character := Character'Val (2);
ETX : constant Character := Character'Val (3);
EOT : constant Character := Character'Val (4);
Of course, one can also declare character types:
type ASCII is (NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL,
BS, HT, LF, VT, FF, CR, SO, SI,
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB,
CAN, EM, SUB, ESC, FS, GS, RS, US,
' ', '!', '"', '#', '$', '%', '&', ''',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', DEL);
You can then refer to the control characters by their enumeration literals: LF
.
ALGOL 68
Algol 68 doesn't have ENUMs but it is easy to create constants, this example shows how a facility similar to Go's iota can be implemented.
Note space is a standard Algol 68 transput (I/O) routine, so spc is used for the spacce character.
# create constants for the ASCII control characters (0-127) #
INT char value := -1;
# increments and returns the next value for a character #
PROC next char = CHAR: REPR ( char value +:= 1 );
CHAR nul = next char;
CHAR soh = next char;
CHAR stx = next char;
CHAR etx = next char;
CHAR eot = next char;
CHAR enq = next char;
CHAR ack = next char;
CHAR bel = next char;
CHAR bs = next char;
CHAR ht = next char;
CHAR lf = next char;
CHAR vt = next char;
CHAR ff = next char;
CHAR cr = next char;
CHAR so = next char;
CHAR si = next char;
CHAR dle = next char;
CHAR dc1 = next char;
CHAR dc2 = next char;
CHAR dc3 = next char;
CHAR dc4 = next char;
CHAR nak = next char;
CHAR syn = next char;
CHAR etb = next char;
CHAR can = next char;
CHAR em = next char;
CHAR sub = next char;
CHAR esc = next char;
CHAR fs = next char;
CHAR gs = next char;
CHAR rs = next char;
CHAR us = next char;
CHAR spc = " "; # using spc as space is a standard transput procedure #
CHAR del = REPR 127;
# e.g.: #
# print( ( nul, soh, ht, lf ) ); prints the characters themselve #
# print( ( ABS nul, ABS soh, ABS ht, ABS lf, lf ) ); prints the characters as #
# integers: +0 +1 +9 +10 #
C
enum: char {
nul,
soh,
stx,
etx,
eot,
enq,
ack,
bel,
bs,
ht,
lf,
vt,
ff,
cr,
so,
si,
dle,
dc1,
dc2,
dc3,
dc4,
nak,
syn,
etb,
can,
em,
sub,
esc,
fs,
gs,
rs,
us,
space,
del = 127
};
C++
#include <cstdint>
#include <iostream>
#include <map>
#include <string>
enum ASCIIControlChar {
NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL,
BS, HT, LF, VT, FF, CR, SO, SI,
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB,
CAN, EM, SUB, ESC, FS, GS, RS, US, DEL
};
struct Data {
std::string text;
uint32_t number;
};
std::map<ASCIIControlChar, Data> ascii_map = {
{ NUL, Data("Null", 0) }, { SOH, Data("Start of Heading", 1) }, { STX, Data("Start of Text", 2) },
{ ETX, Data("End of Text", 3) }, { EOT, Data("End of Transmission", 4) },
{ ENQ, Data("Enquiry", 5) }, { ACK, Data("Acknowledge", 6) }, { BEL, Data("Bell", 7) },
{ BS, Data("Backspace", 8) }, { HT, Data("Horizontal Tab", 9) }, { LF, Data("Line Feed", 10) },
{ VT, Data("Vertical Tabulation", 11) }, { FF, Data("Form Feed", 12) },
{ CR, Data("Carriage Return", 13) }, { SO, Data("Shift Out", 14) }, { SI, Data("Shift In", 15) },
{ DLE, Data("Data Link Escape", 16) }, { DC1, Data("Device Control One (XON)", 17) },
{ DC2, Data("Device Control Two", 18) }, { DC3, Data("Device Control Three (XOFF)", 19) },
{ DC4, Data("Device Control Four", 20) }, { NAK, Data("Negative Acknowledge", 21) },
{ SYN, Data("Synchronous Idle", 22) }, { ETB, Data("End of Transmission Block", 23) },
{ CAN, Data("Cancel", 24) }, { EM, Data("End of Medium", 25) }, { SUB, Data("Substitute", 26) },
{ ESC, Data("Escape", 27) }, { FS, Data("File Separator", 28) }, { GS, Data("Group Separator", 29) },
{ RS, Data("Record Separator", 30) }, { US, Data("Unit Separator", 31) }, { DEL, Data("Delete", 127) }
};
int main() {
ASCIIControlChar etb = ASCIIControlChar::ETB;
std::cout << ascii_map[etb].text << " " << ascii_map[etb].number << std::endl;
ASCIIControlChar del = ASCIIControlChar::DEL;
std::cout << ascii_map[del].text << " " << ascii_map[del].number << std::endl;
}
- Output:
End of Transmission Block 23 Delete 127
D
import std.ascii.ControlChar;
FreeBASIC
Enum AsciiControlChar
NUL = &H00 'Null
SOH = &H01 'Star of Header
STX = &H02 'Start of Text
ETX = &H03 'End of Text
EOT = &H04 'End of Transmission
ENQ = &H05 'Enquiry
ACK = &H06 'Acknowledge
BEL = &H07 'Bell
BS = &H08 'BackSpace
HT = &H09 'Horizontal Tabulation
LF = &H0A 'Line Feed
VT = &H0B 'Vertical Tabulation
FF = &H0C 'Form Feed
CR = &H0D 'Carriage Return
SO = &H0E 'Shift Out
SI = &H0F 'Shift In
DLE = &H10 'Data Link Escape
DC1 = &H11 'Device Control 1 (XON)
DC2 = &H12 'Device Control 2
DC3 = &H13 'Device Control 3 (XOFF)
DC4 = &H14 'Device Control 4
NAK = &H15 'Negative acknowledge
SYN = &H16 'Synchronous Idle
ETB = &H17 'End of Transmission Block
CAN = &H18 'Cancel
EM = &H19 'End of Medium
SUB_ = &H1A 'Substitute
ESC = &H1B 'Escape
FS = &H1C 'File Separator
GS = &H1D 'Group Separator
RS = &H1E 'Record Separator
US = &H1F 'Unit Separator
SP = &H20 'Space
DEL = &H7F 'Delete
End Enum
Print(Hex(AsciiControlChar.CR))
Print(Hex(AsciiControlChar.DEL))
Sleep
- Output:
D 7F
FutureBasic
local fn ASCIIControlInfo( asciiControl as CFStringRef ) as CFStringRef
asciiControl = lcase(asciiControl)
if fn StringIsEqual( asciiControl, @"space" ) then asciiControl = @"spc"
if fn StringIsEqual( asciiControl, @"delete" ) then asciiControl = @"del"
CFStringRef result
CFDictionaryRef asciiDict = @{
@"nul": @"0 0 000 NULL",
@"soh": @"1 01 001 Start of heading",
@"soh": @"2 02 002 Start of text",
@"etx": @"3 03 003 End of text",
@"eot": @"4 04 004 End of transmission",
@"enq": @"5 05 005 Enquiry",
@"ack": @"6 06 006 Acknowledge",
@"bel": @"7 07 007 Bell",
@"bs" : @"8 08 010 Backspace",
@"ht" : @"9 09 011 Horizontal tab",
@"lf" : @"10 0A 012 Line feed",
@"vt" : @"11 0B 013 Vertical tab",
@"ff" : @"12 0C 014 New page/form feed",
@"cr" : @"13 0D 015 Carriage return",
@"so" : @"14 0E 016 Shift out",
@"si" : @"15 0F 017 Shift in",
@"dle": @"16 10 020 Data link escape",
@"dc1": @"17 11 021 Device control 1",
@"dc2": @"18 12 022 Device control 2",
@"dc3": @"19 13 023 Device control 3",
@"dc4": @"20 14 024 Device control 4",
@"nak": @"21 15 025 Negative acknowledge",
@"syn": @"22 16 026 Synchronous idle",
@"etb": @"23 17 027 End of transmission block",
@"can": @"24 18 030 Cancel",
@"em" : @"25 19 031 End of medium",
@"sub": @"26 1A 032 Substitute",
@"esc": @"27 1B 033 Escape",
@"fs" : @"28 1C 034 File separator",
@"gs" : @"29 1D 035 Group separator",
@"rs" : @"30 1E 036 Record separator",
@"us" : @"31 1F 037 Unit separator",
@"spc": @"32 20 040 Space",
@"del": @"127 7F 177 Delete"}
if ( asciiDict[asciiControl] )
result = fn StringWithFormat( @"Ctl\t\tDec\t\tHex\t\tOct\t\tDescription\n%@\t\t%@\n", asciiControl, asciiDict[asciiControl] )
else
result = fn StringWithFormat( @"Error: %@ is not an ASCII control\n", asciiControl )
end if
end fn = result
print fn ASCIIControlInfo( @"vt" )
print fn ASCIIControlInfo( @"CR" )
print fn ASCIIControlInfo( @"Si" )
print fn ASCIIControlInfo( @"ESC" )
print fn ASCIIControlInfo( @"xx" )
print fn ASCIIControlInfo( @"Space" )
print fn ASCIIControlInfo( @"DELETE" )
HandleEvents
Ctl Dec Hex Oct Description nul 0 0 000 NULL Ctl Dec Hex Oct Description vt 11 0B 013 Vertical tab Ctl Dec Hex Oct Description cr 13 0D 015 Carriage return Ctl Dec Hex Oct Description si 15 0F 017 Shift in Ctl Dec Hex Oct Description esc 27 1B 033 Escape Error: xx is not an ASCII control Ctl Dec Hex Oct Description spc 32 20 040 Space Ctl Dec Hex Oct Description del 127 7F 177 Delete
Go
Go's support for enums is unconventional in that they are basically a bunch of constants with which a type name may be associated.
The pre-declared identifier 'iota' is typically used with enums and represents successive untyped integer constants, starting from zero though (as here) the sequence may be interrupted by assigning a new value.
package main
import "fmt"
type Ctrl int
const (
nul Ctrl = iota
soh
stx
etx
eot
enq
ack
bel
bs
ht
lf
vt
ff
cr
so
si
dle
dc1
dc2
dc3
dc4
nak
syn
etb
can
em
sub
esc
fs
gs
rs
us
space
del = 127
)
func main() {
// print some specimen values
fmt.Println(cr)
fmt.Println(del)
}
- Output:
13 127
Java
public final class ASCIIControlCharacters {
public static void main(String[] args) {
ASCIIControlChar syn = ASCIIControlChar.SYN;
System.out.println(syn.name() + " " + syn.getText() + " " + syn.getNumber());
ASCIIControlChar del = ASCIIControlChar.DEL;
System.out.println(del.name() + " " + del.getText() + " " + del.getNumber());
}
private enum ASCIIControlChar {
NUL("Null", 0), SOH("Start of Heading", 1), STX("Start of Text", 2), ETX("End of Text", 3),
EOT("End of Transmission", 4), ENQ("Enquiry", 5), ACK("Acknowledge", 6), BEL("Bell", 7),
BS("Backspace", 8), HT("Horizontal Tab", 9), LF("Line Feed", 10), VT("Vertical Tabulation", 11),
FF("Form Feed", 12), CR("Carriage Return", 13), SO("Shift Out", 14), SI("Shift In", 15),
DLE("Data Link Escape", 16), DC1("Device Control One (XON)", 17), DC2("Device Control Two", 18),
DC3("Device Control Three (XOFF)", 19), DC4("Device Control Four", 20),
NAK("Negative Acknowledge", 21), SYN("Synchronous Idle", 22), ETB("End of Transmission Block", 23),
CAN("Cancel", 24), EM("End of Medium", 25), SUB("Substitute", 26), ESC("Escape", 27),
FS("File Separator", 28), GS("Group Separator", 29), RS("Record Separator", 30),
US("Unit Separator", 31), DEL("Delete", 127);
public String getText() {
return text;
}
public int getNumber() {
return number;
}
private ASCIIControlChar(String aText, int aNumber) {
text = aText;
number = aNumber;
}
private String text;
private int number;
}
}
- Output:
SYN Synchronous Idle 22 DEL Delete 127
jq
def ascii_control_character_names: [
"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
"bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
"can", "em", "sub", "esc", "fs", "gs", "rs", "us",
"space", "del"
];
def Ctrl:
ascii_control_character_names as $a
| reduce range(0; $a|length) as $i ({}; .[$a[$i]] = $i)
| .["del"] = 127;
def examples:
Ctrl as $Ctrl
| "Ctrl.cr => \($Ctrl.cr)",
"Ctrl.del => \($Ctrl.del)",
"Ctrl.space => \($Ctrl.space)";
examples
- Output:
Ctrl.cr => 13 Ctrl.del => 127 Ctrl.space => 32
Julia
Note that Julia recognizes many non-ASCII characters with values above 127 as control Char as well.
julia> filter(iscntrl, Char(0):Char(127))
33-element Vector{Char}:
'\0': ASCII/Unicode U+0000 (category Cc: Other, control)
'\x01': ASCII/Unicode U+0001 (category Cc: Other, control)
'\x02': ASCII/Unicode U+0002 (category Cc: Other, control)
'\x03': ASCII/Unicode U+0003 (category Cc: Other, control)
'\x04': ASCII/Unicode U+0004 (category Cc: Other, control)
'\x05': ASCII/Unicode U+0005 (category Cc: Other, control)
'\x06': ASCII/Unicode U+0006 (category Cc: Other, control)
'\a': ASCII/Unicode U+0007 (category Cc: Other, control)
'\b': ASCII/Unicode U+0008 (category Cc: Other, control)
'\t': ASCII/Unicode U+0009 (category Cc: Other, control)
'\n': ASCII/Unicode U+000A (category Cc: Other, control)
'\v': ASCII/Unicode U+000B (category Cc: Other, control)
'\f': ASCII/Unicode U+000C (category Cc: Other, control)
'\r': ASCII/Unicode U+000D (category Cc: Other, control)
'\x0e': ASCII/Unicode U+000E (category Cc: Other, control)
'\x0f': ASCII/Unicode U+000F (category Cc: Other, control)
'\x10': ASCII/Unicode U+0010 (category Cc: Other, control)
'\x11': ASCII/Unicode U+0011 (category Cc: Other, control)
'\x12': ASCII/Unicode U+0012 (category Cc: Other, control)
'\x13': ASCII/Unicode U+0013 (category Cc: Other, control)
'\x14': ASCII/Unicode U+0014 (category Cc: Other, control)
'\x15': ASCII/Unicode U+0015 (category Cc: Other, control)
'\x16': ASCII/Unicode U+0016 (category Cc: Other, control)
'\x17': ASCII/Unicode U+0017 (category Cc: Other, control)
'\x18': ASCII/Unicode U+0018 (category Cc: Other, control)
'\x19': ASCII/Unicode U+0019 (category Cc: Other, control)
'\x1a': ASCII/Unicode U+001A (category Cc: Other, control)
'\e': ASCII/Unicode U+001B (category Cc: Other, control)
'\x1c': ASCII/Unicode U+001C (category Cc: Other, control)
'\x1d': ASCII/Unicode U+001D (category Cc: Other, control)
'\x1e': ASCII/Unicode U+001E (category Cc: Other, control)
'\x1f': ASCII/Unicode U+001F (category Cc: Other, control)
'\x7f': ASCII/Unicode U+007F (category Cc: Other, control)
An enum can be used for the task:
@enum Control begin
nul = 0
soh = 1
stx = 2
etx = 3
eot = 4
enq = 5
ack = 6
bel = 7
bs = 8
ht = 9
lf = 10
vt = 11
ff = 12
cr = 13
so = 14
si = 15
dle = 16
dc1 = 17
dc2 = 18
dc3 = 19
dc4 = 20
nak = 21
syn = 22
etb = 23
can = 24
em = 25
sub = 26
esc = 27
fs = 28
gs = 29
rs = 30
us = 31
del = 127
end
display(nul), display(ht), display(us), display(del)
A named tuple is a another way to reference such control Chars by name:
const CNTRL = (
nul = 0,
soh = 1,
stx = 2,
etx = 3,
eot = 4,
enq = 5,
ack = 6,
bel = 7,
bs = 8,
ht = 9,
lf = 10,
vt = 11,
ff = 12,
cr = 13,
so = 14,
si = 15,
dle = 16,
dc1 = 17,
dc2 = 18,
dc3 = 19,
dc4 = 20,
nak = 21,
syn = 22,
etb = 23,
can = 24,
em = 25,
sub = 26,
esc = 27,
fs = 28,
gs = 29,
rs = 30,
us = 31,
del = 127,
)
@show CNTRL.nul, CNTRL.ht, CNTRL.us, CNTRL.del
- Output:
nul::Control = 0 ht::Control = 9 us::Control = 31 del::Control = 127 (CNTRL.nul, CNTRL.ht, CNTRL.us, CNTRL.del) = (0, 9, 31, 127)
Maxima
Those character can be put in a list and can be found their ASCII numbers.
/* List of characters that are not constituents (constituent is a graphic character but not a space character) */
block(makelist(ascii(i),i,0,127),sublist(%%,lambda([x],not constituent(x))));
/* [,"�","�","�","�","�","�","�","�","�","
","�","�","
","�","�","�","�","�","�","�","�","�","�","�","�","�","�","�","�","�","�"," ","�"] */
/* Ascii numbers of characters that are not constituents */
map(cint,%);
/* [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,127] */
Nim
We define an enumeration type.
For each element, Nim allows to specify its integer value and its string representation. Here, the integer value is implicit (starting from zero) except for DEL whose value must be specified. As we use the standard names for the elements, we don’t have to specify the string representation.
The integer value is obtained with function ord
and the string representation with function$
.
import std/strutils
type AsciiControlChar {.pure.} = enum NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL,
BS, HT, LF, VT, FF, CR, SO, SI,
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB,
CAN, EM, SUB, ESC, FS, GS, RS, US,
SP, DEL = 0x7F
echo ' ', CR, " = ", ord(CR).toHex(2)
echo DEL, " = ", ord(DEL).toHex(2)
- Output:
CR = 0D DEL = 7F
Perl
use charnames ":loose";
# There is no EM, use END OF MEDIUM.
# Do not confuse BEL with BELL. Starting in Perl 5.18, BELL refers to unicode emoji 0x1F514. ALERT is an alias for BEL.
# compile time literal
"\N{nul}\N{soh}\N{stx}\N{etx}\N{eot}\N{enq}\N{ack}\N{bel}\N{bs}\N{ht}\N{lf}\N{vt}\N{ff}\N{cr}\N{so}\N{si}\N{dle}\N{dc1}\N{dc2}\N{dc3}\N{dc4}\N{nak}\N{syn}\N{etb}\N{can}\N{end of medium}\N{sub}\N{esc}\N{fs}\N{gs}\N{rs}\N{us}\N{space}\N{delete}"
# run time
charnames::string_vianame $_;
Phix
enum nul=0, soh, stx, etx, eot, enq, ack, bel, bs, ht, lf, vt, ff, cr, so, si,
dle, dc1, dc2, dc3, dc4, nak, syn, etb, can, em, sub, esc, fs, gs, rs, us,
space, del = 127
?cr
?del
- Output:
13 127
Raku
There doesn't seem to really be a point or a purpose to this task other than creating a enumeration...
'space' is absolutely NOT a control character. Pretending it is is just completely incorrect.
enum C0 (|(^32).map({ (0x2400 + $_).chr => $_ }), '␡' => 127);
printf "Ord: %3d, Unicode: %s, Enum: %s\n", $_, .uniname, C0($_)
for (^128).grep: {.chr ~~ /<:Cc>/}
- Output:
Ord: 0, Unicode: <control-0000>, Enum: ␀ Ord: 1, Unicode: <control-0001>, Enum: ␁ Ord: 2, Unicode: <control-0002>, Enum: ␂ Ord: 3, Unicode: <control-0003>, Enum: ␃ Ord: 4, Unicode: <control-0004>, Enum: ␄ Ord: 5, Unicode: <control-0005>, Enum: ␅ Ord: 6, Unicode: <control-0006>, Enum: ␆ Ord: 7, Unicode: <control-0007>, Enum: ␇ Ord: 8, Unicode: <control-0008>, Enum: ␈ Ord: 9, Unicode: <control-0009>, Enum: ␉ Ord: 10, Unicode: <control-000A>, Enum: ␊ Ord: 11, Unicode: <control-000B>, Enum: ␋ Ord: 12, Unicode: <control-000C>, Enum: ␌ Ord: 13, Unicode: <control-000D>, Enum: ␍ Ord: 14, Unicode: <control-000E>, Enum: ␎ Ord: 15, Unicode: <control-000F>, Enum: ␏ Ord: 16, Unicode: <control-0010>, Enum: ␐ Ord: 17, Unicode: <control-0011>, Enum: ␑ Ord: 18, Unicode: <control-0012>, Enum: ␒ Ord: 19, Unicode: <control-0013>, Enum: ␓ Ord: 20, Unicode: <control-0014>, Enum: ␔ Ord: 21, Unicode: <control-0015>, Enum: ␕ Ord: 22, Unicode: <control-0016>, Enum: ␖ Ord: 23, Unicode: <control-0017>, Enum: ␗ Ord: 24, Unicode: <control-0018>, Enum: ␘ Ord: 25, Unicode: <control-0019>, Enum: ␙ Ord: 26, Unicode: <control-001A>, Enum: ␚ Ord: 27, Unicode: <control-001B>, Enum: ␛ Ord: 28, Unicode: <control-001C>, Enum: ␜ Ord: 29, Unicode: <control-001D>, Enum: ␝ Ord: 30, Unicode: <control-001E>, Enum: ␞ Ord: 31, Unicode: <control-001F>, Enum: ␟ Ord: 127, Unicode: <control-007F>, Enum: ␡
RPL
There is no enum in RPL, but we can create global variables, each containing a specific control character, which are then available to all programs in the same directory tree.
≪ { NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US }
0 31 FOR ctrl
ctrl CHR OVER ctrl GET STO
NEXT DROP
127 CHR 'DEL' STO
≫ '→ASCII' STO
Rust
The AsciiChar enum is abridged from a currently private enum in Rust core's std::char.
#[derive(Clone, Copy, Debug)]
pub enum AsciiChar {
Null = 0,
StartOfHeading = 1,
StartOfText = 2,
EndOfText = 3,
EndOfTransmission = 4,
Enquiry = 5,
Acknowledge = 6,
Bell = 7,
Backspace = 8,
CharacterTabulation = 9,
LineFeed = 10,
LineTabulation = 11,
FormFeed = 12,
CarriageReturn = 13,
ShiftOut = 14,
ShiftIn = 15,
DataLinkEscape = 16,
DeviceControlOne = 17,
DeviceControlTwo = 18,
DeviceControlThree = 19,
DeviceControlFour = 20,
NegativeAcknowledge = 21,
SynchronousIdle = 22,
EndOfTransmissionBlock = 23,
Cancel = 24,
EndOfMedium = 25,
Substitute = 26,
Escape = 27,
InformationSeparatorFour = 28,
InformationSeparatorThree = 29,
InformationSeparatorTwo = 30,
InformationSeparatorOne = 31,
Space = 32,
ExclamationMark = 33,
QuotationMark = 34,
NumberSign = 35,
DollarSign = 36,
PercentSign = 37,
Ampersand = 38,
Apostrophe = 39,
LeftParenthesis = 40,
RightParenthesis = 41,
Asterisk = 42,
PlusSign = 43,
Comma = 44,
HyphenMinus = 45,
FullStop = 46,
Solidus = 47,
Colon = 58,
Semicolon = 59,
LessThanSign = 60,
EqualsSign = 61,
GreaterThanSign = 62,
QuestionMark = 63,
CommercialAt = 64,
LeftSquareBracket = 91,
ReverseSolidus = 92,
RightSquareBracket = 93,
CircumflexAccent = 94,
LowLine = 95,
GraveAccent = 96,
LeftCurlyBracket = 123,
VerticalLine = 124,
RightCurlyBracket = 125,
Tilde = 126,
Delete = 127,
}
fn main() {
println!("Value Control char name\n{}", "_".repeat(32));
for i in 0_u8..=127 {
unsafe {
// no need to check this, it is all 0 <= c <= 127, transmute is in range
let ch = char::from_u32_unchecked(i as u32);
if ch.is_ascii_control() {
let ascii: AsciiChar = std::mem::transmute::<_, AsciiChar>(i);
println!("{:>3} {:?}", i, ascii);
}
}
}
}
- Output:
Value Control char name ________________________________ 0 Null 1 StartOfHeading 2 StartOfText 3 EndOfText 4 EndOfTransmission 5 Enquiry 6 Acknowledge 7 Bell 8 Backspace 9 CharacterTabulation 10 LineFeed 11 LineTabulation 12 FormFeed 13 CarriageReturn 14 ShiftOut 15 ShiftIn 16 DataLinkEscape 17 DeviceControlOne 18 DeviceControlTwo 19 DeviceControlThree 20 DeviceControlFour 21 NegativeAcknowledge 22 SynchronousIdle 23 EndOfTransmissionBlock 24 Cancel 25 EndOfMedium 26 Substitute 27 Escape 28 InformationSeparatorFour 29 InformationSeparatorThree 30 InformationSeparatorTwo 31 InformationSeparatorOne 127 Delete
V (Vlang)
enum Ctrl {
nul = 0
soh
stx
etx
eot
enq
ack
bel
bs
ht
lf
vt
ff
cr
so
si
dle
dc1
dc2
dc3
dc4
nak
syn
etb
can
em
sub
esc
fs
gs
rs
us
space
del = 127
}
fn main() {
println(int(Ctrl.cr))
println(int(Ctrl.del))
}
- Output:
13 127
Wren
Wren doesn't have enums built into the language but can create them dynamically at runtime. However, such enums need to have consecutive integer values.
Here, we create instead a Group which can contain any values in any order.
import "./dynamic" for Group
var names = [
"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
"bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
"can", "em", "sub", "esc", "fs", "gs", "rs", "us",
"space", "del"
]
var values = (0..32).toList + [127]
var Ctrl = Group.create("Ctrl", names, values)
// print some specimen values
System.print(Ctrl.cr)
System.print(Ctrl.del)
- Output:
13 127
XPL0
def NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, BS, HT, LF, VT, FF, CR, SO,
SI, DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS,
RS, US, Space, DEL=127;
[IntOut(0, NUL); CrLf(0);
IntOut(0, FF); CrLf(0);
IntOut(0, Space); CrLf(0);
IntOut(0, Del); CrLf(0);
]
- Output:
0 12 32 127