2014-12-16 2 views
1

Я пытаюсь открыть файл, имя которого состоит из постоянных и переменных частей.C++ ifstream с переменной filename

Мой фактический код

char filename[100]; 
char extension1[] = ".pdb"; 
vector<string> id; 

//code to find the ids(it works) 

sprintf(filename, "/home/giovanni/Scrivania/enzimi/ligan/%s", id[1].c_str()); 
sprintf(filename, "%s%s", filename,extension1); 

Проблема заключается в том, что имена файлов становится

.pdbe/Джиованни/Scrivania/enzimi/ligan/102M

вместо

/home/giovan п/Scrivania/enzimi/ligan/102M.pdb

Tnx заранее

+5

Вы не можете использовать одну и ту же строку как в качестве адресата, так и аргумент в 'sprintf', то есть [* undefined behavior *] (http://en.wikipedia.org/wiki/Undefined_behavior). В вашем случае вы можете вместо этого «strcat». –

+0

Хотя я тоже верю, не могли бы вы дать более подробное объяснение? Документация на http://www.cplusplus.com/reference/cstdio/sprintf/ не упоминает об этом. – Codor

+0

Лучшим решением было бы использовать ['std :: istringstream'] (http://en.cppreference.com/w/cpp/io/basic_istringstream). –

ответ

3

Просто используйте зЬй :: строка:

string filename = "/home/giovanni/Scrivania/enzimi/ligan/" + id[1] + ".pdb"; 

... 

std::ifstream file(filename.c_str()); 
+0

Я тоже пробовал это, но это дает мне ту же проблему :( – abbax

+1

Does 'id [1]' возможно содержать в конце новую строку, пробелы или нулевые символы? – Wintermute

+0

Выполняет ли оператор +() правильную вещь, если у нас есть оператор + (char *, std :: string)? –

0
  1. Watch Out For Переполнение буфера!

  2. Вам необходимо добавить существующую строку; Вы должны знать количество символов в нем, то смещение указателя вы передаете в ко второму вызову Sprintf:

int len = sprintf(filename, "/home/giovanni/Scrivania/enzimi/ligan/%s", id[1].c_str()); sprintf(filename + len, "%s", extension1);

(Sprintf возвращает количество символов, записанных в буфер, но не включает терминатор NUL.)

Обратите внимание, что второй вызов sprintf имеет только один «% s».

1

Просто с помощью этого кода будет делать (sprintf принимает переменное число аргументов):

sprintf(filename,"/home/giovanni/Scrivania/enzimi/ligan/%s%s", id[1].c_str(), extension1); 

Но, как вы используете C++, делая это в стиле C не является предпочтительным. sprintf() может cuase переполнение буфера, и вы можете безопаснее версия snprintf(). Лучшим вариантом было бы использовать std::string

1

C99 и POSIX.1-2001 указывают, что результаты не определены, если вызов sprintf()/snprintf приведет к копированию между перекрываемыми объектами (например, если целевая строка массив и один из входящих аргументов ввода относятся к одному и тому же буфере). Итак, строка sprintf (имя файла, «% s% s», имя_файла, расширение1) является незаконным. Вы можете попробовать другие параметры, такие как std :: string.