有类似的问题,但我的问题更具体一些。当我使用 RLE 算法进行编码时,我有一个 C 代码,它接受 file.txt 并返回 file.txt.rle 。我以同样的方式对其进行解码,并希望从 file.txt.rle 写入并返回 file.txt。以下代码是我从 file.txt 转到 file.txt.rle 时使用的代码:
char name[NAME_SIZE];
if(sprintf(name, "%s.rle", argv[1]) >= sizeof(name)){
fprintf(stderr, "Destination file name is too long\n");
}
while((o_fp = fopen(name, "wb")) == NULL){
fprintf(stderr, "Can't create the file to be written\n");
exit(1);
}
如何在解码时将扩展名从 file.txt.rle 更改为 file.txt?完整的代码没有帮助,因为我将在解码编码文件的代码中使用它。
注意:给定的文件始终为 .txt.rle 格式,返回的文件应始终将其转换为 .txt。
您可以简单地执行此操作:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* this function will create a new name, replacing the existing extension
by the given one.
returned value should be `free()` after usage
/!\ warning:
* validity of parameters is not tested
* return of strdup and malloc are not tested.
*/
char *replace_ext(const char *org, const char *new_ext)
{
char *ext;
/* copy the original file */
char *tmp = strdup(org);
/* find last period in name */
ext = strrchr(tmp , '.');
/* if found, replace period with '\0', thus, we have a shorter string */
if (ext) { *ext = '\0'; }
/* compute the new name size: size of name w/o ext + size of ext + 1
for the final '\0' */
size_t new_size = strlen(tmp) + strlen(new_ext) + 1;
/* allocate memory for new name*/
char *new_name = malloc(new_size);
/* concatenate the two string */
sprintf(new_name, "%s%s", tmp, new_ext);
/* free tmp memory */
free(tmp);
/* return the new name */
return new_name;
}
int main(void)
{
int i;
char *tests[] = { "test.ext", "test.two.ext", "test_no_ext", NULL};
for (i = 0; tests[i]; ++i)
{
char *new_name = replace_ext(tests[i], ".foo");
printf("%s --> %s\n", tests[i], new_name);
free(new_name);
}
return 0;
}
这是一个实现。 这里的魔法是由
change_file_name(org, dest, size, ext)
执行的,它检查名称 org 是否以 ext 结尾,在这种情况下,将名称复制到该点。
希望这有帮助。
/* Changes the name of the sys input file. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool change_file_name(const char * org, char * dest, size_t max_length, const char * file_ext)
{
bool toret = false;
const size_t name_length = strlen( org );
const size_t ext_length = strlen( file_ext );
const size_t new_name_size = name_length - ext_length;
if ( name_length > ext_length
&& name_length < max_length
&& strcmp( org + new_name_size, file_ext ) == 0 )
{
strncpy( dest, org, name_length - ext_length );
*( dest + new_name_size ) = 0;
toret = true;
}
return toret;
}
void convert_file(const char * org, const char * dest)
{
printf( "Processing file '%s' into '%s'\n", org, dest );
}
int main(int argc, char *argv[])
{
const int NAME_SIZE = 1024;
const char * rle_ext = ".rle";
char new_name[NAME_SIZE];
int toret = EXIT_SUCCESS;
if ( argc == 2 ) {
if ( change_file_name( argv[ 1 ], new_name, NAME_SIZE, rle_ext ) ) {
printf( "The new name is: '%s'\n", new_name );
convert_file( argv[ 1 ], new_name );
} else {
toret = EXIT_FAILURE;
fprintf( stderr,
"Name results empty, is not ending in '%s' or is too large: '%s'\n",
rle_ext,
argv[ 1 ] );
}
} else {
toret = EXIT_FAILURE;
fprintf( stderr, "Usage: %s <file name>.txt.rle\n", argv[ 0 ] );
}
return toret;
}
您可以使用 strsep (strtok 的后继者)来标记您的输入文件名并复制您感兴趣的部分并丢弃其余部分。
如果您的输入文件名始终采用 file.txt.rle 形式,则可以使用以下代码。
char *name = malloc(sizeof(char) * NAME_SIZE);
if(sprintf(name, "%s.rle", argv[1]) >= sizeof(name)){
fprintf(stderr, "Destination file name is too long\n");
}
char *token = NULL;
char *newfilename = malloc(sizeof(char) * (NAME_SIZE-4)); //strlen(".rle") = 4
uint8_t offset = 0;
memset(newfilename, 0, (NAME_SIZE-4));
while ((token = strsep(&name, ".")) != NULL) {
if(strcmp(token, "rle") == 0) {
break;
}
strncpy(newfilename+offset, token, strlen(token));
offset += strlen(token);
newfilename[offset] = '.';
offset += 1;
}
newfilename[strlen(newfilename)-1] = '\0';
我可能会使用独立函数来完成类似的事情。 在 to_rle() 的情况下,我会避免需要释放的 malloc 指针。 特别是因为它是一个函数调用。降低复杂性,保持简单,使用堆栈。
我还允许新的“ext”参数带或不带“.”
要获取原始数据,请传递相同的“ext”参数。 如果它已被删除,只需将文件名原封不动地恢复即可。 否则,删除添加的扩展。
这是特定情况的,但只需很少的想象力,您就可以使用相同的技术来更改正常的文件扩展名。一句建议:并非所有扩展名都是三个字符,因此您仍然需要一个缓冲区,以防万一。
使用示例:
char *p="filename.txt";
添加扩展名:
p = to_rle(p,"rle");
printf("%s\n",p);
结果:
文件名.txt.rle
现在,删除“.rle”:
p = to_txt(p,"rle");
printf("%s\n",p);
结果:
文件名.txt
char *to_rle(char *str, char *ext)
{
static char buf[512]={0}; //use stack, avoid malloc
strcpy(buf,str); //fname to larger buffer
if((strstr(ext,"."))==NULL)//accept ext arg with or without '.'
strcat(buf,".");
strcat(buf,ext); //append extension
return buf;
}
char *to_txt(char *str, char *ext)
{
char *p,*s;
if((strstr(str,ext))==NULL) //'.rle' already removed
return str;
p=s=str; //point to str
p+=strlen(str); //push p to EOS
while((*p!='.')&&(p>s)) //backup to dot
p--;
*p=0; //terminate
return str;
}