данные не рассчитаны правильно [дубликат]

Для меня WriteXLS предоставляет функциональность, которую вы ищете. Поскольку вы не указали, какие ошибки он возвращает, я покажу вам пример:

Пример

library(WriteXLS)
x <- list(sheet_a = data.frame(a=letters), sheet_b = data.frame(b = LETTERS))
WriteXLS(x, "test.xlsx", names(x))

Объяснение

Если x:

  • список кадров данных, каждый из которых записывается на один лист
  • символьный вектор (из объектов R), каждый объект записывается на один лист
  • что-то еще, а затем посмотрите, что говорит помощь:

Подробнее об использовании

?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 после завершения цикла.

Информация сессии

  • R 3.2.4
  • WriteXLS 4.0.0
23
задан Mr.C64 11 March 2014 в 18:32
поделиться

10 ответов

Поскольку этот вопрос отмечен 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() вернуть функцию, если она больше не используется.

5
ответ дан alk 4 September 2018 в 07:25
поделиться

Решение, которое не было вызвано в других ответах.

Если ваш метод является членом класса, например:

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 класса ). Механизмы могут быть сделаны для удаления данных через некоторое время, чтобы не сохранять их навсегда.

1
ответ дан coyotte508 4 September 2018 в 07:25
поделиться

Хорошо, ПОЛНОСТЬЮ верна. Причина, по которой ваш текущий подход не срабатывает, заключается в том, что экземпляр 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!.
}
3
ответ дан jmac 4 September 2018 в 07:25
поделиться

Что происходит в этом коде:

const char * returnCharPtr()
{
    std::string someString("something");
    return someString.c_str();
}
  1. экземпляр std::string создан - это объект с автоматическим временем хранения
  2. указатель на внутренний память этой строки возвращается
  3. объект someString разрушен и внутренняя память очищена
  4. вызывающая сторона этой функции получает оборванный указатель (недействительный указатель), который дает неопределенное поведение

Лучшее решение: возвращает объект :

std::string returnString()
{
    std::string someString("something");
    return someString;
}
18
ответ дан LihO 4 September 2018 в 07:25
поделиться

Проблема заключается в том, что 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());
1
ответ дан milleniumbug 4 September 2018 в 07:25
поделиться

В 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());
}
10
ответ дан Mr.C64 4 September 2018 в 07:25
поделиться

Вы можете передать указатель на свою строку и напрямую обработать метод (т. е. вообще избегать возвратов)

void returnCharPtr(char* someString)
{    
    // some processing!
    if(someString[0] == 'A')
       someString++;
}
1
ответ дан MrDuk 4 September 2018 в 07:25
поделиться

Если у вас есть свобода изменить возвращаемое значение 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;
}
1
ответ дан R Sahu 4 September 2018 в 07:25
поделиться

Лучшим способом было бы вернуть std::string, который автоматически управляет памятью. Если, с другой стороны, вы действительно возвращали const char*, который указывает на некоторую память, выделенную вами из returnCharPtr, тогда она должна быть явно освобождена кем-то другим.

Оставайтесь с std::string.

1
ответ дан user 4 September 2018 в 07:25
поделиться

Ваши параметры:

Return std::string

Передайте буфер в returnCharPtr(), который будет содержать новый буфер символов. Для этого нужно проверить, что предоставленный буфер достаточно велик для хранения строки.

Создайте новый char массив внутри returnCharPtr(), скопируйте буфер в новый и верните указатель на него. Это требует, чтобы вызывающий ящик явно вызывал delete [] на то, что они явно не создавали с помощью new, или сразу же помещал его в класс интеллектуального указателя. Это решение было бы улучшено, если бы вы вернули умный указатель, но на самом деле имеет смысл возвращать std::string напрямую.

Выберите первый; return std::string. Это, безусловно, упрощенный и безопасный вариант.

1
ответ дан xen-0 4 September 2018 в 07:25
поделиться
Другие вопросы по тегам:

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