utiliza sirve que para objective manipulation functions array c++ string initialization string-literals memset

sirve - ¿Cómo usar memset en c++?



string string c (4)

Soy de fondo Python y recientemente estoy aprendiendo C ++. Estaba aprendiendo una función de C / C ++ llamada memset y siguiendo el ejemplo en línea del sitio web https://www.geeksforgeeks.org/memset-in-cpp/ donde obtuve algunos errores de compilación:

/** * @author : Bhishan Poudel * @file : a02_memset_geeks.cpp * @created : Wednesday Jun 05, 2019 11:07:03 EDT * * Ref: */ #include <iostream> #include <vector> #include <cstring> using namespace std; int main(int argc, char *argv[]){ char str[] = "geeksforgeeks"; //memset(str, "t", sizeof(str)); memset(str, ''t'', sizeof(str)); cout << str << endl; return 0; }

Error al usar comillas simples ''t''
Esto imprime caracteres adicionales.

tttttttttttttt!R@`

Error al usar "t" con comillas dobles

$ g++ -std=c++11 a02_memset_geeks.cpp a02_memset_geeks.cpp:17:5: error: no matching function for call to ''memset'' memset(str, "t", sizeof(str)); ^~~~~~ /usr/include/string.h:74:7: note: candidate function not viable: no known conversion from ''const char [2]'' to ''int'' for 2nd argument void *memset(void *, int, size_t); ^ 1 error generated.

¿Cómo usar el memset en C ++?

Estudio adicional
Se proporciona excelente tutorial con deficiencias de memset aquí: https://web.archive.org/web/20170702122030/https:/augias.org/paercebal/tech_doc/doc.en/cp.memset_is_evil.html


Error al usar comillas simples ''t'' Esto imprime caracteres extra.

Eso es porque sobrescribiste el terminador nulo.

El terminador es parte del tamaño de la matriz (una matriz no es mágica), aunque no es parte del tamaño de la cadena lógica .

Entonces, creo que quiso decir:

memset(str, ''t'', strlen(str)); // ^^^^^^

Error al usar "t" con comillas dobles

Una cosa completamente diferente. Le dijiste a la computadora que configurara todos los caracteres de la cadena a una cadena. No tiene sentido; no compilará

¿Cómo usar memset en C ++?

No lo hagas

Utilice el tipo seguro std::fill , en combinación con std::begin y std::end :

std::fill(std::begin(str), std::end(str)-1, ''t'');

(Si está preocupado por el rendimiento, no lo haga: esto solo se delegará a memset través de la especialización de plantillas, no se requiere optimización, sin sacrificar la seguridad de tipos; por ejemplo, aquí en libstdc ++ ).

O simplemente una std::string para empezar. 😊

Estaba aprendiendo el memset de funciones en C ++ de https://www.geeksforgeeks.org/memset-in-cpp/ donde se da el ejemplo como se muestra a continuación

No intentes aprender C ++ de sitios web aleatorios. Consíguete un buen libro en su lugar.


Esta declaracion

char str[] = "geeksforgeeks";

declara una matriz de caracteres que contiene una cadena que es una secuencia de caracteres que incluye el símbolo de cero ''/0'' .

Puedes imaginar la declaración de la siguiente manera equivalente.

char str[] = { ''g'', ''e'', ''e'', ''k'', ''s'', ''f'', ''o'', ''r'', ''g'', ''e'', ''e'', ''k'', ''s'', ''/0'' };

Esta llamada de la función memset

memset(str, ''t'', sizeof(str));

anula todos los caracteres de la matriz, incluido el cero de terminación.

Así que la siguiente afirmación

cout << str << endl;

da como resultado un comportamiento indefinido porque salta a los caracteres hasta que se encuentra el cero final.

Podrías escribir en su lugar

#include <iostream> #include <cstring> int main() { char str[] = "geeksforgeeks"; std::memset( str, ''t'', sizeof( str ) - 1 ); std::cout << str << ''/n''; }

O de la siguiente manera

#include <iostream> #include <cstring> int main() { char str[] = "geeksforgeeks"; std::memset( str, ''t'', std::strlen( str ) ); std::cout << str << ''/n''; }

Eso es mantener el cero de terminación sin cambios en la matriz.

Si desea anular todos los caracteres de la matriz, incluido el cero de terminación, debe sustituir esta declaración.

std::cout << str << ''/n'';

por esta declaración

std::cout.write( str, sizeof( str ) ) << ''/n'';

como se muestra en el siguiente programa porque la matriz ahora no contiene una cadena.

#include <iostream> #include <cstring> int main() { char str[] = "geeksforgeeks"; std::memset( str, ''t'', sizeof( str ) ); std::cout.write( str, sizeof( str ) ) << ''/n''; }

En cuanto a esta llamada

memset(str, "t", sizeof(str));

entonces el tipo del segundo argumento (que es el tipo const char * ) no corresponde al tipo del segundo parámetro de función que tiene el tipo int . Ver la declaración de la función.

void * memset ( void * ptr, int value, size_t num );

Así el compilador emite un mensaje de error.

Además de los arrays de caracteres (que se usan muy a menudo incluso en C ++), también puede usar la clase estándar std::string (o std::basic_string ) que simula cadenas.

En este caso, no es necesario utilizar el memset de la función C estándar para rellenar una cadena con un solo carácter. La forma más sencilla de hacer esto es la siguiente

#include <iostream> #include <string> int main() { std::string s( "geeksforgeeks" ); s.assign( s.length(), ''t'' ); std::cout << s << ''/n''; }

Otra forma es usar el algoritmo estándar std::fill o std::fill_n declarado en el encabezado <algorithm> . Por ejemplo

#include <iostream> #include <string> #include <iterator> #include <algorithm> int main() { std::string s( "geeksforgeeks" ); std::fill( std::begin( s ), std::end( s ), ''t'' ); std::cout << s << ''/n''; }

o

#include <iostream> #include <string> #include <iterator> #include <algorithm> int main() { std::string s( "geeksforgeeks" ); std::fill_n( std::begin( s ), s.length(), ''t'' ); std::cout << s << ''/n''; }

Incluso puede usar el método de replace de la clase std::string una de las siguientes maneras

#include <iostream> #include <string> int main() { std::string s( "geeksforgeeks" ); s.replace( 0, s.length(), s.length(), ''t'' ); std::cout << s << ''/n''; }

O

#include <iostream> #include <string> int main() { std::string s( "geeksforgeeks" ); s.replace( std::begin( s ), std::end( s ), s.length(), ''t'' ); std::cout << s << ''/n''; }


Esta es la sintaxis correcta para memset ...

void* memset( void* dest, int ch, std::size_t count );

Convierte el valor ch en caracteres sin signo y lo copia en cada uno de los primeros caracteres de conteo del objeto al que apunta dest. Si el objeto es un subobjeto potencialmente superpuesto o no es TriviallyCopyable (por ejemplo, escalar, estructura compatible con C, o una matriz de tipo trivialmente copiable), el comportamiento no está definido. Si el recuento es mayor que el tamaño del objeto al que apunta dest, el comportamiento no está definido.

( source )

Para la primera sintaxis memset(str, ''t'', sizeof(str)); . El compilador se quejó por el tamaño extra. Imprime 18 veces tttttttttttttt!R@ . Sugiero probar con sizeof(str) -1 para la matriz char.

Para la segunda sintaxis memset(str, "t", sizeof(str)); Usted está proporcionando el segundo parámetro es una cadena. Esta es la razón por la que el compilador se queja de error: conversión no válida de ''const char *'' a ''int''


Vlad ha respondido amablemente la primera parte de su pregunta, pero creo que la segunda parte podría explicarse un poco más intuitivamente:

Como han mencionado otros, ''t'' es un carácter mientras que "t" es una cadena , y las cadenas tienen un terminador nulo al final. Esto hace que "t" una matriz de no uno sino dos caracteres: [''t'', ''/0''] ! Esto hace que el error de memset sea más intuitivo: puede forzar un solo char a un int fácilmente, pero se ahoga cuando se le da una serie de caracteres. Al igual que en Python, int([''t'', ''/0'']) (o ord([''t'', ''/0'']) ) no computa.