Другой возможный способ:
var _timer;
clearTimeout(_timer);
_timer = setTimeout(function() {
// Your code
}, 1000); // Delay for 1 s.
Может быть, я просто старый и сварливый, но другие ответы, которые я видел, похоже, полностью упускают суть.
C не выполняет присваивания массивов, точка. Вы не можете назначить один массив другому массиву простым присваиванием, в отличие от некоторых других языков (например, PL / 1; Pascal и многие его потомки - Ada, Modula, Oberon и т. Д.). В C нет строкового типа. В нем есть только массивы символов, и вы можете ' • копировать массивы символов (точно так же, как вы можете копировать массивы любого другого типа) без использования цикла или вызова функции. [Строковые литералы на самом деле не считаются строковыми типами.]
Единственный раз, когда массивы копируются, это когда массив встроен в структуру, и вы выполняете присваивание структуры.
В моей копии K&R 2nd Edition, в упражнении 1-19 запрашивается функция реверс (ы)
; в моем экземпляре K&R 1st Edition это было упражнение 1-17 вместо 1-19, но был задан тот же вопрос.
Поскольку указатели не были рассмотрены на этом этапе, решение должно использовать индексы вместо указателей. Я считаю, что это приводит к:
#include <string.h>
void reverse(char s[])
{
int i = 0;
int j = strlen(s) - 1;
while (i < j)
{
char c = s[i];
s[i++] = s[j];
s[j--] = c;
}
}
#ifdef TEST
#include <stdio.h>
int main(void)
{
char buffer[256];
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
int len = strlen(buffer);
if (len == 0)
break;
buffer[len-1] = '\0'; /* Zap newline */
printf("In: <<%s>>\n", buffer);
reverse(buffer);
printf("Out: <<%s>>\n", buffer);
}
return(0);
}
#endif /* TEST */
Скомпилируйте это с помощью -DTEST, чтобы включить тестовую программу и без определения только функции reverse ()
.
С сигнатурой функции, указанной в вопросе, вы избегаете вызова strlen ()
дважды для каждой строки ввода. Обратите внимание на использование fgets ()
- даже в тестовых программах использовать gets ()
- плохая идея. Обратной стороной fgets ()
по сравнению с gets ()
является то, что fgets ()
не удаляет завершающую новую строку, где gets ()
делает. Положительные стороны fgets ()
заключаются в том, что вы не получаете переполнения массива и можете определить, нашла ли программа перевод строки или не хватило места (или данных) до появления новой строки.
fgets ()
по сравнению с gets ()
является то, что fgets ()
не удаляет завершающую новую строку, где gets ()
делает. Положительные стороны fgets ()
заключаются в том, что вы не получаете переполнения массива и можете определить, нашла ли программа перевод строки или не хватило места (или данных) до появления новой строки. Обратной стороной fgets ()
по сравнению с gets ()
является то, что fgets ()
не удаляет завершающую новую строку, где gets ()
делает. Положительные стороны fgets ()
заключаются в том, что вы не получаете переполнения массива и можете определить, нашла ли программа перевод строки или не хватило места (или данных) до появления новой строки. Ваш массив tmp
был объявлен в стеке , поэтому, когда ваш метод завершится, память, используемая для хранения значений, будет освобождена из-за scoping .
s = tmp
означает, что s
должен указывать на то же место в памяти, что и tmp
. Это означает, что когда tmp
освобождается, s
по-прежнему будут указывать на теперь возможную недопустимую освобожденную ячейку памяти.
Этот тип ошибки называется висячий указатель .
Изменить: Это не висячий модификатор, как указано в комментариях к этому ответу. Проблема в том, что выражение s = tmp
изменяет только то, на что указывает параметр, а не то, какой фактический массив был передан.
Кроме того, вы можете выполнить обратное действие за один проход и без выделения всего массива в памяти, просто поменяв местами значения по одному:
void reverse(char s[], int slen) {
int i = 0; // First char
int j = slen - 2; // Last char minus \n\0
char tmp = 0; // Temp for the value being swapped
// Iterate over the array from the start until the two indexes collide.
while(i < j) {
tmp = s[i]; // Save the eariler char
s[i] = s[j]; // Replace it with the later char
s[j] = tmp; // Place the earlier char in the later char's spot
i++; // Move forwards with the early char
j--; // Move backwards with the later char
}
}
To round out the discussion here are two other possible ways to reverse as string:
void reverse(char string1[], char string2[])
{
int i = 0, len = 0;
while(string2[len] != '\0') // get the length of the string
len++;
while(len > 0)
{
string1[i] = string2[len-1]; // copy the elements in reverse
i++;
len--;
}
string1[i] = '\0'; // terminate the copied string
}
Or recursively:
void reverse (const char *const sPtr)
{
//if end of string
if (sPtr[0] == '\0')
{
return;
}
else //not end of the string...
{
reverse(&sPtr[1]); //recursive step
putchar(sPtr[0]); //display character
}
}
because tmp is a pointer, and you need to get a copy, not a "link".
В случае s = tmp значение of tmp, который также является начальным адресом массива, будет скопирован в s.
Таким образом, и s, и tmp будут указывать на один и тот же адрес в памяти, что, я думаю, не является целью.
Ура
Попробуйте поэкспериментировать и посмотрите, что происходит, когда вы делаете что-то вроде этого:
void modifyArrayValues(char x[], int len)
{
for (int i = 0; i < len; ++i)
x[i] = i;
}
void attemptModifyArray(char x[], int len)
{
char y[10];
for (int i = 0; i < len; ++i)
y[i] = i;
x = y;
}
int main()
{
int i = 0;
char x[10];
for (i = 0; i < 10; ++i)
x[i] = 0;
attemptModifyArray(x, 10);
for (i=0; i < 10; ++i)
printf("%d\n", x[i]); // x is still all 0's
modifyArrayValues(x, 10);
for (i=0; i < 10; ++i)
printf("%d\n", x[i]); // now x has 0-9 in it
}
Что происходит, когда вы изменяете массив непосредственно в tryModifyArray
, вы просто перезаписываете локальную копию адреса массива x
. Когда вы вернетесь, исходный адрес все еще будет находиться в копии x main
.
Когда вы изменяете значения в массиве в modifyArrayValues
, вы изменяете сам фактический массив, адрес которого хранится в modifyArrayValues
локальной копии x
. Когда вы вернетесь, x
по-прежнему удерживает тот же массив, но вы изменили значения в этом массиве.
В этом потоке есть интересный подпоток о массивах и указателях. Я нашел эту ссылку в Википедии со своеобразным фрагментом кода, показывающим, насколько «пластилиновым» может быть Си!
/* x designates an array */
x[i] = 1;
*(x + i) = 1;
*(i + x) = 1;
i[x] = 1; /* strange, but correct: i[x] is equivalent to *(i + x) */
Конечно, еще больше сбивает с толку в C то, что я могу делать это:
unsigned int someval = 0xDEADD00D;
char *p = (char *)&someval;
p[2] = (char)0xF0;
Таким образом, взаимозаменяемость указателей и массивов кажется настолько глубоко укоренившейся в языке C, что почти преднамеренной.
Что думают все остальные?
--- Исходное сообщение ---
s и tmp являются указателями, поэтому выполнение s = tmp просто заставит s указывать на адрес, по которому tmp находится в памяти.
Другая проблема с тем, что вы обрисовали в общих чертах, заключается в том, что tmp является локальной переменной, поэтому она станет неопределенной, когда она выйдет за пределы области видимости, т.е. когда функция вернется.
Убедитесь, что вы полностью усвоили эти три концепции, и вы не ошибетесь
Надеюсь, это поможет, и продолжайте!
Очень простой ответ был бы - и s, и tmp являются указателями на ячейку памяти, а не сами массивы. Другими словами, s и tmp - это адреса памяти, где хранятся значения массива, но не сами значения. И один из распространенных способов доступа к этим значениям массива - использование индексов типа s [0] или tmp [0].
Теперь, если вы попытаетесь просто скопировать, s = tmp, адрес памяти массива tmp будет скопировать в s. Это означает, что исходный массив s будет утерян, и даже указатель памяти s теперь будет указывать на массив tmp.
Вы хорошо поймете эти концепции со временем, так что продолжайте читать книгу. Надеюсь, это простое объяснение поможет.
Because both s and tmp are memory addressees. If you s = tmp, both pointers would point to the same array.
Suppose that we have
char s[] ="ab";
/*
* Only for explanatory purposes.
*
*/
void foo(char s[]){
char tmp [] = "cd";
s= tmp;
}
foo(s);
after s= tmp you would have
s[0] : 'c'
s[1] : 'd'
s[2] : '\0'
Even though both arrays have the same data, a change in tmp, will affect both of them, because both arrays are actually the same. They both contain data that´s in the same memory address. So by changing any position of the tmp array, or destroying the tmp array, s would be affected in the same way.
By looping over the array, what you are doing is moving a piece of data from one memory address to another.
In my copy of K & R, pointers are explained in chapter 4. A quick glance through the first pages may be of help.