Строки @Mendelt Siebenga
являются ключевыми объектами на языках программирования. Различные языки реализуют строки по-другому. Реализация join()
сильно зависит от конкретной реализации строк. Псевдокод не отражает конкретную реализацию.
Рассматривают join()
в Python. Это может легко использоваться:
print ", ".join(["Alpha", "Beta", "Gamma"])
# Alpha, Beta, Gamma
Это могло быть легко реализовано следующим образом:
def join(seq, sep=" "):
if not seq: return ""
elif len(seq) == 1: return seq[0]
return reduce(lambda x, y: x + sep + y, seq)
print join(["Alpha", "Beta", "Gamma"], ", ")
# Alpha, Beta, Gamma
И здесь как join()
метод реализован в C (взятый от соединительная линия ):
PyDoc_STRVAR(join__doc__,
"S.join(sequence) -> string\n\
\n\
Return a string which is the concatenation of the strings in the\n\
sequence. The separator between elements is S.");
static PyObject *
string_join(PyStringObject *self, PyObject *orig)
{
char *sep = PyString_AS_STRING(self);
const Py_ssize_t seplen = PyString_GET_SIZE(self);
PyObject *res = NULL;
char *p;
Py_ssize_t seqlen = 0;
size_t sz = 0;
Py_ssize_t i;
PyObject *seq, *item;
seq = PySequence_Fast(orig, "");
if (seq == NULL) {
return NULL;
}
seqlen = PySequence_Size(seq);
if (seqlen == 0) {
Py_DECREF(seq);
return PyString_FromString("");
}
if (seqlen == 1) {
item = PySequence_Fast_GET_ITEM(seq, 0);
if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) {
Py_INCREF(item);
Py_DECREF(seq);
return item;
}
}
/* There are at least two things to join, or else we have a subclass
* of the builtin types in the sequence.
* Do a pre-pass to figure out the total amount of space we'll
* need (sz), see whether any argument is absurd, and defer to
* the Unicode join if appropriate.
*/
for (i = 0; i < seqlen; i++) {
const size_t old_sz = sz;
item = PySequence_Fast_GET_ITEM(seq, i);
if (!PyString_Check(item)){
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(item)) {
/* Defer to Unicode join.
* CAUTION: There's no gurantee that the
* original sequence can be iterated over
* again, so we must pass seq here.
*/
PyObject *result;
result = PyUnicode_Join((PyObject *)self, seq);
Py_DECREF(seq);
return result;
}
#endif
PyErr_Format(PyExc_TypeError,
"sequence item %zd: expected string,"
" %.80s found",
i, Py_TYPE(item)->tp_name);
Py_DECREF(seq);
return NULL;
}
sz += PyString_GET_SIZE(item);
if (i != 0)
sz += seplen;
if (sz < old_sz || sz > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"join() result is too long for a Python string");
Py_DECREF(seq);
return NULL;
}
}
/* Allocate result space. */
res = PyString_FromStringAndSize((char*)NULL, sz);
if (res == NULL) {
Py_DECREF(seq);
return NULL;
}
/* Catenate everything. */
p = PyString_AS_STRING(res);
for (i = 0; i < seqlen; ++i) {
size_t n;
item = PySequence_Fast_GET_ITEM(seq, i);
n = PyString_GET_SIZE(item);
Py_MEMCPY(p, PyString_AS_STRING(item), n);
p += n;
if (i < seqlen - 1) {
Py_MEMCPY(p, sep, seplen);
p += seplen;
}
}
Py_DECREF(seq);
return res;
}
Примечание, что вышеупомянутой Catenate everything.
код является небольшая часть целой функции.
В псевдокоде:
/* Catenate everything. */
for each item in sequence
copy-assign item
if not last item
copy-assign separator
ulong mixed = (ulong)high << 32 | low;
Актерский состав очень важен. Если вы опустите приведение, учитывая тот факт, что high
имеет тип uint
(то есть 32 бита), вы сместите 32-битное значение на 32 бита влево. Операторы сдвига для 32-битных переменных будут использовать сдвиг по правой стороне
по модулю 32. Фактически, сдвиг uint
32 бита влево не является -op . Преобразование в ulong
предотвращает это.
Проверить этот факт легко:
uint test = 1u;
Console.WriteLine(test << 32); // prints 1
Console.WriteLine((ulong)test << 32); // prints (ulong)uint.MaxValue + 1
Вы должны преобразовать highInt в ulong, прежде чем выполнять битовый сдвиг:
ulong output = highInt;
output = output << 32;
output += lowInt;
ulong output = (ulong)highUInt << 32 + lowUInt
Операторы <<
и >>
сдвигают бит влево (вверх) и вправо (вниз) соответственно. highUInt << 32
функционально совпадает с highUInt * Math.Pow (2, 32)
, но может быть быстрее и имеет (IMO) более простой синтаксис.
Кодировка:
ulong mixed = (ulong)hi << 32 | lo;
Декодирование:
uint lo = (uint)(mixed & uint.MaxValue);
uint hi = (uint)(mixed >> 32);