cadenas en c/c++

Iniciado por Beginner Web, 19 Junio 2019, 00:19 AM

0 Miembros y 1 Visitante están viendo este tema.

Beginner Web

buenas chicos, tengo un problema al usar ciertas funciones como gets(); y cin.getline();
En este pasa que guarda mas de lo que debe
Código (cpp) [Seleccionar]
// Example program
#include <iostream>
#include <string.h>
#include <conio.h>
using namespace std;
int main()
{
  char cadena[10], cadena2[10];
  cout<<"Ingrese primer cadena: ";
  gets(cadena);
  cout<<"Ingrese segunda cadena: ";
  gets(cadena2);
  cout<<cadena<<endl;
  cout<<cadena2<<endl;
}


y en este solo sirve si uso una sola cadena en el rograma ero si dos y en la primera coloco mas de 10 caracteres la segunda guarda el enter y no me deja hacer mas bueno prueben los codigos no me se exlicar  :huh:

Código (cpp) [Seleccionar]
// Example program
#include <iostream>
#include <string.h>
#include <conio.h>
using namespace std;
int main()
{
  char cadena[10], cadena2[10];
  cout<<"Ingrese primer cadena: ";
  cin.getline(cadena,10,'\n');
  cout<<"Ingrese segunda cadena: ";
  cin.getline(cadena2,10,'\n');
  cout<<cadena<<endl;
  cout<<cadena2<<endl;
}


lo que quiero es ingresar mas de 10 caracteres y me tome solo 10 y me deje hacer lo mismo con  la segunda cadena colocar mas de 10 caracteres y me muestre por pantalla las dos cadenas con hasta 10 caracteres es decir 9 caracteres y el salto de linea  ;-)
7w7

@XSStringManolo

#1
Si te da igual el gasto de recursos yo haría así:
Código (cpp) [Seleccionar]
#include <iostream>
#include <string>
using namespace std;
int main()
{
 string cadena, cadena2, cadena3, cadena4;
 cout<<"Ingrese primer cadena: ";
 getline(cin, cadena);
 cout<<"Ingrese segunda cadena: ";
 getline(cin, cadena2);
cadena3.append(cadena, 0, 10);
cadena4.append(cadena2, 0, 10);
 cout<<cadena3<<endl;
 cout<<cadena4<<endl;

cin.get() //pausa
return 0;
}

/*Si le quieres meter saltos de linea usas otro append o un +=
cadena3.append("\n");
cadena4 += "\n";

Cumple exactamente lo que pides.
Puedes meter las variables en una función y te las cargas cuando la funcion se termina, ya sea haciendo el propio cout desde la funcion, o metiendo la llamada a la funcion en el propio cout.

Código (cpp) [Seleccionar]
void obtenerFrase();

int main()
{
obtenerFrase();

cin.get()
return 0;
}

obtenerFrases()
{
string a, b, c, d;
cout << "blablabla" <<endl;
getline(cin, a);
cout << "blablabla" << endl;
getline(cin,b);
c.append(a, 0, 10);
d.append(b, 0, 10);
cout << "blabla : " << a <<endl <<"blabla" << b<<endl;
}



Con el método append(); añades a un string el contenido de otro string.
El primer parámetro es un string, el segundo la posición a partir de la cual se van a emlezar a obtener letras. el tercer parámetro es cuantas letras vas a obtener a partir de la posición anterior.

Tienes otros métodos como:
.size() que te devuelve el tamaño del string
.length() hace lo mismo.
.max_size() te dice el número máximo de caracteres que puede tener tu string
.resize(numero, caracter) acorta o alarga. El primer argumento es el tamaño que tendrá el string, ek segundo argumento se aplica si alargas el string llenando de ese caracter el string hasta llegar al tamaño indicado. Ejemplo: mivariable.resize(50, '\0'); para llenar de espacios. Puedes usar variables como argumentos: int miInt = 50; char miChar='1'; mivariable.resize(miInt, miChar);
.capacity() te devuelve el el núneronde memoria destinada para el string.
.reserve(numero) aumenta el tamaño de memoria destinada como minimo al valor que le demos como parametro.
.shrink_to_fit() reduce la memoria destinada al valor mínimo posible sin perder contenido en el string.
.clear() borra lo que hay en el string y le pone el size() a 0. No necesariamente reduce la memoria destinada.
.empty() retorna true si el tamaño es igual a 0. Ejemplo:

while (miString.empty())
//toma valores hasta que al string se le meta algun valor.


A parte de esto, si estas trabajando con strings de C tambien puedes hacerles .append() para meterlos dentro de un string de C++:
a.append(stringDeC*);
Podrías hacer aritmética de punteros de forma manual para usarlo igual que use .append en el ejemplo:
a.append( (stringDeC*+5), 15);
Esto último no tengo comprobado que funcione, pero en teoría debería sumar a la direccion de memoria  apuntada por el puntero el numero 5 multiplicado por el tamaño en bytes del tipo de dato al que se apunta. En este caso sería un char que ocupa un byte * 5 que es el numero que sumamos.
En caso de ser un array de ints, se multiplicaría 4 bytes que ocupa el tipo int * 5 que es número puesto y se sumarían 20 bytes para encontrar el 4 elemento del array.

El tipo string de C es un array de chars que usa punteros y direcciones memorias contiguas + aritmética de punteros para saber donde están.

A medida que avances lo vas comprendiendo mejor.

Pd: Puedes usar string de C nativamente como tipo en C++ sin usar <string.h>
char* stringDeC = "El contendio";
cout << strlen(StringDeC) << endl;

Y usar bucles for para hacer lo que quieras:
for (int i = 0; i <strlen(StringDeC); ++i)
{
   if ( i == 7 )
   {
    StringDeC = '8';
    }
cout << StringDeC << endl;
}

Recuerda que los string empiezan en
  • no en [1] y que al final llevan el null terminator \0 que indica el fin del string.
    También puedes trabajar directamente con punteros:
    StringDeC*  es lo mismo que StringDeC[0]
    Y (StringDeC* +5) es lo mismo que StringDeC[4]

    Mírate el tema de los arrays y punteros.

RayR

No uses gets. Es una función insegura y oficialmente ya ni siquiera es parte del lenguaje, aunque los compiladores aún permitan usarla.

Pasando al otro código, no es que el segundo cin.getline almacene el Enter, sino que cuando introduces una cadena mayor a la especificada, cin queda en un estado de error, y no va a funcionar mientras no lo arregles. Por ejemplo, si aquí:

Código (cpp) [Seleccionar]
cin.getline(cadena,10,'\n');
introduces 10 caracteres o más, ocurre error, y cualquier intento de leer datos con cin (cin.getline(), cin >> variable, etc.) va a fallar, es decir, se saltará a la siguiente instrucción. La solución es que pongas esto inmediatamente después de cin.getline:

Código (cpp) [Seleccionar]
// Si el getline fallo:
if (cin.fail()) {
    // "Arreglar" cin
    cin.clear();
    // Opcional: descartar caracteres restantes en buffer. Incluir <limits>
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}


La última línea es por si quieres que el segundo cin.getline lea una cadena nueva. La función ignore lee y descarta caracteres hasta que haya leído la cantidad especificada en su primer parámetro, o hasta encontrar el caracter de su segundo parámetro. Es decir, esto:

Código (cpp) [Seleccionar]
    cin.ignore(20, '\n');

leería y descartaría del buffer hasta 20 caracteres o hasta encontrar una nueva línea, lo que suceda primero. El primer parámetro que yo usé en el ejemplo de arriba representa el tamaño máximo de un buffer de entrada/salida. Básicamente es decirle a ignore que limpie todo el buffer (por más grande que sea) hasta encontrar el´\n'.

Eso sí, sería mejor que usaras la clase string, como lo hizo string Manolo, en cuyo caso usarías la función global getline, que funciona un poco distinto a cin.getline, y en este caso específico lo  del estado de error no aplicaría como lo puse.

Beginner Web

lo se RayR por eso pregunto, al rato lo pruebo  ;-)
7w7

codX

Beginner, la solución está en usar memoria dinámica