Разработчик
Проверенный
Участник
Пользователь
- Сообщения
- 207
- Реакции
- 420
- Помог
- 10 раз(а)
Введение в программирование на SourcePawn. Строки.
Строки - это массивы символов. Это означает, что помимо обращения к самой строке, Вы можете обращаться к определённым символам по индексу.
Концом строки считается всегда нулевой символ.
Т.е., функции SM и расширения всегда читают строку до нулевого байта (
0
или '\0'
).Размер строки указывается при её создании в квадратных скобках:
Код:
char szString[16] = "Hello, Dev-CS!";
Выделять буфер большого размера без причины считается всегда плохим тоном. Например, я сомневаюсь, что у кого-то IP-адрес игрока будет занимать 1024 байт.
Вообще, у SourcePawn есть константы размеров, которые удобно использовать.
PLATFORM_MAX_PATH
- применяется в буферах под путь файла. Константа равна 256.MAX_TARGET_LENGTH
- применяется в буферах для имени игрока. Равна 32 (с недавнего апдейта SM, из-за очередных "скрытых" фич CS:GO, это число подняли до 128).
MAX_TARGET_LENGTH
обычно ещё применяют для указания размера строки под IP-адрес или SteamID.Для получения размера "буфера" строки внутри функции, где эта строка была объявлена, применяется инструкция пре-процессора (компилятора)
sizeof()
. Вы могли видеть её вызовы в таких функциях, как Format()
, FormatEx()
, strcopy()
и так далее.
Код:
char szString[16];
FormatEx(szString, sizeof(szString), "Hello, Dev-CS!");
// Хочется показать, как работать с этой же инструкцией с двумерными массивами. Тут есть подводный камень.
// sizeof(szString[0]) выплюнет ошибку ещё на процессе компиляции.
// Правильнее записывать sizeof(szString[])
char szString[2][32];
FormatEx(szString[0], sizeof(szString[]), "My first SourcePawn code!");
FormatEx(szString[1], sizeof(szString[]), "Learning sizeof() features...");
strlen()
. Он возвращает кол-во уже записанных в строке байт.
Код:
char szString[16] = "Hello, Dev-CS!";
int iBufferLength = sizeof(szString); // 16
int iStringLength = strlen(szString); // 14
Очистка строк
Есть множество способов очистки строк:
strcopy(szString, sizeof(szString), "");
Format(szString, sizeof(szString), "");
szString = "";
szString[0] = '\0';
szString[0] = 0;
Как мы уже знаем, строка для функций SM заканчивается на нулевой байт. То есть, если мы присвоим первому символу значение нулевого байта, то для всех функций, строка будет пустой.
В двух верхних вариантах мы обращаемся к "сторонним" функциям, что занимает некоторое время.
Потому самыми оптимальными считаются два нижних варианта, т.к. выполнение кода за пределы виртуальной машины не выходит.
А что, если надо обрезать одну строку, и передать значения? Тогда мы можем воспользоваться "фичей" строк, когда строка заканчивается на нулевой байт. Банальный пример: есть строка, в которой перечисляются номера групп пользователя через запятую. Как мы можем вытянуть из неё эти номера и передать их сторонней функции?
Допустим, что максимальное кол-во групп - это 10. Тогда объявляем числовой массив размером 10, и просто итерируемся по строке:
C++:
// для примера: в szGroups хранится строка "2,5,10,99,22"
int[10] iGroupIds;
int iCurrentGroup, i;
while (i != -1) {
i = FindCharInString(szGroups, ',', true);
iGroupIds[iCurrentGroup++] = StringToInt(szGroups+1);
if (i != -1)
szGroups[i] = 0;
}
- Объявляется массив типа
int
с именемiGroupIds
и размером 10. - Объявляется две переменные с типом
int
и стандартным значением 0:iCurrentGroup
(для хранения индекса массива, в который будет записываться номер группы) иi
(для хранения позиции запятой после поиска) - Пока последняя найденная позиция запятой - не
-1
(что означает "такого символа нет"), производить снова и снова её поиск с конца, преобразовывать строку в число, и занулливать позицию запятой (если опять же, позиция запятой не-1
), чтобы функции больше не залезали туда.
Исходя из того факта, что строка всегда заканчивается на нулевой байт, можно так же проверять строку на пустоту:
Код:
if (szString[0] == 0) {
// строка пустая
}
Код:
if (szString[0] != 0) {
// строка не пуста
}
C++:
char szBuffer[64];
strcopy(szBuffer, sizeof(szBuffer), "Dev-CS.RU");
// неверно.
// мы получим строку вида: Hello, Hello, *мусор виртуальной машины*
FormatEx(szBuffer, sizeof(szBuffer), "Hello, %s!", szBuffer);
// верно.
// Hello, Dev-CS.RU!
Format(szBuffer, sizeof(szBuffer), "Hello, %s!", szBuffer);
Так же есть ещё функция VFormat(). Она по сути тоже делает форматирование строки, но применяется в других ситуациях. Мы обязательно её рассмотрим позднее.