Обычно вы не должны делать это с std::copy_n
, что предполагает, что предоставленный итератор при увеличении n раз остается в силе:
Копирует точно
count
значения от диапазона, начинающегося вfirst
до диапазона, начинающегося вresult
. Формально для каждого неотрицательного целого числаi < n
выполняется*(result + i) = *(first + i)
.( статья на cppreference.com на
blockquote>std::copy_n
) sup>Если вы можете это гарантировать, тогда хорошо, но обычно с
std::cin
] это невозможно. Вы можете довольно просто разыменовать недопустимый итератор:Построенный по умолчанию
std::istream_iterator
известен как итератор конца потока. Когда действительныйstd::istream_iterator
достигает конца основного потока, он становится равным итератору конца потока. Разыменование или инкремент в дальнейшем вызывает неопределенное поведение.( статья на cppreference.com на
blockquote>std::istream_iterator
) sup>Вы в значительной степени там со своим циклом, хотя я бы вероятно, используйте более сильное условие завершения, чтобы избежать избыточного чтения из «мертвого» потока:
vector
v(n); for(vector ::size_type i = 0; i < n; i++) if (!cin >> v[i]) break; Я бы соблазнился на самом деле обернуть это во что-то вроде
std::copy_n
, но принимает полный «диапазон», чей границы могут быть проверены в дополнение к подсчету от 0 до N .Реализация может выглядеть следующим образом:
template
OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result) { for (Size i = 0; i < count && first != last; ++i) *result++ = *first++; return result; } Вы бы использовали это так:
copy_atmost_n( std::istream_iterator
(std::cin), std::istream_iterator (), N, std::back_inserter(v) ); Теперь вы получаете M элементов, где [1122 ] M - это либо количество предоставленных входов, либо N , в зависимости от того, что меньше.
( живое демо )
Один возможный путь состоял бы в том, чтобы вычислить подпись MD5 файла (или идентификатор файла в базе данных) и затем создать/найти путь на основе этого.
Например, скажите, что мы получаем подпись MD5 как "1ff8a7b5dc7a7d1f0ed65aaa29c04b1e"
Путь мог бы быть похожим на "/1f/f" или "/1f/ff/8a"
Причина состоит в том, что Вы не хотите иметь все файлы в 1 папке, и Вы хотите иметь способность "разделить" их через различные серверы или SAN или безотносительно equally-spread-out способом.
Подпись MD5 является строкой 16 "шестнадцатеричных" символов. Таким образом, наш пример "/1f/ff/8a" дает нам 256*256*256 папок, чтобы хранить файлы в. Это должно быть достаточно для кого-либо :)
Обновление, из-за популярного спроса:
ОТМЕТЬТЕ - я просто понял, что мы говорим конкретно о том, как MediaWiki делает это. Это не теперь MediaWiki, делает это, но иначе в котором это, возможно, было сделано.
"Подписью MD5" я означаю делать что-то вроде этого (примеры кода в Perl):
use Digest::MD5 'md5_hex';
my $sig = md5_hex( $file->id );
$sig является теперь 32 алфавитно-цифровыми символами долго: "1ff8a7b5dc7a7d1f0ed65aaa29c04b1e"
Затем создайте структуру папок как это:
my $path = '/usr/local/media';
map { mkdir($path, 0666); $path .= "/$_" } $sig =~ m/^(..)(..)(..)/;
open my $ofh, '>', "$path/$sig"
or die "Cannot open '$path/$sig' for writing: $!";
print $ofh "File contents";
close($ofh);
Структура папок похожа
/
usr/
local/
media/
1f/
f8/
a7/
1ff8a7b5dc7a7d1f0ed65aaa29c04b1e
Принятый ответ является неправильным:
Сумма MD5 'Herbs.jpg' является fceaa5e7250d5036ad8cede5ce7d32d6. Первыми 2 символами является 'ФК', давая путь к файлу f/fc/, который является тем, что дано в примере.
В PHP можно вызвать следующую функцию для получения URL. Можно хотеть посмотреть на код php, чтобы выяснить, как они вычисляют путь.
$url = wfFindFile(Title::makeTitle(NS_IMAGE, $fileName))->getURL();