2015-02-10 3 views
4

Я относительно новичок в C++. Я написал функцию WriteToFile, которая записывает в текстовый файл (путь задается строкой a) 2D массива (хранится в 0-строки основного порядка, х строк, у колонок):Функция с общими входными параметрами

void WriteToFile(std::string a, const float *img, const int x, const int y) { 
    FILE *pFile; 
    const char * c = a.c_str(); 
    pFile = fopen(c, "w"); 
    for (int i = 0; i < x; i++){ 
     for (int j = 0; j < y; j++) 
      fprintf(pFile, "%5.5f\t", img[i*y + j]); 
     fprintf(pFile, "\n"); 
    } 
    fclose(pFile); 
} 

Теперь я хочу эту функцию, чтобы иметь дело также с int и double массивами. Для int он просто напечатает номера, как есть, и для двойного %5.10lf должен использоваться в fprintf. Я знаю, что это абсолютно возможно. Я нашел пару похожих вещей, но не понял, как справляться с входными аргументами. Конечно, я могу написать 3 разные функции, но я хочу узнать, как написать общую функцию.

Благодаря

+0

Спецификатор формата зависит от типа массива, поэтому, вероятно, вам понадобится три разных вызова/логики, чтобы фигурировать в какой-то момент этого кода, или могут быть аргументами сложения для добавления типа – P0W

+0

. Вы можете использовать класс 'fstream' и либо добавьте перегруженный 'operator <<' в ваш матричный класс, либо используйте свободную стоячую функцию для записи 2d-массива в 'fstream'. 'Fstream' уже настроен для обработки других типов объектов, таких как' double'. –

+0

Возможный дубликат [возможно ли сделать функцию, которая будет принимать несколько типов данных для данного аргумента?] (Http: // stackoverflow.com/questions/8627625/is-it-possible-to-make-function-that-will-accept-multiple-data-types-for-given-a) –

ответ

3

Вы можете использовать шаблон функции и некоторые вспомогательные функции, чтобы получить строку формата.

Вот рабочая программа.

#include <cstdio> 
#include <string> 

template <typename T> char const* getFormatString(); 

template <> char const* getFormatString<int>() 
{ 
    return "%d\t"; 
} 

template <> char const* getFormatString<float>() 
{ 
    return "%5.5f\t"; 
} 

template <> char const* getFormatString<double>() 
{ 
    return "%15.10lf\t"; 
} 

template <typename T> 
void WriteToFile(std::string a, const T *img, const int x, const int y) { 
    FILE *pFile; 
    const char * c = a.c_str(); 
    pFile = fopen(c, "w"); 
    for (int i = 0; i < x; i++){ 
     for (int j = 0; j < y; j++) 
      fprintf(pFile, getFormatString<T>(), img[i*y + j]); 
     fprintf(pFile, "\n"); 
    } 
    fclose(pFile); 
} 

int main() 
{ 
    int img1[] = {1, 1, 1, 1}; 
    float img2[] = {1, 1, 1, 1}; 
    double img3[] = {1, 1, 1, 1}; 
    WriteToFile("int.img", img1, 2, 2); 
    WriteToFile("float.img", img2, 2, 2); 
    WriteToFile("double.img", img3, 2, 2); 
} 
+0

Я думал что-то вроде этого! – P0W

+0

Спасибо, это то, что я хотел –

-2

Идея была бы

template <typename T> 
void WriteToFile(std::string a, const T *img, const int x, const int y) { 
} 

, а затем

inline 
void write(FILE *file, double) { //write double } 

inline 
void write(FILE *file, int) { // write } 
+2

OP хочет избежать отдельных вызовов – P0W

0

Если вам нужно использовать другой формат строку для каждого типа, вы можете использовать шаблонную функцию и в строке формата в качестве параметра:

template<typename T> void WriteToFile(std::string a, const T *img, 
         const int x, const int y, std::string formatStr) { 
... 
     fprintf(pFile, formatStr.c_str(), img[i*y + j]); 
... 
} 
2

«Теперь я хочу, чтобы эта функция имела дело с int и double массивами. "

Вы можете использовать шаблонные функции для обработки различных типов массивов, а также использовать стандартную библиотеку C++ I/O

template <typename T> 
void WriteToFile(std::string a, const T *img, const int x, const int y) { 
    std::ofstream file(a); 

    for (int i = 0; i < x; i++){ 
     for (int j = 0; j < y; j++) 
      file << std::fixed << std::setw(5) << std::setprecision(5) 
       << img[i*y + j] << "\t" << std::endl; 
    } 
    file.close(); 
} 

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

+0

Если специализация входит в картину, то это не то, что ОП спросил – P0W

+1

@ P0W 'std :: fixed' и' std :: setprecision' никак не повлияет на вывод 'int'. –

+0

Согласовано, но что, если десятичная точность отличается для 'float' и' double', вам придется специализироваться – P0W

0

У вас есть такие опции, как перегрузка и функции шаблона. Я просто хочу ввести способность, которая поставляется с C++ 11. Использование std::is_same.

У этого есть свои плюсы и минусы. Например, предположим, что тип входа ограничен int и float:

#include <type_traits> 

template <typename T> 
void WriteToFile(std::string a, const T *img, const int x, const int y) 
{ 
    const char *format = std::is_same<T, int>::value? "%i\t" : "%5.5f\t"; 

    ... 

     fprintf(pFile, format, img[i*y + j]); 

    ... 
} 

Обратите внимание, что этот подход к обобщению и ваш код не является максимально стандартизован.

Смежные вопросы