vectores resueltos punteros practica matrices ejercicios ejemplo dev arreglos apuntadores c++ pointers segmentation-fault readonly

practica - punteros en c++ ejercicios resueltos pdf



¿Por qué no puedo asignar valores a los punteros? (6)

Después de leer las preguntas frecuentes y todo lo demás que puedo encontrar, todavía estoy confundido. Si tengo un puntero de char que se inicializa de esta manera:

char *s = "Hello world!"

La cadena está en la memoria de solo lectura y no puedo cambiarla así:

*s = ''W'';

para hacer "Wello world!". Esto lo entiendo, pero no puedo, por mi vida, entender cómo hacerlo NO de solo lectura. ¿Tengo que usar una matriz en lugar de un puntero? Como aquí ?

Este es mi código:

char *s = str; char *e = s; while (*e != ''/0'') e++; e--; char *temp; //Swop the string around while (s <= e) { *temp = *s; *s = *e; *e = *temp; e--; s++; }

El mensaje de error es solo un error de segmentación. Disculpas de antemano si esta es una pregunta realmente estúpida.

Muchas gracias por toda la ayuda. Después de tomar todos sus consejos, entiendo esto:

void something(char * str) { char *store = str; char *s = new char[strlen(str) + 1]; //Allocate memory. Nice one. strcpy(s, str); char *e = new char[strlen(str) + 1]; strcpy(e, str); while (*e != ''/0'') e++; e--; char temp; //no longer a pointer while (s <= e) { cout << *e; temp = *s; *s = *e; *e = temp; e--; s++; } delete [] e; delete [] s; }

sin embargo, las eliminaciones al final de la función parecen estar causando sus propias fallas de segmentación. ¿Por qué?

Por interés: las fallas se debieron al acceso a los punteros eys después de que se incrementaron. Una solución mucho más simple siguió de eso:

void something(char * str) { char *s = new char[strlen(str) + 1]; strcpy(s, str); char temp; int j = strlen(str) - 1; for (int i = 0; i <= strlen(str)/2; i++) { cout << s << endl; temp = s[i]; s[i] = s[j]; s[j] = temp; j--; } delete [] s; }


Técnicamente, lo que tienes está escrito más correctamente así:

const char *s = "Hello world!"

Lo que realmente quieres es algo como eso:

char s[] = "Hello world!"

Seguir algunas líneas puede ayudarlo a comprender más:

const char *p = "Hello World"; char q[] = "Hello World"; printf("%d %d", sizeof(p), sizeof(q)); // p[0] = ''W'' // INVALID q[0] = ''W''; // valid


El puntero no es de solo lectura. (los datos de cadena sí lo son, pero un puntero que apunta a él se puede modificar libremente) Sin embargo, asignar un carácter a un puntero no hace lo que espera.

En general, lo único que puede asignar a un punto es una dirección. No puede asignar valores, solo la dirección de valores.

Los literales de cadena (como "hello world") son la única excepción, porque las cadenas son especiales. Si asigna uno de esos a un puntero, obtiene un puntero a esa cadena. Pero, en general, asigna direcciones a punteros.

El otro punto es que los caracteres en C ++ son tipos de datos integrales. Se pueden tratar como enteros sin necesidad de conversión. Puedo hacer int i = ''W'' y el compilador no se quejará.

Entonces, ¿qué sucede si asigna ''W'' a un puntero? Toma ''W'' como un valor entero, y asume que esta es una dirección. ''W'' tiene el valor ASCII 127, por lo que está configurando efectivamente su puntero para apuntar a la dirección 127, lo cual no tiene sentido.

Aunque no veo cómo eso tiene mucho que ver con tu código. El problema parece ser que la temp no apunta a datos válidos. Usted declara un puntero, que apunta a una dirección indefinida. Y luego dices "donde sea que apunte, quiero escribir el valor que s señala. Lo siguiente debería funcionar algo mejor:

char temp; // not a pointer. We want a character to store our temporary value in while (s <= e) { temp = *s; // note, no * on temp. *s = *e; *e = temp; // note, no * on temp. e--; s++; }

Sin embargo, si str apunta a un literal de cadena, como "hello world", entonces esto no será legal, porque los datos de cadena en sí son de solo lectura. El compilador puede no hacer cumplir, pero luego te has aventurado en tierras de comportamiento indefinido. Si desea modificar la cadena, cópiela en un búfer local, como mostró una de las otras respuestas.

Parece un poco confundido acerca de la semántica de los punteros. Asignar una dirección (o algo que se puede convertir a una dirección, como un entero) a un puntero hace que el puntero apunte a esa dirección. No modifica los datos apuntados. Declarar un puntero no significa que señalará algo significativo. Si quiere almacenar un char, declare una variable char. Un puntero no almacena datos, solo apunta a datos asignados en otro lugar.

edita comentarios y correcciones a tu código actualizado:

void something(const char * str) { // let the function take a pointer to a non-modifiable string, so add the const. Now it''s clear that we''re not allowed to modify the string itself, so we have to make a copy. char *s = new char[strlen(str) + 1]; // Since the original string is const, we have to allocate a copy if we want to modify it - in C, you''d use malloc(strlen(str)) instead strcpy(s, str); char *e = s; // make e point to the start of the copied string (don''t allocate two copies, since e and s are supposed to work on the same string while (*e != ''/0'') { // add braces so it''s clear where the loop starts and ends. e++; } e--; while (s <= e) { // the loop condition wouldn''t work if s and e pointed to separate copies of the string cout << *e; // why? I thought you just wanted to reverse the string in memory. Alternatively, if you just want to print out the string reversed, you don''t need to do most of the rest of the loop body. In C, you''d use printf instead of *e char temp = *s; // might as well declare the temp variable when you need it, and not before *s = *e; *e = temp; e--; s++; } }

Solo como referencia, y en respuesta a los comentarios sobre C vs C ++, así es como escribiría una función para invertir una cadena en C ++:

std::string revert_string(const std::string& str) { return std::string(str.rbegin(), str.rend()); }

O para revertir la cadena en el lugar:

std::string revert_string(const std::string& str) { std::reverse(str.begin(), str.end()); }


La forma más fácil de modificarlo es crear una matriz para su almacenamiento y luego copiar la cadena en ella.

Por ejemplo:

char buf[128]; const char *src = "Hello World"; strncpy(buf, src, 127); // one less - we always 0-terminate buf[127] = ''/0''; // you can now modify buf buf[0] = ''W'';

La razón por la que su código no funciona es porque no ha asignado ninguna memoria para la copia de la cadena; acaba de hacer un segundo puntero a la misma memoria de solo lectura. (¿Y luego intenté copiarlo? No estoy muy seguro de lo que está haciendo el resto del código). Necesita obtener algo de memoria que no sea de solo lectura en alguna parte, y es mucho más fácil usar la biblioteca estándar para copiarla en esa nueva memoria, en lugar de escribir el loop tú mismo.

En el caso de que no sepas la longitud de la cadena de antemano, también puedes usar malloc (o, mejor aún, hacer lo que dice la respuesta de drschnz y usar la nueva char [] ):

const char *src = "Hello world"; char *buf = malloc(strlen(src) + 1); // or = new char[strlen(src) + 1]; strcpy(buf, src); // you can now modify buf // later, you need to free it free(buf); // or delete [] buf;

Además, si está usando C ++, puede simplemente usar std :: string:

std::string myString("Hello world"); myString[0] = "W";

Espero que ayude.


No hay una función "strdup ()" para hacer una copia de una cadena ... se asegura de que no olvides el "+1" en tu malloc.

char* source = "Hello World"; char* dest = strdup(source);


Tratar:

char src[] = "Hello world"; src[6] = ''W''; -- // or char buffer[] = "Hello world"; char* src = buffer; src[6] = ''W'';

Si desea copiar una cadena en un búfer, utilice strcpy () o strncpy ()

char buffer[20]; char const* s = "Hello World" strcpy(s,buffer);

Si debe escribir su propia copia de cadena, debería verse así:

char buffer[20]; char const* s = "Hello World"; // OK this is not the perfect solution but it is easy to read. for(int loop = 0;s[loop] != ''/0'';++loop) { buffer[loop] = s[loop]; } buffer[loop] = ''/0'';


Tus eliminaciones generan fallas, porque cambiaste el puntero. Debería guardar la ubicación original de la nueva y eliminarla []. Intenta eliminar una ubicación que no está en la tabla de asignación. Si desea cambiar el valor del puntero, cree otro char * temp = t; y úsala para iterar sobre la cadena.