Привязка к строке

Вы можете передать somevar по значению (не по ссылке) с помощью функции javascript, известной как clos :

var someVar='origin';
func = function(v){
    console.log(v);
}
document.addEventListener('click',function(someVar){
   return function(){func(someVar)}
}(someVar));
someVar='changed'

Или вы могли бы написать общую функцию обертки, такую ​​как wrapEventCallback:

function wrapEventCallback(callback){
    var args = Array.prototype.slice.call(arguments, 1);
    return function(e){
        callback.apply(this, args)
    }
}
var someVar='origin';
func = function(v){
    console.log(v);
}
document.addEventListener('click',wrapEventCallback(func,someVar))
someVar='changed'

Здесь wrapEventCallback(func,var1,var2) выглядит следующим образом:

func.bind(null, var1,var2)

30
задан Dave Jarvis 24 February 2010 в 18:50
поделиться

7 ответов

Вряд ли можно избежать копирования, если вы хотите, чтобы оно выполнялось в том же фрагменте памяти. Если выделенный фрагмент достаточно велик, вы можете использовать memmove , чтобы сдвинуть исходную строку на длину того, что вы хотите добавить, а затем скопировать эту строку в начало, но я сомневаюсь в этом менее «неуклюжий». Однако это сэкономит вам дополнительную память (опять же, при условии, что в исходном фрагменте достаточно свободного места для них обоих).

Примерно так:

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>


/* Prepends t into s. Assumes s has enough space allocated
** for the combined string.
*/
void prepend(char* s, const char* t)
{
    size_t len = strlen(t);
    size_t i;

    memmove(s + len, s, strlen(s) + 1);

    for (i = 0; i < len; ++i)
    {
        s[i] = t[i];
    }
}


int main()
{
    char* s = malloc(100);
    strcpy(s, "file");
    prepend(s, "dir/");

    printf("%s\n", s);
    return 0;
}
14
ответ дан 28 November 2019 в 00:23
поделиться

sprintf () обычно не "быстрый". Поскольку вы знаете, что предварительное ожидание memmove () дважды, вероятно, было бы предпочтительнее для скорости.

Если вы изначально выделяете строки с помощью malloc (), вы можете подумать об использовании realloc () для изменения размеров символьных массивов, чтобы они могли содержать новую строку.

   char* p = malloc( size_of_first_string );
   ...
   p = realloc( p, size_of_first_string + size_of_prepended_string + 1 );
   memmove( p + size_of_prepended_string, p, size_of_first_string );
   memmove( p, prepended_string, size_of_prepended_string );
3
ответ дан 28 November 2019 в 00:23
поделиться

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

int i = 0;
int j;

char temp*[MAX_DIR_DEPTH], file[LENGTH];

while (some_condition) {
    temp[i++] = some_calculation_that_yields_name_of_parent_dir;        
}

char *pCurrent = file;    
for( j = i-1; j > 0; j-- )
{
    strcpy(pCurrent, temp[j]);
    pCurrent += strlen(temp[j]);
    *pCurrent++ = '\';
}
strcpy(pCurrent, filename);
*pCurrent = 0;
1
ответ дан 28 November 2019 в 00:23
поделиться

Возможно, я запутался, но я считаю, что добавление - это то же самое, что добавление с переставленными строками. Таким образом, вместо добавления «Hello» к «World», строка «World» может быть добавлена ​​ к «Hello»:

const char world[] = "World";
const char hello[] = "Hello";

// Prepend hello to world:
const unsigned int RESULT_SIZE = sizeof(world) + sizeof(hello) + 2 * sizeof('\0');
char * result = malloc(RESULT_SIZE);
if (result)
{
  strcpy(result, hello);
  strcat(result, world);
  puts("Result of prepending hello to world: ");
  puts(result);
  puts("\n");
}

Кроме того, основная трата времени выполнения - поиск конец строки. Если бы строки были сохранены с длиной, конец можно было бы вычислить быстрее.

1
ответ дан 28 November 2019 в 00:23
поделиться

Это решение не требует копирования больше, чем необходимо. Для этого требуется один strlen, поэтому, если извлечение имени каталога может вернуть количество скопированных байтов или если вы можете предварительно рассчитать длину строки родительского каталога, вы можете оптимизировать это.

void GetFilename(char *pFile)
{
    strcpy(pFile, "someFile");
}

void GetParentDir(char *pDir)
{
    strcpy(pDir, "/parentdir");
}

int _tmain(int argc, _TCHAR* argv[])
{

    char path[1024];
    GetParentDir(path);
    int dirSize = strlen(path);
    path[dirSize] = '/';
    GetFilename(path + dirSize + 1);
    printf(path);
    return 0;
}
0
ответ дан 28 November 2019 в 00:23
поделиться

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

Я полагаю, что это, по сути, вектор (в терминах языка C, массив) из struct { char *begin; char *end };

В C++ он реализует все функции std::string. В C вам придется написать (или получить библиотеку) функции-заменители для всех функций strxxx().

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

Веревка очень хороша для больших строк. Но все, что меньше 8 КБ, быстрее обрабатывается с помощью memmove и memcpy.

7
ответ дан 28 November 2019 в 00:23
поделиться

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

Итак, если файл изначально был (foo.txt)

[] [] [] [] [] [f] [o] [o] [.] [t] [x] [t] [\0]
             ^
             |
          lastEmpty           

Теперь, если вы добавите родительский dir a/, он будет выглядеть как

[] [] [] [a] [/] [f] [o] [o] [.] [t] [x] [t] [\0]
       ^      
       |      
    lastEmpty           

Таким образом, код будет выглядеть примерно так (могут быть ошибки, но вы поняли идею).

char temp[LENGTH], file[LENGTH]; 
int lastEmpty = put_at_end(some_file_name, file);  
// lastEmpty points to right most empty slot

while (some_condition) { 
    parent_dir = some_calculation_that_yields_name_of_parent_dir; 

    int len = strlen(parent_dir);
    char *tmp = parent_dir + len -1;

    while (lastEmpty > 0) {
        file[lastEmpty] = *tmp;
        lastEmpty --;
        tmp--;
    }
} 

Поскольку я полагаю, что мы можем ожидать, что parent_dir будет небольшим, то дважды пройтись по нему не составит труда. Если вы хотите передать строку файла, вы можете просто использовать file+lastEmpty+1.

1
ответ дан 28 November 2019 в 00:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: