Pregunta

Estoy utilizando Linux c99 GCC.

Me pregunto cuál sería el mejor técnica. Para cambiar una cadena. Estoy usando strstr ();

Tengo un nombre de archivo llamado "file.vce" y quiero cambiar la extensión a "file.wav".

¿Es este el mejor método:

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

Muchas gracias por cualquier consejo,


He editado mi respuesta mediante el uso de sus sugerencias. ¿Puede usted ver cualquier otra cosa mal?

/** 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;
}
¿Fue útil?

Solución

Me gustaría hacer esto

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

lo que necesita hacer manipulación de punteros en cada programa c. Por supuesto que haría un poco más de la comprobación de memoria intermedia en tramos etc. o incluso utiliza la ruta de funciones específicas.

Otros consejos

Hay algunos problemas con:

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

Sólo hay un almacenamiento de un hilo, pero al final se intenta imprimir dos cadenas diferentes.

El llamado new_file_name variables efectivamente apunta a una parte del mismo nombre de archivo.

El VCE cadena podría ocurrir en cualquier lugar dentro de un nombre de archivo, no sólo una la extensión. ¿Qué pasa si se srvce.vce el nombre del archivo?

Es posible que desee para encontrar la última. carácter de la cadena, a continuación, comprobar si es seguido por la extensión esperada, y luego vuelva a esa extensión. Y recuerde que si usted hace esto mediante la modificación del búfer original, usted no será capaz de imprimir la cadena antigua después.

En lugar de buscar. o vce cualquiera de los cuales puede aparecer varias veces en la cadena, el cálculo de la longitud de la cadena y restar 3 a punto a la extensión. Vuelva a colocar la extensión en el lugar utilizando 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);

Hay que añadir manualmente cero terminador al final de new_file_name porque strncpy() no añadirá en su caso.

Se acaba de ocurrir que ya tiene cero bytes en el lugar correcto, pero no puede ser garantizada en todas las situaciones por lo que es un buen hábito de hacer cosas como

new_file_name[3] = '\0';

después strncpy().

También tenga cuidado con esa cadena "VCE" puede aparecer dentro de nombre de archivo.

Hay algunos problemas con su código. He aquí un punto de vista diferente, con los cambios comentados en línea:

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

Esto todavía se puede mejorar, no comprueba que hay espacio suficiente para incluir la nueva extensión, por ejemplo. Pero lo hace interrumpir la cadena, de un modo ligeramente más natural que hurgando en caracteres individuales.

estoy aburrido, y en lugar de señalar los problemas en el código original, escribí mi propia. Traté de que queden libres para los propósitos instructivos.

#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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top