Код для изменения расширения файла (для просмотра)
Я использую следующий кусок кода C, чтобы изменить расширение файла.
{
#define EVAL_MAX_LEN (300)
int nLen;
char szOut [EVAL_MAX_LEN] = {0};
char szPath [EVAL_MAX_LEN] = "/db/file/face.bmp";
// Get string length !!!
nLen = strlen (szPath);
if ((nLen > 0) && (nLen < EVAL_MAX_LEN)) {
while (nLen) {
// Check for extension character !!!
if (szPath [nLen] == '.') {
szPath [nLen] = '\0';
break;
}
nLen --;
}//while (nLen ...
// Create output file name and with new extension
sprintf (szOut, "%s.txt", szPath);
}// if ((nLen > 0) && (nLen < EVAL_MAX_LEN ...
}
Любое предложение для лучшего и более элегантного кода приветствуется. Я также знаю, что в Windows мы можем использовать _splitpath, чтобы сделать это элегантно. Но сейчас я использую этот код в Linux.
6 ответов
Как насчет написания тестовых случаев? Если вышеупомянутое является подпрограммой с именем change_ext_to_txt(char* szPath)
, вы хотите проверить:
change_ext_to_txt("/foo/bar.baz");
change_ext_to_txt("/foo/bar");
change_ext_to_txt("/foo/bar.baz/bal.bat");
change_ext_to_txt("/foo/bar.baz/bal");
и удостоверьтесь, что правильная вещь выходит из всех них. Подсказка: все решения, представленные до сих пор (включая ваше!), Терпят неудачу по крайней мере на одном из вышеперечисленных.
// find file name
char *pFile = strrchr(szPath, '/');
pFile = pFile == NULL ? szPath : pFile+1;
// change extension
char *pExt = strrchr(pFile, '.');
if (pExt != NULL)
strcpy(pExt, ".txt");
else
strcat(pFile, ".txt");
Вы должны использовать snprintf()
вместо sprintf()
чтобы избежать потенциального переполнения буфера. Вы также можете использовать strrchr(3)
чтобы найти последний период, вместо того, чтобы кодировать свой собственный цикл. Тем не менее, две вещи, которые следует соблюдать осторожность:
- Что если входной файл не имеет расширения, т.е. в имени пути нет точки?
- Что если входной файл не имеет расширения, но в одной из папок в имени пути есть точка? Например:
"/home/joeuser/dotted.folder/thefile"
Убедитесь, что вы правильно обрабатываете оба этих случая.
Вам нужно использовать dirname и basename, чтобы разделить каталог и имя файла, а затем разделить имя файла, чтобы получить последнее "." а затем объедините dirname и '/' и basename, чтобы получить переименованное расширение.
Pseduodcode где результат - это результат
char *dirc, *basec, *bname, *dname,*result;
char *path = "/etc/passwd";
char *extn = NULL;
dirc = strdup(path);
basec = strdup(path);
dname = dirname(dirc);
bname = basename(basec);
extn = strrchr( bname, '.' );
if(extn != NULL) *extn = '\0';
sprintf(result, "%s/%s.txt"", dname, bname);
free(dirc);
free(basec);
Как насчет этого?
#define EVAL_MAX_LEN (300)
int nLen;
char szOut [EVAL_MAX_LEN] = {0};
char szPath [EVAL_MAX_LEN] = "/db/file/face.bmp";
char *res = NULL;
// Get string length !!!
nLen = sizeof (szPath);
memset(szOut,0,sizeof(szOut));
if ((nLen > 0) && (nLen <= EVAL_MAX_LEN)) {
res = strrchr( szPath, '.' );
if(res != NULL)
*res = '\0';
}
// Create output file name and with new extension
sprintf (szOut, "%s.txt", szPath);
// if ((nLen
Я хотел бы рассмотреть возможность использования strnlen () и base EVAL_MAX_LEN из системного предела PATH_MAX (или любого другого, что применимо) (проверьте его возвращаемое значение, прежде чем продолжить).
Это позволит избежать даже попыток записи сомнительного содержимого в szOut или необходимости проверять количество символов, не напечатанных в szOut, если строка слишком велика (хотя я все же рекомендую использовать snprintf () над sprintf()).