C语言 如何从文件名中删除扩展名?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2736753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to remove extension from file name?
提问by alaamh
I want to throw the last three character from file name and get the rest?
我想从文件名中抛出最后三个字符并获得其余的字符?
I have this code:
我有这个代码:
char* remove(char* mystr) {
char tmp[] = {0};
unsigned int x;
for (x = 0; x < (strlen(mystr) - 3); x++)
tmp[x] = mystr[x];
return tmp;
}
回答by paxdiablo
Try:
尝试:
char *remove(char* myStr) {
char *retStr;
char *lastExt;
if (mystr == NULL) return NULL;
if ((retStr = malloc (strlen (myStr) + 1)) == NULL) return NULL;
strcpy (retStr, myStr);
lastExt = strrchr (retStr, '.');
if (lastExt != NULL)
*lastExt = '#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// remove_ext: removes the "extension" from a file spec.
// myStr is the string to process.
// extSep is the extension separator.
// pathSep is the path separator (0 means to ignore).
// Returns an allocated string identical to the original but
// with the extension removed. It must be freed when you're
// finished with it.
// If you pass in NULL or the new string can't be allocated,
// it returns NULL.
char *remove_ext (char* myStr, char extSep, char pathSep) {
char *retStr, *lastExt, *lastPath;
// Error checks and allocate string.
if (myStr == NULL) return NULL;
if ((retStr = malloc (strlen (myStr) + 1)) == NULL) return NULL;
// Make a copy and find the relevant characters.
strcpy (retStr, myStr);
lastExt = strrchr (retStr, extSep);
lastPath = (pathSep == 0) ? NULL : strrchr (retStr, pathSep);
// If it has an extension separator.
if (lastExt != NULL) {
// and it's to the right of the path separator.
if (lastPath != NULL) {
if (lastPath < lastExt) {
// then remove it.
*lastExt = '[hello]
[hello]
[hello]
[hello.txt]
[/no.dot/in_path]
[/has.dot/in]
[/no]
';
}
} else {
// Has extension separator with no path separator.
*lastExt = ' DESCRIPTION
The rindex() function locates the last character matching c (converted to a char) in the null-terminated string s.
';
}
}
// Return the modified string.
return retStr;
}
int main (int c, char *v[]) {
char *s;
printf ("[%s]\n", (s = remove_ext ("hello", '.', '/'))); free (s);
printf ("[%s]\n", (s = remove_ext ("hello.", '.', '/'))); free (s);
printf ("[%s]\n", (s = remove_ext ("hello.txt", '.', '/'))); free (s);
printf ("[%s]\n", (s = remove_ext ("hello.txt.txt", '.', '/'))); free (s);
printf ("[%s]\n", (s = remove_ext ("/no.dot/in_path", '.', '/'))); free (s);
printf ("[%s]\n", (s = remove_ext ("/has.dot/in.path", '.', '/'))); free (s);
printf ("[%s]\n", (s = remove_ext ("/no.dot/in_path", '.', 0))); free (s);
return 0;
}
';
return retDtr;
}
You'll have to free the returned string yourself. It simply finds the last .in the string and replaces it with a null terminator character. It will handle errors (passing NULL or running out of memory) by returning NULL.
您必须自己释放返回的字符串。它只是找到.字符串中的最后一个并将其替换为空终止符。它将通过返回 NULL 来处理错误(传递 NULL 或内存不足)。
It won't work with things like /this.path/is_badsince it will find the .in the non-file portion but you could handle this by also doing a strrchrof /, or whatever your path separator is, and ensuring it's position is NULL or before the .position.
它不适用于类似的事情,/this.path/is_bad因为它会.在非文件部分找到 ,但您也可以通过执行 a strrchrof/或任何您的路径分隔符来处理此问题,并确保它的位置为 NULL 或.位置之前。
A more general purpose solution to this problem could be:
这个问题的一个更通用的解决方案可能是:
char *remove_three(const char *filename) {
size_t len = strlen(filename);
char *newfilename = malloc(len-2);
if (!newfilename) /* handle error */;
memcpy(newfilename, filename, len-3);
newfilename[len - 3] = 0;
return newfilename;
}
and this produces:
这会产生:
char *remove_three(char *dst, const char *filename) {
size_t len = strlen(filename);
memcpy(dst, filename, len-3);
dst[len - 3] = 0;
return dst;
}
回答by diciu
Use rindexto locate the "." character. If the string is writable, you can replace it with the string terminator char ('\0') and you're done.
使用rindex来定位“.” 特点。如果字符串是可写的,您可以将其替换为字符串终止符字符 ('\0') 就完成了。
char * rindex(const char *s, int c);
char * rindex(const char *s, int c);
/* warning: may modify filename. To avoid this, take a copy first
dst may need to be longer than filename, for example currently
"file.txt" -> "./file.txt". For this reason it would be safer to
pass in a length with dst, and/or allow dst to be NULL in which
case return the length required */
void remove_extn(char *dst, char *filename) {
strcpy(dst, dirname(filename));
size_t len = strlen(dst);
dst[len] = '/';
dst += len+1;
strcpy(dst, basename(filename));
char *dot = strrchr(dst, '.');
/* retain the '.' To remove it do dot[0] = 0 */
if (dot) dot[1] = 0;
}
回答by Steve Jessop
If you literally just want to remove the last three characters, because you somehow know that your filename has an extension exactly three chars long (and you want to keep the dot):
如果您实际上只想删除最后三个字符,因为您以某种方式知道您的文件名的扩展名正好是三个字符(并且您想保留点):
last_dot = -1
for each char in str:
if char = '.':
last_dot = index(char)
if last_dot != -1:
str[last_dot] = 'if ((retstr = malloc (strlen (mystr) + 1)) == NULL)
'
Or let the caller provide the destination buffer (which they must ensure is long enough):
或者让调用者提供目标缓冲区(他们必须确保足够长):
if ((retstr = static_cast<char*>(malloc (strlen (mystr) + 1))) == NULL)
If you want to generically remove a file extension, that's harder, and should normally use whatever filename-handling routines your platform provides (basenameon POSIX, _wsplitpath_son Windows) if there's any chance that you're dealing with a path rather than just the final part of the filename:
如果您想一般地删除文件扩展名,那就更难了,并且如果您有可能处理路径而不仅仅是最后一部分,通常应该使用您的平台提供的任何文件名处理例程(basename在 POSIX 上,_wsplitpath_s在 Windows 上)文件名:
i = 0;
n = 0;
while(argv[1][i] != '....
char outputname[255]
sscanf(inputname,"%[^.]",outputname); // foo.bar => foo
sprintf(outputname,"%s.txt",outputname) // foo.txt <= foo
....
') { // get length of filename
i++; }
for(ii = 0; i > -1; i--) { // look for extension working backwards
if(argv[1][i] == '.') {
n = i; // char # of exension
break; } }
memcpy(new_filename, argv[1], n);
Come to think of it, you might want to pass dst+1rather than dstto strrchr, since a filename starting with a dot maybe shouldn't be truncated to just ".". Depends what it's for.
想想看,您可能想要传递dst+1而不是dststrrchr,因为以点开头的文件名可能不应该被截断为“.”。取决于它是干什么用的。
回答by Bastien Léonard
I would try the following algorithm:
我会尝试以下算法:
int32_t strip_extension(char *in_str)
{
static const uint8_t name_min_len = 1;
static const uint8_t max_ext_len = 4;
/* Check chars starting at end of string to find last '.' */
for (ssize_t i = sizeof(in_str); i > (name_min_len + max_ext_len); i--)
{
if (in_str[i] == '.')
{
in_str[i] = 'void remove_extension(char* s) {
char* dot = 0;
while (*s) {
if (*s == '.') dot = s; // last dot
else if (*s == '/' || *s == '\') dot = 0; // ignore dots before path separators
s++;
}
if (dot) *dot = 'char file[] = "test.png";
file[strlen(file) - 4] = 0;
puts(file);
';
}
';
return i;
}
}
return -1;
}
回答by Rory Milne
To get paxdiablo's second more general purpose solution to work in a C++ compiler I changed this line:
为了让 paxdiablo 的第二个更通用的解决方案在 C++ 编译器中工作,我更改了这一行:
##代码##to:
到:
##代码##Hope this helps someone.
希望这可以帮助某人。
回答by Rory Milne
Get location and just copy up to that location into a new char *.
获取位置并将该位置复制到新的字符 * 中。
##代码##回答by Yi Feng Xie
This is simple way to change extension name.
这是更改扩展名的简单方法。
##代码##回答by cs01
With configurable minimum file length and configurable maximum extension length. Returns index where extension was changed to null character, or -1 if no extension was found.
具有可配置的最小文件长度和可配置的最大扩展长度。返回扩展名更改为空字符的索引,如果未找到扩展名,则返回 -1。
##代码##回答by ?r?ola
I use this code:
我使用这个代码:
##代码##It handles the Windows path convention correctly (both /and \can be path separators).
它正确处理Windows路径约定(包括/与\可路径分隔符)。
回答by jhenninger
Just replace the dot with "0". If you know that your extension is always 3 characters long you can just do:
只需将点替换为“0”。如果您知道您的扩展名总是 3 个字符长,您可以这样做:
##代码##This will output "test". Also, you shouldn't return a pointer to a local variable. The compiler will also warn you about this.
这将输出“测试”。此外,您不应返回指向局部变量的指针。编译器也会警告你这一点。

