2012-02-06 2 views
0

я должен написать функцию (C++), определение которых является:Как написать функцию, возвращающую const char *, которая является модифицированным аргументом const char *?

const char* getFileName(const char* name); 

сделать вещи Короче говоря, эта функция будет принимать имя, проверить некоторые условия и добавить к нему суффикса, что делает его правильное имя файла. Например:

имя = "" некий-файл, вернитесь = "hd.png-некий-файл"

const char* возвращаемый этой функцией будет немедленно передается в другую, которая принимает const char* в качестве аргумента

something->loadFile(getFileName("someFile")); 

у меня есть проблема, что когда я создаю в моей функции в const char* она будет иметь ограниченную область действия функции она была создана в. с другой стороны, я не могу изменить код loadFile, потому что это сторонняя библиотека, которую я использую.

Я могу написать обертку вокруг loadFile, чтобы удалить const char*, который я создал, но я не хотел бы этого делать, поскольку это упражнение по переносу, и это сломало бы некоторые шаблоны, которые я создал, чтобы сделать это проще.

Есть ли способ написать эту функцию, как я описал?

Благодаря

EDIT: небольшого объяснения:

getFileName функции Я пытаюсь написать, что я могу изменить тип возвращаемого, но он должен соответствовать в качестве параметра loadFile функции. Моя основная проблема заключается в том, что const char*, возвращенный getFileName, либо потерян, потому что это вне области видимости, либо я должен удалить его явно, что нарушает мой шаблон переноса. Я хотел бы сгенерировать имя файла в одном вызове функции и ничего не делать об этом [другими словами, в исходном коде у меня есть loadFile("something.png"), и я хочу изменить его на loadFile(getFileName("something")) без добавления каких-либо новых строк.

+1

Имеет ли 'getFileName()' потокобезопасность/реентерабельность? Если это не так, вы можете вернуть указатель на «статический» буфер, локальный для этой функции. –

+0

Да, я работаю с pthreads и предпочел бы иметь потокобезопасность, просто чтобы быть уверенным. – Krystian

+0

Можете ли вы изменить возвращаемый тип 'getFileName()'? – hmjd

ответ

5

Если вы можете изменить тип возвращаемого getFileName() быть std::string вы можете сделать следующее:

std::string getFileName(const char* a_name) 
{ 
    std::string result(a_name); 
    result += ".png"; 

    return result; 
} 

// No memory management req'd 
something->loadFile(getFileName("someFile").c_str()); 
+0

Damn :) Я думал об использовании строки, но я вернул result.c_str() вместо того, чтобы просто возвращать строку и делать .c_str() после этого! Большое спасибо! Это решает, не нарушая мой шаблон! – Krystian

+0

Насколько я знаю, использование '.c_str()' для этой цели считается плохой практикой, поскольку вы не можете полагаться на существование копии 'std :: string result'. – LihO

+0

@ Liho, спасибо, но я _think_ вы можете, поскольку временный объект будет жить до конца выражения. – hmjd

2

Основная логика использования аргументов const заключается в том, что это означает, что вы не собираетесь изменять этот аргумент в теле функции, которая его принимает.

Если вы хотите изменить его, не используйте const.

И не волнуйтесь о литье char* в const char*. Для этого существует неявное преобразование.

Вы действительно не должны изменять этот аргумент const char*. Вы можете использовать его для построения объекта std::string и избежать возможной утечки памяти - проверьте ответ на hmjd.

+1

Это утечка памяти, хотя ... а также немного неэффективная, так как 'strcat' будет пересчитывать длину первого string, в то время как 'strcpy' уже (хотя это ошибка API C, а не ваша). –

+0

Ну, это зависит от того, как он планирует его использовать. Если он будет называть 'something-> loadFile (getFileName (" someFile ")), то он не будет течь или будет? И для эффективности я думаю, что он все же быстрее, чем накладные расходы, связанные со строительством 'std :: string' и копированием в решении hjmd. – LihO

+0

@LihO: Это зависит от того, что делает loadFile. Поскольку loadFile является членом «чего-то», но getFileName нет, возможно, странно предположить, что loadFile очистит память, которая не принадлежит к ее собственному классу. Я согласен с Matthieu, это приведет к утечке памяти и, следовательно, к плохой практике. Кроме того, на самом деле нет смысла возвращать указатели, подобные этому в C++. – Lundin

1

Повторные указатели из функций, как правило, не имеют смысла в C (и даже меньше, так и в C++). Поскольку вы отметили это как C, так и C++, это C-ответ.

Обычный способ сделать это было бы что-то вроде:

void getFileName (const char* name, 
        char*  complete_name, 
        size_t  complete_name_n) 
{ 
    ... // create a new file name in a temp buffer 

    if(the new file name has a strlen() < complete_name_n) 
    { 
    strcpy(complete_name, the new file name); 
    } 
} 

// caller: 
char name_buf [N]; 

getFileName(name, name_buf, N); 
something->LoadFile(name_buf); 

Например, весь Windows API вызовы функций именно таким образом, в результате чего распределение параметров абонента, позволяя самой функции озабоченность только с его задачей (а не с распределением памяти и т. д.).

Хотя, конечно, это означает, что вызывающий должен ввести несколько строк вместо одного. На этом этапе вы должны спросить себя, что самое главное:

  • писать чистые функции интерфейсы без непонятных возвращает указатель, ни странным, ненужным, утечка динамического распределения, или
  • набрать как можно меньше кода, как это возможно в вызывающий, чтобы уменьшить износ клавиатуры и программного обеспечения.
Смежные вопросы