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.