Вопрос

Я использую Linux GCC c99.

Мне интересно, какая техника будет лучшей.Чтобы изменить строку.Я использую strstr();

У меня есть имя файла «file.vce», и я хочу изменить расширение на «file.wav».

Это лучший метод:

char file_name[80] = "filename.vce";
char *new_file_name = NULL;
new_file_name = strstr(file_name, "vce");
strncpy(new_file_name, "wav", 3);
printf("new file name: %s\n", new_file_name);
printf("file name: %s\n", file_name);

Большое спасибо за любой совет,


Я отредактировал свой ответ, используя ваши предложения.Можете ли вы увидеть что-нибудь еще неправильное?

/** Replace the file extension .vce with .wav */
void replace_file_extension(char *file_name)
{
    char *p_extension;

    /** Find the extension .vce */
    p_extension = strrchr(file_name, '.');
    if(p_extension)
    {
        strcpy(++p_extension, "wav");
    }
    else
    {
        /** Filename did not have the .vce extension */
        /** Display debug information */
    }
}

int main(void)
{
    char filename[80] = "filename.vce";

    replace_file_extension(filename);

    printf("filename: %s\n", filename);
    return 0;
}
Это было полезно?

Решение

я бы сделал это

char file_name[80] = "filename.vce";
char *pExt;

pExt = strrchr(file_name, ".");
if( pExt )
  strcpy(++pExt, "wav");
else
{
 // hey no extension
}
printf("file name: %s\n", file_name);

Вам НЕОБХОДИМО манипулировать указателями в каждой программе на языке C.Конечно, вы бы еще немного проверили буфер при прогонах и т. д.или даже использовать функции, специфичные для пути.

Другие советы

Есть несколько проблем:

char file_name[80] = "filename.vce";
char *new_file_name = NULL;
new_file_name = strstr(file_name, "vce");
strncpy(new_file_name, "wav", 3);
printf("new file name: %s\n", new_file_name);
printf("file name: %s\n", file_name);

В памяти хранится только одна строка, но в конце вы пытаетесь напечатать две разные строки.

Переменная с именем new_file_name фактически указывает на часть того же имени файла.

Строка vce может встречаться в любом месте имени файла, а не только в его расширении.Что, если имя файла было srvce.vce?

Вы, вероятно, хотите найти последний .символ в строке, затем проверьте, следует ли за ним ожидаемое расширение, а затем замените это расширение.И помните, что если вы сделаете это, изменив исходный буфер, вы не сможете впоследствии напечатать старую строку.

Вместо того, чтобы искать .или vce, любой из которых может встречаться в строке несколько раз, вычислите длину строки и вычтите 3, чтобы указать на расширение.Замените расширение на месте, используя strncpy.

size_t length;
char* pextension;
char file_name[80] = "filename.vce";
printf("file name: %s\n", file_name);    
length = strlen(file_name);
pextension = file_name + length - 3;
strncpy(pextension, "wav", 3);
printf("new file name: %s\n", file_name);

Вам придется вручную добавить нулевой терминатор в конце new_file_name потому что strncpy() не добавлю его в вашем случае.

Так получилось, что у вас уже есть нулевой байт в нужном месте, но это не может быть гарантировано во всех ситуациях, поэтому хорошей привычкой будет делать такие вещи, как

new_file_name[3] = '\0';

после strncpy().

Также будьте осторожны, внутри имени файла может появиться строка «vce».

Есть несколько проблем с вашим кодом.Вот другой вариант, с комментариями к изменениям:

char file_name[80] = "filename.vce";
char *new_file_name = NULL;

printf("old file name: '%s'\n", file_name);
/* Use strrstr(), to find the last occurance, and include the period. */
new_file_name = strrstr(file_name, ".vce");
if(new_file_name != NULL)
{
  /* Use plain strcpy() to make sure the terminator gets there.
   * Don't forget the period.
  */
  strcpy(new_file_name, ".wav");
}
printf("new file name: '%s'\n", file_name);

Это все еще можно улучшить, например, он не проверяет, достаточно ли места для включения нового расширения.Но он завершает строку несколько более естественным способом, чем возня с отдельными символами.

Мне стало скучно, и вместо того, чтобы указывать на проблемы в исходном коде, я написал свой.Я старался изложить это ясно в поучительных целях.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


/* Replace the last suffix in a filename with a new suffix. Copy the new
   name to a new string, allocated with malloc. Return new string. 
   Caller MUST free new string.

   If old name has no suffix, a period and the new suffix is appended
   to it. The new suffix MUST include a period it one is desired.

   Slashes are interepreted to separate directories in the filename.
   Suffixes are only looked after the last slash, if any.

   */
char *replace_filename_suffix(const char *pathname, const char *new_suffix)
{
    size_t new_size;
    size_t pathname_len;
    size_t suffix_len;
    size_t before_suffix;
    char *last_slash;
    char *last_period;
    char *new_name;

    /* Allocate enough memory for the resulting string. We allocate enough
       for the worst case, for simplicity. */
    pathname_len = strlen(pathname);
    suffix_len = strlen(new_suffix);
    new_size = pathname_len + suffix_len + 1;
    new_name = malloc(new_size);
    if (new_name == NULL)
        return NULL;

    /* Compute the number of characters to copy from the old name. */
    last_slash = strrchr(pathname, '/');
    last_period = strrchr(pathname, '.');
    if (last_period && (!last_slash || last_period > last_slash))
        before_suffix = last_period - pathname;
    else
        before_suffix = pathname_len;

    /* Copy over the stuff before the old suffix. Then append a period
       and the new suffix. */
#if USE_SPRINTF
    /* This uses snprintf, which is how I would normally do this. The
       %.*s formatting directive is used to copy a specific amount
       of text from pathname. Note that this has the theoretical
       problem with filenames larger than will fit into an integer. */
    snprintf(new_name, new_size, "%.*s%s", (int) before_suffix, pathname,
             new_suffix);
#else
    /* This uses memcpy and strcpy, to demonstrate how they might be
       used instead. Much C string processing needs to be done with
       these low-level tools. */
    memcpy(new_name, pathname, before_suffix);
    strcpy(new_name + before_suffix, new_suffix);
#endif

    /* All done. */
    return new_name;
}


int main(int argc, char **argv)
{
    int i;
    char *new_name;

    for (i = 1; i + 1 < argc; ++i) {
        new_name = replace_filename_suffix(argv[i], argv[i+1]);
        if (new_name == NULL) {
            perror("replace_filename_suffix");
            return EXIT_FAILURE;
        }
        printf("original: %s\nsuffix: %s\nnew name: %s\n",
               argv[i], argv[i+1], new_name);
        free(new_name);
    }
    return 0;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top