Для меня WriteXLS
предоставляет функциональность, которую вы ищете. Поскольку вы не указали, какие ошибки он возвращает, я покажу вам пример:
Пример
library(WriteXLS)
x <- list(sheet_a = data.frame(a=letters), sheet_b = data.frame(b = LETTERS))
WriteXLS(x, "test.xlsx", names(x))
Объяснение
Если x
:
Подробнее об использовании
?WriteXLS
показано:
`x`: A character vector or factor containing the names of one or
more R data frames; A character vector or factor containing
the name of a single list which contains one or more R data
frames; a single list object of one or more data frames; a
single data frame object.
Решение
Для вашего примера вам нужно будет собрать все data.frames в списке во время цикла и использовать WriteXLS
после завершения цикла.
Информация сессии
Поскольку этот вопрос отмечен C, сделайте следующее:
#define _POSIX_C_SOURCE 200809L
#include <string.h>
const char * returnCharPtr()
{
std::string someString;
// some processing!.
return strdup(someString.c_str()); /* Dynamically create a copy on the heap. */
}
Не забудьте free()
вернуть функцию, если она больше не используется.
Решение, которое не было вызвано в других ответах.
Если ваш метод является членом класса, например:
class A {
public:
const char *method();
};
И если экземпляр класса будет жить за пределами полезности указателя, вы можете сделать:
class A {
public:
const char *method() {
string ret = "abc";
cache.push_back(std::move(ret));
return cache.last().c_str();
}
private:
vector<string> cache; //std::deque would be more appropriate but is less known
}
Таким образом, указатели будут действительны до разрушения A
.
Если функция не является частью класса, она все еще может использовать класс для хранения данных (например, переменную static
для функции или экземпляр внешнего класса, на который можно ссылаться по всему миру, или даже член класса static
класса ). Механизмы могут быть сделаны для удаления данных через некоторое время, чтобы не сохранять их навсегда.
Хорошо, ПОЛНОСТЬЮ верна. Причина, по которой ваш текущий подход не срабатывает, заключается в том, что экземпляр std::string
, созданный внутри функции, будет действителен только до тех пор, пока эта функция будет работать. Когда ваша программа покинет область действия, будет вызван деструктор std :: string, и это будет конец вашей строки.
Но если вы хотите, это C-строка, как насчет ...
const char * returnCharPtr()
{
std::string someString;
// some processing!.
char * new_string = new char[someString.length() + 1];
std::strcpy(new:string, someString.c_str());
return new_string;
}
Но подождите ... это почти так же, как и возвращение std::string
, не так ли?
std::string returnCharPtr()
{
std::string someString;
// some processing!.
return new_string;
}
Это скопирует вашу строку в новую за пределами область действия. Он работает, но создает новую копию строки.
Благодаря оптимизации возвращаемого значения это не создаст копию (спасибо за все исправления!).
So , другой вариант - передать параметр в качестве аргумента, поэтому вы обрабатываете строку в функции, но не создаете новую копию. :
void returnCharPtr(std::string & someString)
{
// some processing!.
}
Или, опять же, если вы хотите C-Strings, вам нужно следить за длиной вашей строки:
void returnCharPtr(char*& someString, int n) // a reference to pointer, params by ref
{
// some processing!.
}
Что происходит в этом коде:
const char * returnCharPtr()
{
std::string someString("something");
return someString.c_str();
}
std::string
создан - это объект с автоматическим временем хранения someString
разрушен и внутренняя память очищена Лучшее решение: возвращает объект :
std::string returnString()
{
std::string someString("something");
return someString;
}
Проблема заключается в том, что someString
уничтожается в конце функции, а функция возвращает указатель на несуществующие данные.
Не возвращайте .c_str()
строки, которая может быть уничтожена, прежде чем использовать возвращаемый указатель char.
Вместо ...
const char* function()
{
std::string someString;
// some processing!
return someString.c_str();
}
//...
useCharPtr(function());
использовать
std::string function()
{
std::string someString;
// some processing!
return someString;
}
//...
useCharPtr(function().c_str());
В C ++ проще всего просто вернуть return std::string
(что также эффективно благодаря оптимизации, такой как семантика перемещения RVO и C ++ 11):
std::string returnSomeString()
{
std::string someString;
// some processing...
return someString;
}
Если вы действительно нужен исходный указатель C char*
, вы всегда можете вызвать .c_str()
в возвращаемом значении, например
// void SomeLegacyFunction(const char * psz)
// .c_str() called on the returned string, to get the 'const char*'
SomeLegacyFunction( returnSomeString().c_str() );
Если вы действительно хотите вернуть указатель char*
из функции, вы можете динамически выделяет строчную память в куче (например, используя new[]
) и возвращает указатель на это:
// NOTE: The caller owns the returned pointer,
// and must free the string using delete[] !!!
const char* returnSomeString()
{
std::string someString;
// some processing...
// Dynamically allocate memory for the returned string
char* ptr = new char[someString.c_str() + 1]; // +1 for terminating NUL
// Copy source string in dynamically allocated string buffer
strcpy(ptr, someString.c_str());
// Return the pointer to the dynamically allocated buffer
return ptr;
}
Альтернативой является указание указателя буфера назначения и размер буфера (чтобы избежать переполнения буфера!) в качестве функциональных параметров:
void returnSomeString(char* destination, size_t destinationSize)
{
std::string someString;
// some processing...
// Copy string to destination buffer.
// Use some safe string copy function to avoid buffer overruns.
strcpy_s(destination, destinationSize, someString.c_str());
}
Вы можете передать указатель на свою строку и напрямую обработать метод (т. е. вообще избегать возвратов)
void returnCharPtr(char* someString)
{
// some processing!
if(someString[0] == 'A')
someString++;
}
Если у вас есть свобода изменить возвращаемое значение returnCharPtr
, измените его на std::string
. Это будет самый чистый метод для возврата строки. Если вы не можете, вам нужно выделить память для возвращаемой строки, скопировать ее с std::string
и вернуть указатель на выделенную память. Вы также должны убедиться, что вы удаляете память в вызывающей функции. Поскольку вызывающий абонент будет отвечать за освобождение памяти, я бы изменил возвращаемое значение на char*
.
char* returnCharPtr()
{
std::string someString;
// some processing!.
char* cp = new char[someString.length()+1];
strcpy(cp, someString.c_str());
return cp;
}
Лучшим способом было бы вернуть std::string
, который автоматически управляет памятью. Если, с другой стороны, вы действительно возвращали const char*
, который указывает на некоторую память, выделенную вами из returnCharPtr
, тогда она должна быть явно освобождена кем-то другим.
Оставайтесь с std::string
.
Ваши параметры:
Return std::string
Передайте буфер в returnCharPtr()
, который будет содержать новый буфер символов. Для этого нужно проверить, что предоставленный буфер достаточно велик для хранения строки.
Создайте новый char
массив внутри returnCharPtr()
, скопируйте буфер в новый и верните указатель на него. Это требует, чтобы вызывающий ящик явно вызывал delete []
на то, что они явно не создавали с помощью new
, или сразу же помещал его в класс интеллектуального указателя. Это решение было бы улучшено, если бы вы вернули умный указатель, но на самом деле имеет смысл возвращать std::string
напрямую.
Выберите первый; return std::string
. Это, безусловно, упрощенный и безопасный вариант.