我想从文件名抛出最后三个字符,并得到其余的?如何从文件名中删除扩展名?
我有这样的代码: “”
char* remove(char* mystr) {
char tmp[] = {0};
unsigned int x;
for (x = 0; x < (strlen(mystr) - 3); x++)
tmp[x] = mystr[x];
return tmp;
}
我想从文件名抛出最后三个字符,并得到其余的?如何从文件名中删除扩展名?
我有这样的代码: “”
char* remove(char* mystr) {
char tmp[] = {0};
unsigned int x;
for (x = 0; x < (strlen(mystr) - 3); x++)
tmp[x] = mystr[x];
return tmp;
}
尝试:
char *remove(char* mystr) {
char *retstr;
char *lastdot;
if (mystr == NULL)
return NULL;
if ((retstr = malloc (strlen (mystr) + 1)) == NULL)
return NULL;
strcpy (retstr, mystr);
lastdot = strrchr (retstr, '.');
if (lastdot != NULL)
*lastdot = '\0';
return retstr;
}
你必须自己释放返回的字符串。它只是在字符串中找到最后一个.
并用空终止符替换它。它将通过返回NULL来处理错误(传递NULL或耗尽内存)。
,不会的东西像/this.path/is_bad
工作,因为它会发现,在非文件部分的.
,但是你可以通过也做的/
一个strrchr
,或者其他路径分隔符为解决这个问题,并确保它的位置是NULL或位于.
之前。
一个更通用的解决这个问题可能是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// remove_ext: removes the "extension" from a file spec.
// mystr is the string to process.
// dot is the extension separator.
// sep 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 dot, char sep) {
char *retstr, *lastdot, *lastsep;
// 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);
lastdot = strrchr (retstr, dot);
lastsep = (sep == 0) ? NULL : strrchr (retstr, sep);
// If it has an extension separator.
if (lastdot != NULL) {
// and it's before the extenstion separator.
if (lastsep != NULL) {
if (lastsep < lastdot) {
// then remove it.
*lastdot = '\0';
}
} else {
// Has extension separator with no path separator.
*lastdot = '\0';
}
}
// 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;
}
并且这产生:
[hello]
[hello]
[hello]
[hello.txt]
[/no.dot/in_path]
[/has.dot/in]
[/no]
使用RINDEX定位字符。如果字符串是可写的,则可以用字符串终止符char('\ 0')替换它,然后就完成了。
char * rindex(const char * s,int c);
DESCRIPTION
The rindex() function locates the last character matching c (converted to a char) in the null-terminated string s.
我会尝试下面的算法:
last_dot = -1
for each char in str:
if char = '.':
last_dot = index(char)
if last_dot != -1:
str[last_dot] = '\0'
就用 “0” 代替点。如果你知道你的分机总是3个字符长,你可以这样做:
char file[] = "test.png"; file[strlen(file) - 4] = 0; puts(file);
这将输出“测试”。另外,你不应该返回一个指向局部变量的指针。编译器也会对此提出警告。
这应该做的工作:
char* remove(char* oldstr) {
int oldlen = 0;
while(oldstr[oldlen] != NULL){
++oldlen;
}
int newlen = oldlen - 1;
while(newlen > 0 && mystr[newlen] != '.'){
--newlen;
}
if (newlen == 0) {
newlen = oldlen;
}
char* newstr = new char[newlen];
for (int i = 0; i < newlen; ++i){
newstr[i] = oldstr[i];
}
return newstr;
}
如果你真的只是想删除最后三个字符,因为你不知何故知道你的文件名有一个扩展恰好有三个字符长(你想保持点):
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;
}
或者让呼叫者提供目标缓冲区(他们必须保证足够长):
char *remove_three(char *dst, const char *filename) {
size_t len = strlen(filename);
memcpy(dst, filename, len-3);
dst[len - 3] = 0;
return dst;
}
如果您想一般删除文件扩展名,这很难,并且通常应该使用您的平台提供的任何文件名处理例程(POSIX上的basename
,Windows上的_wsplitpath_s
),如果有任何机会处理路径不仅仅是文件名的最后部分:
/* 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;
}
试想想起来了,你可能想通过dst+1
,而不是dst
到strrchr,因为文件名以点开头,也许不应该被截断只是“ “。取决于它的用途。
+1 - 比我的回答好得多。 – 2010-04-29 11:46:31
要获得paxdiablo的第二更通用的解决方案,在C工作++编译器我改变了这一行:
if ((retstr = malloc (strlen (mystr) + 1)) == NULL)
到:
if ((retstr = static_cast<char*>(malloc (strlen (mystr) + 1))) == NULL)
希望这可以帮助别人。
获取位置并将其复制到新的char *位置。
i = 0;
n = 0;
while(argv[1][i] != '\0') { // 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);
这是更改扩展名的简单方法。
....
char outputname[255]
sscanf(inputname,"%[^.]",outputname); // foo.bar => foo
sprintf(outputname,"%s.txt",outputname) // foo.txt <= foo
....
对于以“..”开头并且可能是“。”开头的相对文件路径,这被打破了。 – bazz 2015-09-02 15:05:54
具有可配置的最小文件长度和可配置的最大扩展长度。返回扩展名更改为空字符的索引,如果未找到扩展名,则返回-1。
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] = '\0';
return i;
}
}
return -1;
}
我用这个代码:
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 = '\0';
}
它能够正确处理Windows路径约定(包括/
和\
可以路径分隔符)。
C++是否正常? – 2010-04-29 11:14:28
你知道“文件扩展名”和“文件名的最后三个字符”是**不是**是同一个东西吗?有些文件的扩展名多于或少于3个字符:'Foo.java','foo.c'就是很好的例子。有些甚至在扩展中有多个点:'foo.tar.gz'。还有一些人在扩展名之外有一个点:'foo.bar.txt'。简而言之:这是一项不平凡的任务。 – 2010-04-29 11:15:24
什么平台?在C中正确执行此操作并不重要,并且标准库中没有任何内容(因为文件名有点特定于平台)。例如,反斜杠是Windows中的路径分隔符,但不是* nix,所以对于'some \ path.to \ file',Windows上的“删除扩展名”的结果是'some \ path.to \ file'(因为没有扩展名),但是* nix是'some \ path'(因为扩展名是'to \ file')。 – 2010-04-29 11:16:39