Директива препроцессора для создания имен файлов - PullRequest
2 голосов
/ 01 сентября 2011

Мне нужно открывать файлы один за другим для чтения в C / C ++.Имена файлов: in0, in1, in2, in3 ..... Я пытался использовать директиву препроцессора для создания имен файлов.я хочу что-то вроде.

for(int i=0;i<n;i++)
{
    string inp_file="/path/"+"in"+APPEND(i);  //to generate /path/in1 etc
    open(inp_file);
}

, где APPEND - МАКРО.Поскольку

#define APP(i) i

может генерировать значение,

#define APP(i) #i

может преобразовывать токен в строку.
Я пытаюсь объединить их обоими способами, но не удалось.Как получить желаемый результат или вообще возможно получить такой результат с помощью макроса?

Ответы [ 5 ]

10 голосов
/ 01 сентября 2011

В вашем случае переменная i не является константой времени компиляции, и поэтому невозможно использовать препроцессор или специализацию шаблона, потому что значение просто не известно во время компиляции. Что вы можете сделать, это преобразовать целое число в строку - boost.lexical_cast - это одно из самых простых в использовании решений:

for (int i = 0; i < n; ++i) {
    // Generate /path/in1 etc
    std::string inp_file = "/path/in"+ boost::lexical_cast<std::string>(i);
    open(inp_file);
}

Если у вас есть компилятор с поддержкой C ++ 11, вы можете использовать std::to_string(). Например:

for (int i = 0; i < n; ++i) {
    // Generate /path/in1 etc
    std::string inp_file = "/path/in" + std::to_string(i);
    open(inp_file);
}

Надеюсь, это поможет. Удачи!

7 голосов
/ 01 сентября 2011

Приложение к ответу Влада - если по какой-то причине вы не можете / не хотите использовать Boost, вы можете выполнить то, что вы хотите, используя стандартный C ++ с классом stringstream:

#include <sstream>

void Foo() {
    for (int i = 0; i < n; ++i) {
        std::stringstream converter;
        converter << "/path/in" << i;
        open(converter.str());
    }
}
4 голосов
/ 01 сентября 2011

Если вы не используете повышение, попробуйте это:

namespace StringUtils
{
    // Converts any type which implements << to string (basic types are alright!)
    template<typename T>
    std::string StringUtils::toString(const T &t)
    {
       std::ostringstream oss;
       oss << t;
       return oss.str();
    }
}

Используйте это следующим образом:

for(int i=0;i<n;i++)
{
    string inp_file="/path/"+"in"+ StringUtils::toString(i);  //to generate /path/in1 etc
    open(inp_file);
}
1 голос
/ 01 сентября 2011

Решение C таково:

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

int main()
{
  int n =4;
  char nstr[12];
  sprintf(nstr, "%d", n);
  int nlen = strlen( nstr );


  const char *fd = "/path/in";
  char buff[ strlen(fd) + nlen + 1 ];

  sprintf( buff, "%s%d", fd, n );

  /* for testing */
  printf( "%s\n", buff );
}
1 голос
/ 01 сентября 2011

Просто дополнение к существующим ответам, и все это здорово, если вы используете более новый компилятор и стандартную библиотеку, c ++ 11 представляет std::to_string(). Таким образом, вы можете написать код так:

for(int i = 0; i < n; i++) {
    string inp_file = "/path/in"+ std::to_string(i);
    open(inp_file);
}
...