1

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;
}
4

6 に答える 6

3

いくつかの問題があります:

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);

1 つの文字列用のストレージしかありませんが、最後に 2 つの異なる文字列を出力しようとします。

という名前の変数は、new_file_name実際には同じファイル名の一部を指しています。

文字列 vce は、拡張子だけでなく、ファイル名内のどこにでも出現する可能性があります。ファイル名がsrvce.vce.

おそらく最後の . 文字列内の文字の後に、予想される拡張子が続くかどうかを確認し、その拡張子を置き換えます。また、元のバッファを変更してこれを行うと、後で古い文字列を出力できなくなることに注意してください。

于 2009-03-27T07:41:35.973 に答える
2

を検索するのではなく、. または 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);
于 2009-03-27T11:51:51.253 に答える
1

私は退屈していて、元のコードの問題を指摘する代わりに、自分で書いた。私は、有益な目的のためにそれを明確に保つように努めました。

#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;
}
于 2009-03-27T12:38:49.147 に答える
1

私はこれをするだろう

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 プログラムでポインター操作を行う必要があります。もちろん、バッファオーバーランなどをさらにチェックしたり、パス固有の関数を使用したりすることもできます。

于 2009-03-27T11:15:40.937 に答える
1

new_file_nameあなたのケースでは追加されないため、末尾にゼロターミネータを手動で追加する必要がありstrncpy()ます。

たまたま正しい場所にすでにゼロバイトがありますが、すべての状況で保証されるわけではないため、次のようなことを行うのは良い習慣です

new_file_name[3] = '\0';

strncpy()

また、ファイル名内に文字列「vce」が表示される場合があることに注意してください。

于 2009-03-27T07:34:49.920 に答える
1

コードにはいくつかの問題があります。これは別のテイクで、変更がインラインでコメントされています。

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);

これはまだ改善される可能性があります。たとえば、新しい拡張機能を含めるのに十分なスペースがあるかどうかはチェックされません。ただし、単一の文字を突き刺すよりも少し自然な方法で、文字列を終了します。

于 2009-03-27T07:51:31.770 に答える