Руководство по программированию на c#. преобразование строки в число

Использование функции stoi ()

Функция atoi () используется для возврата числа путем преобразования строкового значения в целое число. Первый аргумент этой функции является обязательным, а остальные аргументы — необязательными. Синтаксис этой функции приведен ниже.

Синтаксис:

Создайте файл C ++ со следующим кодом для преобразования строки в целое число с помощью функции stoi (). После выполнения кода входное значение, полученное от пользователя, будет преобразовано в число и распечатано, если входное значение является допустимым числом. Если входное значение содержит какой-либо алфавитный или нечисловой символ, будет сгенерировано исключение invalid_argument и будет напечатано сообщение об ошибке.

Выход:

Следующий вывод появится, если после выполнения кода в качестве входных данных будет выбрано 4577.

Следующий вывод появится, если после выполнения кода будет принято приветствие в качестве ввода.

Явные числовые преобразования

В следующей таблице показаны предопределенные явные преобразования между встроенными числовыми типами, для которых нет :

Исходный тип Кому
sbyte , , или либо
byte
short , , , , или
ushort , или
int , , , , , или
uint , , , или
long , , , , , , , или
ulong , , , , , , , или
float , , , , , , , , , или
double , , , , , , , , , , или
decimal , , , , , , , , , , или
nint , , , , , , или
nuint , , , , , , или

Примечание

Явное числовое преобразование может привести к утрате данных или созданию исключения, обычно OverflowException.

Также обратите внимание на следующее

  • При преобразовании значения целочисленного типа в другой целочисленный тип результат зависит от переполнения контекста проверки. В проверенном контексте преобразование выполняется успешно, если исходное значение находится в диапазоне конечного типа. В противном случае возникает исключение OverflowException. В непроверяемом контексте преобразование всегда завершается успешно и выполняется следующим образом.

    • Если исходный тип больше целевого, исходное значение усекается путем отбрасывания его «лишних» самых значимых битов. Результат затем обрабатывается как значение целевого типа.

    • Если исходный тип меньше целевого, исходное значение дополняется знаками или нулями, чтобы иметь тот же размер, что и целевой тип. Знаки добавляются, если исходный тип имеет знак. Если у исходного типа нет знака, добавляются нули. Результат затем обрабатывается как значение целевого типа.

    • Если исходный тип совпадает по размеру с целевым, исходное значение обрабатывается как значение целевого типа.

  • При преобразовании значения в целочисленный тип оно округляется в сторону нуля до ближайшего целого значения. Если итоговое целое значение находится вне диапазона целевого типа, возникает исключение OverflowException.

  • При преобразовании значения или в целочисленный тип оно округляется в сторону нуля до ближайшего целого значения. Если полученное целое значение выходит за пределы диапазона целевого типа, результат будет зависеть от контекста проверки переполнения. В проверенном контексте возникает исключение OverflowException, а в непроверенном контексте результатом будет неопределенное значение целевого типа.

  • При преобразовании из в значение округляется до ближайшего значения . Если значение слишком мало или слишком велико для типа , результатом будет ноль или бесконечность соответственно.

  • При преобразовании из или в исходное значение преобразуется в представление и при необходимости округляется до ближайшего числа после 28-го десятичного разряда. В зависимости от исходного значения возможны следующие результаты:

    • Если исходное значение слишком мало для представления в виде , результатом будет ноль.

    • Если исходное значение не является числом (NaN), равно бесконечности или слишком велико для представления в виде , возникает исключение OverflowException.

  • При преобразовании из в или исходное значение округляется до ближайшего значения или соответственно.

Строка Python в Int

Собственно, во многих случаях это необходимо. Например, вы читаете некоторые данные из файла, тогда они будут в формате String, и вам нужно будет преобразовать String в int.

Теперь перейдем к коду. Если вы хотите преобразовать число, представленное в строке, в int, вы должны использовать для этого функцию int(). Смотрите следующий пример:

num = '123'  # string data

# print the type

print('Type of num is :', type(num))

# convert using int()

num = int(num)

# print the type again

print('Now, type of num is :', type(num))

Результатом следующего кода будет:

Type of num is : <class 'str'>
Now, type of num is : <class 'int'>

Еscape-последовательности

С этой группой символов мы уже встречались в первом уроке. Символ \n. Он, как вы наверное помните, переносит выводимый текст на новую строку. Есть и другие эскейп-последовательности (иногда можно встретить название управляющие последовательности). Любая такая последовательность начинается с символа обратный слеш \.

Часто используемые escape-последовательности:

\n     — новая строка\t     — горизонтальная табуляция. Сдвигает выводимые данные вправо на ближайшую позицию табуляции. Обычно используется для выравнивания текста внутри строки.\’     — вывод символа ‘    — вывод символа «\\     — вывод символа \\?     — вывода символа ?

Как видите, последние четыре последовательности нужны лишь для того, чтобы вывести на экран символы «»», «’», «\» и «?». Дело в том, что если эти символы просто записать в формат-строку, то они не отобразятся на экране, а в некоторых случаях программа и вовсе не скомпилируется.

Следующая программа иллюстрирует работу escape-последовательностей.

Листинг 1.

#include <stdio.h> 
int main(void){
	printf("What is your name\?\n\tMy name\'s Bond! James Bond!\n");
	return 0;
}

Хотя escape-последовательности состоят из нескольких символов, но в потоке вывода они воспринимаются как цельный символ, который имеет своё собственное значение.

Итого, используя управляющие последовательности мы можем влиять на то, как данные будут выводиться на экране.

Использование функции atoi ()

Функция atoi () используется для возврата числа путем преобразования строки, созданной массивом символов, в целое число. Для использования этой функции необходимо включить заголовочный файл cstdlib.

Синтаксис:

Создайте файл C ++ со следующим кодом для преобразования строки чисел в целое число с помощью функции atoi (). Здесь функция strcpy () использовалась для преобразования строки в массив символов. Значение входной строки преобразовано в массив символов, и преобразованное значение было использовано в функции atoi () для получения целочисленного значения строки. Затем преобразованное целое число будет напечатано, если преобразование выполнено правильно.

Выход:

Следующие выходные данные появятся, если 6090 будет принято в качестве входных данных после выполнения кода.

Спецификация точности

В спецификации преобразования третье необязательное поле является спецификацией точности. Он состоит из точки ( ), за которой следует Неотрицательное десятичное целое число, которое в зависимости от типа конвертации указывает число символов строки, число десятичных разрядов или число значащих цифр для вывода.

В отличие от спецификации ширины, спецификация точности может вызывать либо усечение выходного значения, либо округление значения с плавающей запятой. Если параметр имеет значение 0, а преобразуемые данные равны 0, результат не будет содержать символы, как показано в следующем примере:

Если спецификация точности представляет собой звездочку (), аргумент из списка аргументов предоставляет значение. В списке аргументов аргумент должен предшествовать форматируемому значению, как показано в следующем примере:

Символ определяет либо интерпретацию, либо точность по умолчанию , если аргумент не указан, как показано в следующей таблице.

Влияние значений точности на тип

Тип Значение По умолчанию
, Точность определяет количество цифр после запятой. Точность по умолчанию — 13. Если точность равна 0, десятичная запятая не выводится, если не используется флаг .
, Точность не применяется. Символ выводится.
, , , , , Точность определяет минимальное выводимое количество цифр. Если количество цифр в аргументе меньше значения precision, выходное значение дополняется слева нулями. Значение не усекается, если число цифр превышает точность. Точность по умолчанию — 1.
, Выводимое количество знаков дробной части задается спецификацией точности. Последняя выводимая цифра округляется. Точность по умолчанию — 6. Если точность равна 0 или точка ( ) отображается без номера, то десятичная запятая не печатается.
, Значение точности задает количество цифр после десятичной запятой. Если десятичная запятая присутствует, перед ней присутствует по крайней мере одна цифра. Значение округляется до соответствующего количества цифр. Точность по умолчанию — 6. Если точность равна 0 или если точка ( ) отображается без числа после него, десятичная запятая не печатается.
, Точность определяет максимальное выводимое количество значащих цифр. Выводятся шесть значащих цифр, а конечные нули усекаются.
, Точность определяет максимальное количество выводимых символов. Символы, выходящие за рамки precision, не выводятся. Символы выводятся до тех пор, пока не будет найден символ null.

Спецификация размера аргумента

В спецификации преобразования поле size — это модификатор длины аргумента для описателя преобразования type. Префиксы полей размера для поля типа —,, , (строчные буквы L),,,,, , (прописные i), и — Укажите размер соответствующего аргумента — длинный или короткий, 32-разрядный или 64-разрядный, однобайтовый или расширенный символ — в зависимости от описателя преобразования, который они изменяют. Эти префиксы размера используются с символами type в семействах функций и для определения интерпретации размеров аргументов, как показано в следующей таблице. Поле size является необязательным для некоторых типов аргументов. Если префикс размера не указан, модуль форматирования использует целые аргументы, например подписанные или не подписанные , , , и типы перечисления как 32-разрядные типы , а аргументы , и с плавающей запятой используются как 64-разрядные типы . Такое поведение соответствует правилам повышения уровня аргументов по умолчанию для списков аргументов переменных. Дополнительные сведения об акциях аргументов см. в разделе аргументы многоточия и по умолчанию в постфиксных выражениях. В 32-разрядных и 64-разрядных системах спецификация преобразования для целочисленного аргумента 64-bit должна включать в себя префикс размера или . В противном случае поведение модуля форматирования не определено.

Некоторые типы имеют разный размер в 32-разрядном и 64-разрядном коде. Например, на 32 бита длиннее в коде, скомпилированном для x86, и на 64 бита длиннее в коде, скомпилированном для x64. Чтобы создать код форматирования для типов с переменным количеством байт, не зависящий от платформы, можно использовать модификатор размера аргумента с переменным количеством байт. Вместо этого используйте 64-разрядный модификатор размера аргумента и явно додвигайте тип аргумента переменной ширины в 64 бит. Модификатор размера аргумента, зависящий от Майкрософт (в верхнем регистре), обрабатывает целочисленные аргументы переменной ширины, но для переносимости рекомендуется использовать модификаторы для конкретного типа, и.

Префиксы размера для описателей формата функций printf и wprintf

Чтобы указать Используемый префикс Со спецификатором типа
, , , , или
, , , , или
, , , , или
, , , , или
или , , , , или
(строчная L) или , , , , , , или
(строчная L) , , , , или
(все символы в нижнем регистре) , , , , или
или (прописная i) , , , , или
или (прописная i) , , , , или
Однобайтовый символ или
Расширенный символ (строчная L) или или
Строка однобайтовых символов , или
Строка расширенных символов (строчная L) или , или

Типы и являются или на 32-разрядных платформах и или на 64-разрядных платформах. Префиксы (прописные i), , и size имеют правильную ширину аргумента для платформы.

В Visual C++ хотя является отдельным типом, он имеет то же внутреннее представление, что и тип .

Описатель типа или является синонимом в функциях и в функциях. Описатель типа,, или является синонимом в функциях и в функциях. Описатель типа или является синонимом в функциях и в функциях. Описатель типа,, или является синонимом в функциях и в функциях.

Примечание

Зависит от корпорации Майкрософт: Префиксы модификатора размера аргумента (прописные i),, и, и являются расширениями Майкрософт и не совместимы с ISO C. Префикс при использовании с данными типа и префикс (строчная L) при использовании с данными типа — расширения Майкрософт.

ValueError Exception при преобразовании строки Python в int

Сценарий: Если какая-либо из входных строк содержит цифру, не принадлежащую к десятичной системе счисления.

В приведенном ниже примере, если вы хотите преобразовать строку «A» в целочисленное значение A с основанием 16, и мы не передаем base = 16 в качестве аргумента методу int(), тогда это вызовет исключение ValueError.

Поскольку, хотя ‘A’ является шестнадцатеричным значением, оно не принадлежит к десятичной системе счисления, оно не будет рассматривать A как эквивалент десятичного числа 10, пока мы не передадим base = 16 в качестве аргумента в функцию int().

Пример:

string_num = 'A'
print("The data type of the input variable is:\n")
print(type(string_num))
result = int(string_num)

print(type(result))
print("The converted variable from string(base 16) to int:\n")
print(result) 

Выход:

The data type of the input variable is:

<class 'str'>
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    result = int(string_num)
ValueError: invalid literal for int() with base 10: 'A'

Исключение ValueError при преобразовании

При преобразовании строки в int вы можете получить исключение ValueError. Это исключение возникает, если строка, которую вы хотите преобразовать, не представляет никаких чисел.

Предположим, вы хотите преобразовать шестнадцатеричное число в целое. Но вы не передали аргумент base = 16 в функцию int(). Он вызовет исключение ValueError, если есть какая-либо цифра, которая не принадлежит десятичной системе счисления. Следующий пример иллюстрирует это исключение при преобразовании строки в int.

"""
    Scenario 1: The interpreter will not raise any exception but you get wrong data
"""
num = '12'  # this is a hexadecimal value

# the variable is considered as decimal value during conversion
print('The value is :', int(num))

# the variable is considered as hexadecimal value during conversion
print('Actual value is :', int(num, base=16))

"""
    Scenario 2: The interpreter will raise ValueError exception
"""

num = '1e'  # this is a hexadecimal value

# the variable is considered as hexadecimal value during conversion
print('Actual value of \'1e\' is :', int(num, base=16))

# the variable is considered as decimal value during conversion
print('The value is :', int(num))  # this will raise exception

В итоге результатом приведенного выше кода будет:

The value is : 12
Actual value is : 18
Actual value of '1e' is : 30
Traceback (most recent call last):
  File "/home/imtiaz/Desktop/str2int_exception.py", line 22, in 
    print('The value is :', int(num))  # this will raise exception
ValueError: invalid literal for int() with base 10: '1e'

Преобразование типов и класс Convert

Последнее обновление: 17.06.2017

Методы Parse и TryParse

Все примитивные типы имеют два метода, которые позволяют преобразовать строку к данному типу. Это методы Parse() и TryParse().

Метод Parse() в качестве параметра принимает строку и возвращает объект текущего типа. Например:

int a = int.Parse("10");
double b = double.Parse("23,56");
decimal c = decimal.Parse("12,45");
byte d = byte.Parse("4");
Console.WriteLine($"a={a}  b={b}  c={c}  d={d}");

Стоит отметить, что парсинг дробных чисел зависит от настроек текущей культуры. В частности, для получения числа double я передаю строку «23,56» с запятой в качестве разделителя.
Если бы я передал точку вместо запятой, то приложение выдало ошибку выполнения. На компьютерах с другой локалью, наоборот, использование запятой вместо точки выдало бы ошибку.

Чтобы не зависеть от культурных различий мы можем установить четкий формат с помощью класса NumberFormatInfo и его свойства
NumberDecimalSeparator:

using System;
using System.Globalization;

namespace FirstApp
{
    class Program
    {
        public static void Main(string[] args)
        {
            IFormatProvider formatter = new NumberFormatInfo { NumberDecimalSeparator = "." };
            double b = double.Parse("23.56", formatter);
        }
    }
}

В данном случае в качестве разделителя устанавливается точка. Однако тем не менее потенциально при использовании метода Parse мы можем столкнуться с ошибкой, например,
при передачи алфавитных символов вместо числовых. И в этом случае более удачным выбором будет применение метода TryParse().
Он пытается преобразовать строку к типу и, если преобразование прошло успешно, то возвращает true. Иначе возвращается false:

int number;
Console.WriteLine("Введите строку:");
string input = Console.ReadLine();

bool result = int.TryParse(input, out number);
if (result == true)
	Console.WriteLine("Преобразование прошло успешно");
else
	Console.WriteLine("Преобразование завершилось неудачно");

Если преобразование пройдет неудачно, то исключения никакого не будет выброшено, просто метод TryParse возвратит false, а переменная number будет содержать значение по умолчанию.

Convert

Класс Convert представляет еще один способ для преобразования значений. Для этого в нем определены следующие статические методы:

  • ToBoolean(value)

  • ToByte(value)

  • ToChar(value)

  • ToDateTime(value)

  • ToDecimal(value)

  • ToDouble(value)

  • ToInt16(value)

  • ToInt32(value)

  • ToInt64(value)

  • ToSByte(value)

  • ToSingle(value)

  • ToUInt16(value)

  • ToUInt32(value)

  • ToUInt64(value)

В качестве параметра в эти методы может передаваться значение различных примитивных типов, необязательно строки:

int n = Convert.ToInt32("23");
bool b = true;
double d = Convert.ToDouble(b);
Console.WriteLine($"n={n}  d={d}");

Однако опять же, как и в случае с методом Parse, если методу не удастся преобразовать значение к нужному типу, то он выбрасывает исключение FormatException.

НазадВперед

Конвертация с помощью String.format()

String.format() – это новый альтернативный метод, который можно использовать для преобразования Integer в объект String. Хотя целью этого метода является форматирование строки, его также можно использовать для преобразования.

Синтаксис

Есть два разных выражения:

public static String format(Locale l, String format, Object… args)

public static String format(String format, Object… args)

Параметры

Аргументы для этого метода:

  • l: локальный адрес для форматирования;
  • format: строка формата, которая включает спецификатор формата и иногда фиксированный текст;
  • args: аргументы, которые ссылаются на спецификаторы формата, установленные в параметре format.

Возвращаемое значение

Этот метод возвращает отформатированную строку в соответствии со спецификатором формата и указанными аргументами.

Пример

class Method3
{ 
  public static void main(String args[]) 
  { 
    int number = -1234; 
    String str = String.format("%d", number);
    System.out.println("With format method: string = " + str);
  } 
}

Модификатор * и #

Для некоторых из своих спецификаторов преобразования функция printf() поддерживает два дополнительных модификатора: * и #.

Непосредственное расположение # перед спецификаторами преобразования g, G, f, Е или e означает, что при выводе обязательно появится десятичная точка — даже если десятичных цифр нет. Если вы поставите # непосредственно перед x или X, то шестнадцатеричное число будет выведено с префиксом 0x. Если # будет непосредственно предшествовать спецификатору преобразования o, число будет выведено с ведущим нулем. К любым другим спецификаторам преобразования модификатор # применять нельзя. (В С99 модификатор # можно применять по отношению к преобразованию ; это значит, что обязательно будет выведена десятичная точка.)

Модификаторы минимальной ширины поля и точности можно передавать функции printf() не как константы, а как аргументы. Для этого в качестве заполнителя используйте звездочку (*). При сканировании строки формата функция printf() будет каждой звездочке * из этой строки ставить в соответствие очередной аргумент, причем в том порядке, в каком расположены аргументы. Например, при выполнении оператора, показанного на рис. 8.1, минимальная ширина поля будет равна 10 символам, точность — 4, а отображаться будет число 123.3.

В следующей программе показано применение обоих модификаторов # и *:

#include <stdio.h>

int main(void)
{
  printf("%x %#x\n", 10, 10);
  printf("%*.*f", 10, 4, 1234.34);

  return 0;
}

Рис. 8.1

Обратите внимание на то, каким образом звездочке (*) ставится в соответствие определенное значение

printf("%*.*f", 10.4, 123.3);
         | |     |     |
         '-+-----'     |
           |           |
           '-----------'

<<<>>>

Обработка данных других типов

Некоторые модификаторы в вызове функции printf() позволяют отображать целые числа типа short и long. Такие модификаторы можно использовать для следующих спецификаторов типа: d, i, o, u и x. Модификатор l (эль) в вызове функции printf() указывает, что за ним следуют данные типа long. Например, %ld означает, что надо выводить данные типа long int. После модификатора h функция printf() выведет целое значение в виде short. Например, %hu означает, что выводимые данные имеют тип short unsigned int.

Модификаторы l и h можно также применить к спецификатору n. Это делается с той целью, чтобы показать — соответствующий аргумент является указателем соответственно на длинное (long) или короткое (short) целое.

Если компилятор поддерживает обработку символов в расширенном 16-битном алфавите, добавленную Поправкой 1 от 1995 года (1995 Amendment 1), то для указания символа в расширенном 16-битном алфавите вы можете применять модификатор 1 для спецификатора преобразования c. Кроме того, для указания строки из символов в расширенном 16-битном алфавите можно применять модификатор 1 для спецификатора преобразования s.

Модификатор L может находиться перед спецификаторами преобразования с плавающей точкой e, f и g, и указывать этим, что преобразуется значение long double.

В Стандарте С99 вводится два новых модификатора формата: hh и ll. Модификатор hh можно применять для спецификаторов преобразования d, i, o, u, x или n. Он показывает, что соответствующий аргумент является значением signed или unsigned char или, в случае n, указателем на переменную signed char. Модификатор ll также можно применять для спецификаторов преобразования d, i, o, u, x или n. Он показывает, что соответствующий аргумент является значением signed или unsigned long long int или, в случае n, указателем на long long int. В С99 также разрешается применять l для спецификаторов преобразования с плавающей точкой a, е, f и g; впрочем, это не дает никакого результата.

На заметку В составе С99 имеются некоторые дополнительные модификаторы типа для функции printf(); о них рассказывается в части II.

Преобразование строки Python в int

Метод Python позволяет преобразовать любое значение типа String в целочисленное значение.

Синтаксис:

int(string_variable)

Пример:

string_num = '75846'
print("The data type of the input variable is:\n")
print(type(string_num))

result = int(string_num)
print("The data type of the input value after conversion:\n")
print(type(result))
print("The converted variable from string to int:\n")
print(result)

Выход:

The data type of the input variable is:
<class 'str'>
The data type of the input value after conversion:
<class 'int'>
The converted variable from string to int:
75846

Python также предоставляет нам эффективный вариант преобразования чисел и значений типа String в целочисленные значения с определенной базой в соответствии с системой счисления.

Синтаксис:

int(string_value, base = val)

Пример:

string_num = '100'
print("The data type of the input variable is:\n")
print(type(string_num))

print("Considering the input string number of base 8....")
result = int(string_num, base = 8)
print("The data type of the input value after conversion:\n")
print(type(result))
print("The converted variable from string(base 8) to int:\n")
print(result) 

print("Considering the input string number of base 16....")
result = int(string_num, base = 16)
print("The data type of the input value after conversion:\n")
print(type(result))
print("The converted variable from string(base 16) to int:\n")
print(result) 

В приведенном выше фрагменте кода мы преобразовали «100» в целочисленное значение с основанием 8 и основанием 16 соответственно.

Выход:

The data type of the input variable is:

<class 'str'>
Considering the input string number of base 8....
The data type of the input value after conversion:

<class 'int'>
The converted variable from string(base 8) to int:

64
Considering the input string number of base 16....
The data type of the input value after conversion:

<class 'int'>
The converted variable from string(base 16) to int:

256

Преобразование функционала из другой базы

Если строка, которую вы хотите преобразовать в число int, принадлежит другой базе чисел, отличной от базы 10, вы можете указать базу для преобразования.

Но помните, что выходное целое число всегда находится в базе 10. Еще одна вещь, которую вам нужно запомнить, – это то, что данная база должна находиться в диапазоне от 2 до 36. Смотрите следующий пример, чтобы понять преобразование строки в int с аргументом base.

num = '123'
# print the original string
print('The original string :', num)

# considering '123' be in base 10, convert it to base 10

print('Base 10 to base 10:', int(num))

# considering '123' be in base 8, convert it to base 10

print('Base 8 to base 10 :', int(num, base=8))

# considering '123' be in base 6, convert it to base 10

print('Base 6 to base 10 :', int(num, base=6))

Результатом следующего кода будет:

Неявные числовые преобразования

В следующей таблице приведены предопределенные неявные преобразования между встроенными числовыми типами:

Исходный тип Кому
sbyte , , , , , или
byte , , , , , , , , , или
short , , , или либо
ushort , , , , , или , или
int , , или ,
uint , , , или либо
long , или
ulong , или
float
nint , , или
nuint , , или

Примечание

Неявные преобразования из , , , , или в и из , , или в могут приводить к потере точности, но не к потере порядка величин. Другие неявные числовые преобразования никогда не теряют никаких сведений.

Также обратите внимание на следующее

  • Любой целочисленный тип неявно преобразуется в любой числовой тип с плавающей запятой.

  • Не поддерживается неявное преобразование в типы и . Не поддерживается неявное преобразование из типов и .

  • Не поддерживается неявное преобразование между типом и типами или .

  • Значение константного выражения типа (например, значение, представленное целочисленным литералом) может быть неявно преобразовано в , , , , , , или , если оно находится в диапазоне целевого типа:

    Как показано в предыдущем примере, если значение константы выходит за пределы диапазона целевого типа, возникает ошибка компилятора CS0031.

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: