Extracción de strings en C: funciones estándar y multibyte

目次

1. Introducción

La manipulación de cadenas en el lenguaje C es una de las habilidades importantes al aprender programación. En particular, corte de cadenas (extracción de subcadenas) se usa frecuentemente al procesar datos o al realizar conversiones de formato.

En este artículo, métodos para cortar cadenas en C sobre, el uso de funciones de la biblioteca estándar, la creación de funciones propias, el soporte de caracteres multibyte (japonés) y los métodos para dividir cadenas se explicarán en detalle. Además, se presentarán ejemplos de aplicación y manejo de errores, así que le invitamos a leer hasta el final.

Lo que aprenderá en este artículo

Al leer este artículo, podrá adquirir las siguientes habilidades.

  • Conceptos básicos de cadenas en C y el carácter de terminación su función
  • strncpystrchrextracción de subcadenas usando funciones de la biblioteca estándar
  • función propia
  • Considerando caracteres multibyte (japonés)
  • strtokmétodo de división de cadenas
  • Método para obtener el texto antes y después de un carácter específico

Se explicará de manera que incluso los principiantes lo comprendan, acompañando la explicación con ejemplos de código.

¿Por qué es importante cortar cadenas en C?

El lenguaje C trata las cadenas como arreglos (arreglos de tipo char) , por lo que, a diferencia de lenguajes de alto nivel (Python o JavaScript, entre otros), no es posible obtener subcadenas de forma sencilla. Por ello, es importante elegir el método adecuado en situaciones como las siguientes.

1. Procesamiento de datos de entrada

Por ejemplo, al analizar datos como registros de logs o archivos CSV, es necesario extraer campos específicos.

2. Búsqueda de palabras clave específicas

Buscar una palabra clave específica dentro de una cadena y obtener la información circundante es esencial para funciones de búsqueda y extracción de datos.

3. Mejora de la seguridad del programa

Al usar adecuadamente funciones como strncpy , se puede prevenir desbordamiento de búfer (escritura de datos que exceden el tamaño del búfer) . Esto es importante para evitar riesgos de seguridad.

Estructura del artículo

En este artículo, la explicación seguirá el siguiente orden.

  1. ¿Qué son las cadenas en C? Conceptos básicos y la importancia del carácter de terminación
  2. Método de extraer subcadenas en C [Edición de la biblioteca estándar]
  3. Cómo extraer subcadenas en C [versión con función propia]
  4. Método de extracción de cadenas por código de caracteres
  5. Cómo dividir cadenas en C
  6. Ejemplo de aplicación: Método para extraer el texto antes y después de un carácter específico
  7. Resumen
  8. FAQ

Entonces, primero veamos en detalle “¿Qué son las cadenas en C? Conceptos básicos y la importancia del carácter terminador”.

2. ¿Qué son las cadenas en C? Conceptos básicos y la importancia del carácter de terminación

2.1 Conceptos básicos de las cadenas en C

Las cadenas son «arreglos de char»

En C, las cadenas se tratan como arreglos de caracteres (arreglos de tipo char) como tal. Por ejemplo, el siguiente código es un ejemplo básico de definición y visualización de una cadena.

#include <stdio.h>

int main() {
    char str[] = "Hello, World!"; // Define a string literal as an array
    printf("%s ", str); // Output the string
    return 0;
}

En este código, la cadena "Hello, World!" se almacena como un arreglo de tipo char, y se muestra mediante printf("%s\n", str); .

Estructura interna de la cadena

La cadena "Hello" se almacena en memoria de la siguiente manera.

Índice012345
textoHello\0

En C, un carácter especial que indica el final de la cadena (el carácter nulo '\0') se agrega automáticamente al final , por lo que la longitud de la cadena es «número real de caracteres + 1» .

2.2 Importancia del carácter de terminación (carácter nulo '

¿Qué es el carácter nulo?

'
)

Problemas cuando falta el carácter nulo

El carácter nulo ('\0') es un carácter especial que indica el final de una cadena. Para manejar correctamente las cadenas en C, es necesario comprender la existencia de este carácter nulo.

#include <stdio.h>

int main() {
    char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicitly specify the null terminator
    printf("%s ", str);                            // Display correctly
    return 0;
}

En el código anterior, si falta '\0', el final de "Hello" no se reconoce, lo que puede provocar comportamientos inesperados.

2.3 Forma correcta de definir cadenas

Como se muestra a continuación, si se olvida el carácter de terminación, existe la posibilidad de provocar un comportamiento anómalo de la memoria.

#include <stdio.h>

int main() {
    char str[5] = {'H', 'e', 'l', 'l', 'o'}; // Does not include the null terminator
    printf("%s ", str);                      // May cause unexpected behavior
    return 0;
}

Causa del error

  • printf("%s\n", str);el carácter nulo '\0' que continúa imprimiendo caracteres hasta que lo encuentra
  • Si no está presente, existe la posibilidad de que se muestren otros datos en la memoria.

Método ① Usar literal de cadena

Método ② Definir el arreglo explícitamente

El método más común para definir una cadena es usar un literal de cadena.

char str[] = "Hello";

Con este método, el compilador de C agrega automáticamente el carácter nulo '\0', por lo que no se requiere procesamiento especial.

2.4 Cómo verificar el tamaño de una cadena

Si se define manualmente incluyendo '\0', se escribe de la siguiente manera.

char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
  • Es importante especificar el tamaño de caracteres y, al final, colocar 。
  • Si se olvida de colocar en , se producirá un comportamiento inesperado.

Funcionamiento de strlen

Para obtener la longitud (número de caracteres) de una cadena, se utiliza la función strlen.

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

int main() {
    char str[] = "Hello";
    printf("Length of the string: %lu\n", strlen(str)); // Outputs 5 (does not include the null terminator)
    return 0;
}

2.5 Resumen

  • strlencarácter nulo '\0'
  • sizeof(str)

3. Método para extraer subcadenas en C【Biblioteca estándar】

  1. Las cadenas de C se representan con un arreglo de char se representan con un arreglo
  2. El carácter final (carácter nulo '\0') indica el final de la cadena, por lo que debe incluirse siempre
  3. Para obtener la longitud de una cadena, use strlen
  4. Si no defines la cadena de manera adecuada, puede ocurrir un error inesperado.

3.1 Obtención de subcadenas usando strncpy

Para extraer subcadenas en C, existe un método que aprovecha la biblioteca estándar. En esta sección, se explicará cómo obtener partes de una cadena usando strncpy y strchr funciones de la biblioteca estándar para obtener partes de una cadena.

Sintaxis básica de strncpy

strncpy es una función que copia una parte de una cadena a otro búfer.

Ejemplo básico de uso

char *strncpy(char *dest, const char *src, size_t n);
  • dest
  • src
  • n'\0'

Precauciones de strncpy

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];  // Buffer to store the substring

    strncpy(dest, src, 5); // Copy the first 5 characters "Hello"
    dest[5] = '\0';        // Manually add the null terminator

    printf("Substring: %s\n", dest);  // Output "Hello"

    return 0;
}

3.2 Copia segura de cadenas usando strncpy_s

  1. carácter nulo '\0' es necesario añadirlo manualmentestrncpyn'\0' no se añade automáticamente, dest[n] = '\0';
  2. Cuidado con el desbordamiento de búferndest

Sintaxis básica de strncpy_s

strncpy_s es una versión de strncpy con mayor seguridad, que permite prevenir desbordamientos de búfer.

Ejemplo de uso

errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n);
  • dest
  • destszdest
  • src
  • n

Ventajas de strncpy_s

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];

    if (strncpy_s(dest, sizeof(dest), src, 5) == 0) {
        dest[5] = '\0';  // Add null terminator just in case
        printf("Substring: %s\n", dest);
    } else {
        printf("Copy error\n");
    }

    return 0;
}

3.3 Extracción hasta un carácter específico usando strchr

  • Para especificar el tamaño del búfer (), se puede copiar de manera segura.
  • Si es mayor que , devuelve un error.

Sin embargo, strncpy_s se añadió en la norma C11, por lo que es necesario tener en cuenta que puede no estar disponible en algunos entornos.

Sintaxis básica de strchr

strchr permite encontrar la posición de un carácter específico y obtener la subcadena hasta esa posición.

Ejemplo de uso

char *strchr(const char *str, int c);
  • str
  • cchar

Puntos clave

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

int main() {
    char str[] = "Hello, World!";
    char *pos = strchr(str, ','); // Find the position of ','

    if (pos != NULL) {
        int length = pos - str; // Calculate the number of characters up to ','
        char result[20];

        strncpy(result, str, length);
        result[length] = '\0'; // Add the null terminator

        printf("Substring: %s\n", result);  // Output "Hello"
    }

    return 0;
}

3.4 Búsqueda de palabras clave y extracción usando strstr

  • strchr devuelve la dirección del primer c encontrado,
  • pos - strstrncpy

Sintaxis básica de strstr

strstr es útil para buscar una subcadena y obtener el resto de la cadena de esa posición.

Ejemplo de uso

char *strstr(const char *haystack, const char *needle);
  • haystack
  • needle

Puntos clave

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

int main() {
    char str[] = "Hello, World!";
    char *pos = strstr(str, "World"); // Search for the position of "World"

    if (pos != NULL) {
        printf("Found substring: %s\n", pos);
    } else {
        printf("Substring not found.\n");
    }

    return 0;
}

3.5 Resumen

  • strstrneedle
  • NULLneedlehaystack

4. Cómo extraer subcadenas en C (funciones personalizadas)

  1. strncpy si se usa, se puede copiar subcadenas de forma segura, pero es necesario añadir el carácter nulo manualmente.
  2. strncpy_s permite especificar destsz y mejora la seguridad.
  3. strchr Si lo usas, puedes obtener la subcadena hasta un carácter específico.
  4. strstr Si lo usas, puedes obtener la posición de una palabra clave específica y luego recortar a partir de allí.

Al aprovechar la biblioteca estándar, se puede implementar el manejo de cadenas en C de forma simple y segura.

4.1 Ventajas de crear funciones personalizadas

Si se aprovecha la biblioteca estándar, es posible extraer subcadenas básicas, pero en algunos casos se requiere un método más flexible. Por ello, en esta sección se explica la extracción de subcadenas usando funciones personalizadas.

4.2 Función básica de extracción de subcadenas

Al usar la biblioteca estándar, se pueden copiar y buscar subcadenas, pero existen los siguientes problemas.

  • strncpy no añade automáticamente el carácter nulo '\0'
  • strchr y strstr solo permite búsquedas parciales
  • Manipular cadenas de forma más flexible es difícil

Por lo tanto, crear funciones personalizadas que se puedan adaptar a usos específicos es eficaz.

Especificación de la función

Primero, se crea una función básica que extrae la cadena a partir de la posición especificada.

Código de implementación

  • Argumento
  • const char *source
  • int start
  • int length
  • char *dest
  • Contenido del procesamiento
  • Copiar una cadena de caracteres desde hasta
  • '\0'

Puntos clave

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

void substring(const char *source, int start, int length, char *dest) {
    int i;
    for (i = 0; i < length && source[start + i] != '\0'; i++) {
        dest[i] = source[start + i];
    }
    dest[i] = '\0'; // Add null terminator
}

int main() {
    char text[] = "Hello, World!";
    char result[10];

    substring(text, 7, 5, result); // Extract "World"
    printf("Substring: %s\n", result);

    return 0;
}

4.3 Obtención dinámica de subcadenas usando malloc

  • forlength
  • '\0'
  • dest[i] = '\0'; siempre colocar el carácter nulo al final

Especificación de la función

En la función anterior, es necesario reservar previamente el tamaño de dest. Sin embargo, si se puede reservar dinámicamente el tamaño necesario, la función será más genérica.

Código de implementación

  • La memoria necesaria con
  • startlength
  • El llamador debe

Puntos clave

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

char *substring_dynamic(const char *source, int start, int length) {
    char *dest = (char *)malloc(length + 1); // +1 for the null terminator
    if (dest == NULL) {
        return NULL; // Memory allocation failed
    }

    int i;
    for (i = 0; i < length && source[start + i] != '\0'; i++) {
        dest[i] = source[start + i];
    }
    dest[i] = '\0';

    return dest;
}

int main() {
    char text[] = "Hello, World!";
    char *result = substring_dynamic(text, 7, 5);

    if (result != NULL) {
        printf("Substring: %s\n", result);
        free(result); // Free allocated memory
    } else {
        printf("Memory allocation failed.\n");
    }

    return 0;
}

4.4 Compatibilidad con caracteres multibyte (japonés)

  • mallocla asignación dinámica de memoria
  • Después de usarlo, es necesario liberar la memoria con .

Implementación considerando caracteres multibyte

Al manejar japonés (caracteres multibyte como UTF-8), un carácter no necesariamente ocupa 1 byte, por lo que una función simple de substring no funciona correctamente.

Código de implementación (compatible con UTF-8)

  • mbstowcswchar_t
  • wcsncpy
  • wcstombs

Puntos clave

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

void substring_utf8(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, ""); // Set the locale

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert UTF-8 string to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Extract substring in wide characters
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert back to multibyte string
}

int main() {
    char text[] = "こんにちは、世界!"; // UTF-8 string
    char result[20];

    substring_utf8(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

4.5 Resumen

  • setlocale(LC_ALL, "");
  • mbstowcs
  • wcsncpywcstombs

5. Métodos de extracción de subcadenas según la codificación de caracteres

  1. substring si lo creas tú mismo, puedes obtener subcadenas de forma flexible.
  2. Al utilizar la asignación dinámica de memoria (malloc), es posible obtener subcadenas de tamaño variable。
  3. Cuando se manejan caracteres multibyte (japonés), mbstowcs / wcstombs utilice。

Cuando la biblioteca estándar, como strncpy o strchr, resulta difícil de usar, crear funciones personalizadas permite hacer el manejo de cadenas en C más potente.

5.1 ASCII (caracteres de 1 byte)

En el lenguaje C、si no se presta atención a las diferencias de codificación de caracteres, el proceso de extracción de subcadenas puede no funcionar correctamente puede ocurrir. En particular, al manejar caracteres multibyte como el japonés (UTF-8, Shift_JIS, EUC-JP, etc.), porque 1 carácter no equivale a 1 byte, las funciones simples strncpy y substring no pueden procesarlo adecuadamente.

En esta sección, Métodos de extracción de subcadenas según la codificación de caracteres se explican detalladamente.

Obtención básica de subcadenas

Ejemplo de implementación

Los caracteres ASCII son 1 carácter = 1 byte , por lo que las funciones strncpy y substring pueden procesarse fácilmente.

5.2 UTF-8 (caracteres multibyte)

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

void substring_ascii(const char *source, int start, int length, char *dest) {
    strncpy(dest, source + start, length);
    dest[length] = '\0'; // Add null terminator
}

int main() {
    char text[] = "Hello, World!";
    char result[6];

    substring_ascii(text, 7, 5, result); // Extract "World"
    printf("Substring: %s\n", result);

    return 0;
}

Puntos

  • En el caso de caracteres ASCII (solo alfanuméricos), strncpy es suficiente para manejarlo
  • '\0'Siempre añada (carácter nulo)

Características de UTF-8

Método de procesamiento correcto

En UTF-8, el número de bytes por carácter es 1-4 bytes y variable, por lo que usar strncpy directamente puede cortar el carácter a la mitad.

Obtención de subcadenas compatible con UTF-8

En el lenguaje C, para procesar UTF-8 de forma segura se recomienda usar mbstowcs para convertir a una cadena ancha ( wchar_t ) y obtener la subcadena.

5.3 Shift_JIS (caracteres multibyte)

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>

void substring_utf8(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, ""); // Set the locale

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert multibyte string to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Get the substring
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte
}

int main() {
    char text[] = "こんにちは、世界!"; // UTF-8 string
    char result[20];

    substring_utf8(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

Puntos

  • setlocale(LC_ALL, "");
  • Con convierte la cadena multibyte a y la procesa de forma segura con .
  • wcstombs

Características de Shift_JIS

Obtención de subcadenas compatible con Shift_JIS

En Shift_JIS, 1 carácter puede ser 1 byte o 2 bytes , por lo que usar strncpy simple puede causar corrupción de texto.

Implementación en Shift_JIS

En el caso de Shift_JIS también se recomienda convertir a cadena ancha y procesar.

5.4 EUC-JP (caracteres multibyte)

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>

void substring_sjis(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, "Japanese"); // Set locale to handle Shift_JIS

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert multibyte string (Shift_JIS) to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Extract substring
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (Shift_JIS)
}

int main() {
    char text[] = "こんにちは、世界!"; // Shift_JIS string (depending on environment)
    char result[20];

    substring_sjis(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

Puntos

  • Para procesar correctamente Shift_JIS, configure
  • mbstowcswcstombs

Características de EUC-JP

Obtención de subcadenas compatible con EUC-JP

EUC-JP, al igual que Shift_JIS, tiene una longitud de byte variable por carácter, por lo que es necesario usar conversiones a caracteres anchos.

5.5 Resumen

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>

void substring_eucjp(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, "ja_JP.eucJP"); // Set locale to handle EUC-JP

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert multibyte string (EUC-JP) to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Extract substring
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (EUC-JP)
}

int main() {
    char text[] = "こんにちは、世界!"; // EUC-JP string (depending on environment)
    char result[20];

    substring_eucjp(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

Puntos

  • setlocale(LC_ALL, "ja_JP.eucJP");
  • mbstowcswcstombs

6. Cómo dividir cadenas en C

código de caracteresNúmero de bytesMétodo de procesamiento recomendado
ASCII1 bytestrncpy
UTF-81-4 bytesmbstowcswcstombs
Shift_JIS1 o 2 bytesmbstowcswcstombs
EUC-JP1 o 2 bytesmbstowcswcstombs
  • si solo hay texto ASCII strncpy está bien
  • En caso de UTF-8, Shift_JIS, EUC-JP, use mbstowcs / wcstombs use
  • Según el entorno setlocale(LC_ALL, "..."); establezca correctamente

6.1 División de cadenas usando strtok

El proceso de dividir cadenas es necesario en muchos casos, como el análisis de datos CSV, el procesamiento de argumentos de línea de comandos, el análisis de datos de registro y otros. En C, existen métodos que utilizan funciones de la biblioteca estándar como strtok y strtok_r, así como la posibilidad de crear funciones propias.

En esta sección, cómo dividir una cadena usando un delimitador específico se explica en detalle.

基本構文

strtok es una función que divide una cadena usando los delimitadores especificados (delimitador).

Ejemplo de uso: dividir una cadena con coma ,

char *strtok(char *str, const char *delim);
  • str
  • delim
  • Valor de retorno
  • Puntos a tener en cuentastrtok'\0'

Resultado de la ejecución

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


int main() {
    char str[] = "apple,banana,orange,grape"; // String to be split
    char *token = strtok(str, ",");            // Get the first token

    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok(NULL, ",");             // Get the next token
    }

    return 0;
}

Consideraciones sobre strtok

token: apple
token: banana
token: orange
token: grape

6.2 División de cadenas segura para hilos usando strtok_r

  1. Cambiar la cadena original
  • strtokcarácter delimitador reemplaza con '\0'
  1. no es thread-safe
  • strtokque utiliza una variable estática global internamente

基本構文

strtok_r es la versión segura para hilos de strtok, y guarda su estado en saveptr para que pueda usarse de forma segura en entornos multihilo.

Ejemplo de uso: dividir una cadena con espacio

char *strtok_r(char *str, const char *delim, char **saveptr);
  • str
  • delim
  • saveptr

Ventajas de strtok_r

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

int main() {
    char str[] = "Hello World from C"; // String to be split
    char *token;
    char *saveptr; // Pointer to store internal state

    token = strtok_r(str, " ", &saveptr); // Get the first token
    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok_r(NULL, " ", &saveptr); // Get the next token
    }

    return 0;
}

6.3 Dividir cadenas con una función propia (método sin usar strtok)

  • seguro en hilos
  • Puede procesar múltiples cadenas en paralelo

Especificaciones de la función propia

strtok modifica la cadena original, por lo que es posible crear una función propia que divida la cadena sin modificarla.

Código de implementación

  • entrada
  • const char *source
  • const char delim
  • char tokens[][50]
  • procesamiento
  • source
  • delimtokens

Resultado de la ejecución

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

void split_string(const char *source, char delim, char tokens[][50], int *count) {
    int i = 0, j = 0, token_index = 0;

    while (source[i] != '\0') {
        if (source[i] == delim) {
            tokens[token_index][j] = '\0';
            token_index++;
            j = 0;
        } else {
            tokens[token_index][j] = source[i];
            j++;
        }
        i++;
    }
    tokens[token_index][j] = '\0';
    *count = token_index + 1;
}

int main() {
    char text[] = "dog,cat,bird,fish";
    char tokens[10][50]; // Can store up to 10 words
    int count;

    split_string(text, ',', tokens, &count);

    for (int i = 0; i < count; i++) {
        printf("Token: %s\n", tokens[i]);
    }

    return 0;
}

Puntos clave

Token: dog
Token: cat
Token: bird
Token: fish

6.4 Aplicación de la división de cadenas (procesamiento de datos CSV)

  • source
  • tokens

Ejemplo de análisis de datos CSV

Se pueden analizar datos CSV (separados por comas) usando strtok.

Resultado de la ejecución

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

int main() {
    char csv[] = "Alice,24,Female\nBob,30,Male\nCharlie,28,Male"; // CSV data
    char *line = strtok(csv, "\n"); // Process line by line

    while (line != NULL) {
        char *name = strtok(line, ",");
        char *age = strtok(NULL, ",");
        char *gender = strtok(NULL, ",");

        printf("Name: %s, Age: %s, Gender: %s\n", name, age, gender);

        line = strtok(NULL, "\n");
    }

    return 0;
}

6.5 Resumen

Name: Alice, Age: 24, Gender: Female
Name: Bob, Age: 30, Gender: Male
Name: Charlie, Age: 28, Gender: Male

Conclusión

MétodoVentajasdesventajas
strtokse puede dividir fácilmenteCambiar la cadena original
strtok_rseguro en hilosEl uso es un poco complicado
función personalizadaNo modifiques la cadena originalel código se vuelve largo
Análisis de CSVConveniente para el procesamiento de datosstrtok prestar atención a las limitaciones

7. Ejemplo de aplicación: Método para extraer el texto antes y después de un carácter específico

  • Si es una división simple strtok
  • si es multihilo strtok_r
  • Si no quieres cambiar el original, crea tu propia función
  • También aplicable al análisis de datos CSV

En la siguiente sección, se explicará en detalle el ejemplo de aplicación: «Cómo extraer los caracteres antes y después de un carácter específico«.

7.1 strchr para obtener la cadena anterior a un carácter específico

En el procesamiento de cadenas, extraer el texto antes y después de caracteres o palabras clave específicos es una operación que a menudo se necesita. Por ejemplo, se pueden considerar los siguientes casos.

  • Obtener solo la parte del dominio de la URL
  • Extraer el nombre del archivo desde la ruta del archivo
  • Obtener la cadena antes y después de etiquetas o símbolos específicos

En el lenguaje C, strchr y strstr pueden utilizarse para implementar este tipo de procesamiento. Además, si se requiere un procesamiento más flexible, crear funciones propias también es una solución eficaz.

Sintaxis básica

strchr permite identificar la posición de un carácter (el primero que se encuentre).

Ejemplo de uso: Obtener el nombre de archivo a partir de la ruta del archivo

char *strchr(const char *str, int c);
  • str
  • cchar

strchr devuelve la dirección cuando encuentra el c.

Resultado de la ejecución

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

void get_filename(const char *path, char *filename) {
    char *pos = strrchr(path, '/'); // Search for the last '/'

    if (pos != NULL) {
        strcpy(filename, pos + 1); // Copy from the character after '/'
    } else {
        strcpy(filename, path); // If no '/', copy the whole path
    }
}

int main() {
    char path[] = "/home/user/documents/report.txt";
    char filename[50];

    get_filename(path, filename);
    printf("Filename: %s\n", filename);

    return 0;
}

Puntos clave

Filename: report.txt

7.2 strstr para obtener la cadena posterior a una palabra clave específica

  • strrchrobtener la posición del carácter específico que aparece por última vez ( / )
  • pos + 1solo puedes obtener el nombre del archivo

Sintaxis básica

strstr permite buscar una cadena específica (palabra clave) y obtener la cadena que sigue a esa posición.

Ejemplo de uso: Obtener el dominio a partir de una URL

char *strstr(const char *haystack, const char *needle);
  • haystack
  • needle

strstr devuelve la dirección de la posición donde encuentra el needle.

Resultado de la ejecución

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

void get_domain(const char *url, char *domain) {
    char *pos = strstr(url, "://"); // Search for the position of "://"

    if (pos != NULL) {
        strcpy(domain, pos + 3); // Copy from the character after "://"
    } else {
        strcpy(domain, url); // If "://" is not found, copy the entire string
    }
}

int main() {
    char url[] = "https://www.example.com/page.html";
    char domain[50];

    get_domain(url, domain);
    printf("Domain part: %s\n", domain);

    return 0;
}

Puntos clave

Domain part: www.example.com/page.html

7.3 strchr para dividir las partes antes y después de un carácter específico

  • strstr"https://""http://""//"
  • pos + 3://

Ejemplo de uso: Separar el nombre de usuario y el dominio de una dirección de correo electrónico

strchr permite dividir y obtener la cadena antes y después de un carácter específico.

Resultado de la ejecución

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

void split_email(const char *email, char *username, char *domain) {
    char *pos = strchr(email, '@'); // Search for the position of '@'

    if (pos != NULL) {
        strncpy(username, email, pos - email); // Copy the part before '@'
        username[pos - email] = '\0';          // Add null terminator
        strcpy(domain, pos + 1);               // Copy the part after '@'
    }
}

int main() {
    char email[] = "user@example.com";
    char username[50], domain[50];

    split_email(email, username, domain);
    printf("Username: %s\n", username);
    printf("Domain: %s\n", domain);

    return 0;
}

Puntos clave

Username: user
Domain: example.com

7.4 Aplicación: Extraer un atributo específico dentro de una etiqueta HTML

  • strchr'@'
  • strncpy'@' la parte antes de ‘@’ y añade un carácter nulo
  • strcpy'@' copiar la parte después de

Ejemplo de uso: Obtener la URL de <a href="URL">

Incluso al obtener un atributo específico de una etiqueta HTML, se puede utilizar strstr .

Resultado de la ejecución

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

void get_href(const char *html, char *url) {
    char *start = strstr(html, "href=\""); // Search for the position of href="
    if (start != NULL) {
        start += 6; // Move past href="
        char *end = strchr(start, '"'); // Search for the next "
        if (end != NULL) {
            strncpy(url, start, end - start);
            url[end - start] = '\0'; // Add null terminator
        }
    }
}

int main() {
    char html[] = "<a href=\"https://example.com\">Click Here</a>";
    char url[100];

    get_href(html, url);
    printf("Extracted URL: %s\n", url);

    return 0;
}

Puntos clave

Extracted URL: https://example.com

7.5 Resumen

  • strstr"href=\"
  • strchr"

Conclusión

Contenido del procesoUso de la funciónVentajas
Obtener antes de un carácter específicostrchr / strrchrSimple y rápido
Obtener después de un carácter específicostrstrLa búsqueda por palabras clave es posible
Dividir antes y después de un carácter específicostrchr + strncpyConveniente para la división de nombre de usuario y dominio, etc.
Obtención de atributos de etiquetas HTMLstrstr + strchrAplicable a la extracción web

8. Resumen

  • strchr y strstr al aprovecharlos, puedes obtener fácilmente antes y después de un carácter o palabra clave
  • El manejo de rutas de archivos, el análisis de URL, la división de direcciones de correo electrónico, etc., son útiles en muchas situaciones.
  • Aplicable incluso a procesos avanzados como el web scraping

8.1 Repaso del artículo

En este artículo, Métodos de extracción de cadenas en C sobre, se explicó detalladamente desde lo básico hasta lo avanzado. Aquí, repasaremos los puntos clave de cada sección y organizaremos los métodos óptimos según el uso.

8.2 Métodos óptimos según el uso

SecciónContenidoPuntos importantes
Fundamentos de las cadenas en CEn C, las cadenas se tratan como un arreglo , y el carácter final es importante.Al manejar cadenas,
Extracción con la biblioteca estándarstrncpystrchrstrncpyterminador nulo manualmente agregado
Extracción mediante función propiaCrear una función flexiblemalloc se puede obtener una subcadena de longitud variable
Procesamiento por código de caracteresCómo manejar UTF-8, Shift_JIS, EUC-JPmbstowcswcstombses seguro convertir a caracteres anchos
Método de división de cadenasstrtokstrtok_rstrtokla cadena original se modifica
Extraer los caracteres antes y después de un carácter específicostrchrstrstrObtención de nombres de archivo, análisis de URL, análisis de HTML

1. Extracción de subcadenas

2. División de cadenas

situaciones de usoEl método óptimo
Quiero obtener una cadena de cierta longitudstrncpy or substring()
Quiero hacer un corte segurostrncpy_s
Manejo de caracteres multibyte (UTF-8, Shift_JIS, EUC-JP)mbstowcs / wcstombs

3. Obtención del texto antes y después de un carácter específico

situaciones de usoel método óptimo
Quiero dividir la cadena de manera simplestrtok
Quiero hacer una división segura para hilosstrtok_r
Quiero dividir sin modificar la cadena original.función personalizada(split_string()

8.3 Precauciones en el manejo de cadenas en C

Escenario de usoEl método óptimo
Obtener el nombre del archivo a partir de la ruta del archivostrrchr(path, '/')
Obtener la parte del dominio de la URLstrstr(url, "://")
Separar el nombre de usuario y el dominio de la dirección de correo electrónicostrchr(email, '@')
Obtener el valor del atributo de una etiqueta HTMLstrstr(tag, "href=\"") + strchr(tag, '"')

1. Gestionar rigurosamente la terminación nula '
Ejemplo de copia segura de cadenas
'

2. Tener cuidado con el desbordamiento de búfer

En el manejo de cadenas en C, el carácter de terminación '\0' debe gestionarse adecuadamente, lo cual es lo más importante. En particular, al usar strncpy o strchr, tenga cuidado de añadir manualmente el carácter nulo.

3. Para el manejo de caracteres multibyte, use mbstowcs

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];

    strncpy(dest, src, 5);
    dest[5] = '\0'; // Add null terminator for safety

    printf("Substring: %s\n", dest);

    return 0;
}

4. Gestión del tamaño del búfer

En la manipulación de cadenas en C, es necesario implementar con cuidado para no acceder fuera de los límites del arreglo. En particular, al usar strncpy, es importante controlar la cantidad de bytes a copiar.

Ejemplo de copia segura de cadenas

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];

    strncpy(dest, src, sizeof(dest) - 1);
    dest[5] = '\0'; // Explicitly add null terminator

    printf("Substring: %s\n", dest);
    return 0;
}

8.4 Hacia un aprendizaje adicional

Al trabajar con caracteres multibyte como UTF-8 o Shift_JIS, strncpy y strlen no funcionan correctamente.

Por lo tanto, cuando se manejan caracteres multibyte, se recomienda convertir primero a una cadena ancha con mbstowcs y luego procesarla adecuadamente.

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main() {
    setlocale(LC_ALL, ""); // Set the locale

    char text[] = "こんにちは、世界!"; // UTF-8
    wchar_t wtext[256];

    mbstowcs(wtext, text, 256); // Convert to wide-character string

    printf("Converted wide-character string: %ls\n", wtext);

    return 0;
}

Temas para profundizar el aprendizaje

En el manejo de cadenas, es importante calcular previamente el tamaño de memoria necesario y prevenir el desbordamiento del búfer. En particular, al usar malloc para asignar memoria dinámica, asegúrese de conocer con precisión el tamaño requerido.

8.5 Resumen

El manejo de cadenas en C es una habilidad importante para mejorar la seguridad y la legibilidad del programa. Basándose en lo presentado en este artículo, aprender los siguientes temas permitirá realizar un manejo de cadenas más avanzado.

Temas para profundizar el aprendizaje

  1. Expresiones regulares (regex)
  2. Operaciones de archivos (procesamiento de cadenas usando fgets, fscanf)
  3. Gestión de memoria (procesamiento de cadenas dinámicas usando malloc, realloc)
  4. Análisis de datos (Métodos de análisis de JSON, XML)

8.5 Resumen

  1. Las cadenas en C se gestionan con un arreglo char, por lo que el manejo del carácter terminador '\0' es importante
  2. Para extraer subcadenas, se usan strncpy, substring(), malloc
  3. Para la división de cadenas, strtok / strtok_r / utilizar funciones propias
  4. Para obtener el texto antes y después de un carácter específico, utilice strchr, strstr utilice
  5. Cuando se manejen caracteres multibyte (japonés), mbstowcs se utilice
  6. Practica un manejo seguro de cadenas y presta atención a los desbordamientos de búfer

Si aprovecha el contenido de este artículo, podrá realizar procesamiento práctico de cadenas en C. Después de comprender las funciones básicas, desafíese a crear sus propias funciones y a aplicar técnicas avanzadas para escribir código más eficiente!

侍エンジニア塾