Я следовал ниже шагов для закрытия filezilla.
В терминале, введите ниже для списка всех рабочих процессов.
ps -A
Это даст Вам список выполнения процессов. Найдите идентификатор процесса, который имеет имя "filezilla", и уничтожьте процесс. В моей системе идентификатор процесса является 1759.
kill 1759
Filezilla закроется немедленно. Спасибо.
Строка 2 проверяет, является ли текущий символ нулевым ограничителем строки - поскольку строки C заканчиваются нулем, и нулевой символ считается ложным значением, он начнет разворачивать рекурсию, когда достигнет конца строки (вместо попытки вызвать StrReverse4 для символа после нулевого терминатора, который будет за пределами допустимых данных).
Также обратите внимание, что указатель указывает на char
, таким образом, приращение указателя увеличивается только на 1 байт (поскольку char
является однобайтовым типом).
Пример:
0 1 2 3
+--+--+--+--+
|f |o |o |\0|
+--+--+--+--+
str
= 0
, тогда * str
равно 'f'
, поэтому рекурсивный вызов выполняется для str + 1 = 1. str
= 1
, тогда * str
равно 'o'
, поэтому рекурсивный вызов выполняется для str + 1 = 2. str
= 2
, тогда * str
равно 'o'
, поэтому рекурсивный вызов выполняется для str + 1 = 3. str
= 3
, тогда * str
равно '\ 0'
и \ 0
является ложным значением, поэтому if (* str)
оценивается как false, поэтому рекурсивный вызов не выполняется, таким образом, возвращаясь к рекурсии, которую мы получаем ... Тип строки C - не что иное, как указатель на char. По соглашению указатель указывает на массив символов, оканчивающийся нулевым байтом .
* str
, таким образом, является первым символом строки, на которую указывает ] str
.
Использование * str
в условном выражении оценивается как false
, если str
указывает на завершающий нулевой байт в (пустой) строке .
Строка 2 проверяет, является ли текущий символ нулевым ограничителем строки - поскольку строки C являются нулевыми. завершен, а нулевой символ считается ложным значением, он начнет развертывание рекурсии, когда достигнет конца строки (вместо попытки вызвать StrReverse4 для символа после нулевого терминатора,
В конце строки стоит 0
- значит, у вас есть "test" => [0] 't' [1] 'e' [2] 's' [3] 't' [4] 0
и if (0) -> false
, таким образом это будет работать.
В строке 3 указатель всегда будет увеличиваться до следующего блока (4 байта, так как это целое число) ...
Это неверно, это char *, это будет только увеличивается на 1. Поскольку длина char составляет всего 1 байт.
Но как это использовать в качестве аргумента условного оператора (который должен исключать логическое право?)?
Вы можете использовать любое значение в if ($$) в $$, и он будет только проверять, отличен ли он от нуля, в основном bool также реализован как простые 1 = true и 0 = false.
В другой строго типизированный язык более высокого уровня, в if вы не можете использовать такие вещи, но в C все сводится к числам. И вы можете использовать что угодно.
if(1) // evaluates to true
if("string") // evaluates to true
if(0) // evaulates to false
Вы можете передать что угодно в if, а условия в C.
условные операторы ( if
, для
, while
и т. Д.) Ожидают логического выражения. Если вы указываете целочисленное значение, оценка сводится к 0 == false
или не-0 == true
. Как уже упоминалось, завершающий символ c-строки - это нулевой байт (целочисленное значение 0). Таким образом, if
завершится ошибкой в конце строки (или первом нулевом байте в строке).
В стороне, если вы сделаете * str
для NULL-указателя, вы вызывают неопределенное поведение; вы всегда должны проверять действительность указателя перед разыменованием.
C не имеет концепции логических значений: в C каждый скалярный тип (то есть арифметические типы и типы указателей) можно использовать в логических контекстах, где 0
означает ложь
и ненулевое значение истина
.
Поскольку строки заканчиваются нулем, терминатор будет интерпретироваться как ложь
, тогда как все остальные символы (с ненулевым значением!) будет истинным
. Это означает, что существует простой способ перебора символов строки:
for(;*str; ++str) { /* so something with *str */ }
StrReverse4 ()
делает то же самое, но путем рекурсии вместо итерации.
1.
str
- указатель на char. Увеличение str
заставит указатель указывать на второй символ строки (так как это массив символов).
ПРИМЕЧАНИЕ: Увеличивающие указатели будут увеличиваться в зависимости от типа данных, на который указывает указатель.
Например:
int *p_int;
p_int++; /* Increments by 4 */
double *p_dbl;
p_dbl++; /* Increments by 8 */
2.
if(expression)
{
statements;
}
Выражение вычисляется, и если результирующее значение равно нулю ( NULL
, \ 0
, 0
), операторы не выполняются. Поскольку каждая строка заканчивается на \ 0
, рекурсия должна закончиться через некоторое время.
Попробуйте этот код, такой же простой, как тот, который вы используете:
int rev(int lower,int upper,char*string)
{
if(lower>upper)
return 0;
else
return rev(lower-1,upper-1,string);
}
Это вроде как не по теме, но когда я увидел вопрос, я сразу подумал, действительно ли это быстрее, чем просто выполнение strlen и итерации сзади.
Итак, я сделал небольшой тест.
#include <string.h>
void reverse1(const char* str)
{
int total = 0;
if (*str) {
reverse1(str+1);
total += *str;
}
}
void reverse2(const char* str)
{
int total = 0;
size_t t = strlen(str);
while (t > 0) {
total += str[--t];
}
}
int main()
{
const char* str = "here I put a very long string ...";
int i=99999;
while (--i > 0) reverseX(str);
}
Сначала я скомпилировал его с X = 1 (используя функцию reverse1), а затем с X = 2. Оба раза с -O0.
Он последовательно возвращал примерно 6 секунд для рекурсивной версии и 1,8 секунды для версии strlen.
Я думаю, это потому, что strlen реализован на ассемблере, а рекурсия добавляет довольно накладные расходы.
Я совершенно уверен, что тест репрезентативен, если я ошибаюсь, поправьте меня.
В любом случае, я подумал, что должен поделиться этим с вами.