Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Error al comparar dos char en un If

Estas en el tema de Error al comparar dos char en un If en el foro de C/C++ en Foros del Web. Hola. Me encuentro haciendo un algoritmo que obtiene un string de una variable, crea un arreglo de registros, un registro para cada caracter de la ...
  #1 (permalink)  
Antiguo 16/10/2014, 17:09
 
Fecha de Ingreso: abril-2012
Mensajes: 12
Antigüedad: 12 años
Puntos: 0
Pregunta Error al comparar dos char en un If

Hola. Me encuentro haciendo un algoritmo que obtiene un string de una variable, crea un arreglo de registros, un registro para cada caracter de la tabla ascii extendida, y compara cada caracter del string con su correspondiente en la tabla ascii, aumentando un contador cada vez que hay una coincidencia.
En palabras mas simples, busca cada caracter en al string y cuenta con que frecuencia se repite, guardandolo en el registro del caracter correspondiente.

Me presenta un mensaje de error en la linea en la que comparo el caracter que extraigo del string con el que tengo almacenado en el registro.

Código:
using namespace std;
struct letraalfabeto {
	public:
		char letra;
		int frecuencia;
};

int main(){
	string texto1;
	letraalfabeto alfabeto[224];
	texto1 = "some text asd 123456";
	
	alfabeto[1].letra = ' ';
	alfabeto[1].frecuencia = 0;
	for (int i = 2; i<224; i++){ //Guarda valores ascii en el arreglo de registros
		alfabeto[i].letra = alfabeto[i-1].letra+1;
		alfabeto[i].frecuencia = 0;
	}
	
	for (int i=1; i<texto1.length(); i++){
		for (int j=0; j>texto1.length(); j++){
			if ((char)texto1.substr(i-1,1) == alfabeto[j].letra){
				alfabeto[i].frecuencia=alfabeto[j].frecuencia+1;
			}
		}
	}
	
	return 0;	
}
Este es el error que me presenta.
Código:
28:33 [Error] invalid cast from type 'std::basic_string<char>' to type 'char'

28:33: error: invalid cast from type 'std::basic_string<char>' to type 'char'
    if ((char)texto1.substr(i-1,1) == alfabeto[j].letra){
Pueden ayudarme a solventar este error?
  #2 (permalink)  
Antiguo 16/10/2014, 18:22
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Error al comparar dos char en un If

Por suerte el mensaje de error que muestra el compilador es muy explícito:
Cita:
Iniciado por tyrax Ver Mensaje
28:33: error: invalid cast from type 'std::basic_string<char>' to type 'char'
if ((char)texto1.substr(i-1,1) == alfabeto[j].letra){
El problema es que std::string::substr() devuelve un objeto de tipo std::string, que no se puede "castear" a char.

Resolviendo eso, te vas a encontrar también vas a necesitar revisar la lógica de tu algoritmo.

A modo de ejemplo, y porque puede resultar útil, pongo acá abajo una forma bastante habitual de llevar la cuenta de la cantidad de ocurrencias de elementos en una secuencia. Uso un std::map, que es un "contenedor asociativo" de la biblioteca estándar (http://www.cplusplus.com/reference/map/map/)

Código C++:
Ver original
  1. #include <string>
  2. #include <map>
  3. #include <iostream>
  4.  
  5.  
  6. int main()
  7. {
  8.     std::string texto1;
  9.     texto1 = "some text asd 123456";
  10.  
  11.     std::map<char, int> alfabeto;
  12.  
  13.     for(std::size_t i = 0; i<texto1.length(); ++i)
  14.         alfabeto[texto1[i]]++;
  15.  
  16.     // muestra cómo ha quedado el alfabeto:
  17.     typedef std::map<char, int>::iterator it;
  18.     for(it i=alfabeto.begin(); i!=alfabeto.end(); ++i)
  19.         std::cout << i->first << " --> " << i->second << '\n';
  20.  
  21.     return 0;
  22. }

Lareto :)
  #3 (permalink)  
Antiguo 16/10/2014, 18:44
 
Fecha de Ingreso: abril-2012
Mensajes: 12
Antigüedad: 12 años
Puntos: 0
Respuesta: Error al comparar dos char en un If

Cita:
Iniciado por lareto Ver Mensaje
Por suerte el mensaje de error que muestra el compilador es muy explícito:


El problema es que std::string::substr() devuelve un objeto de tipo std::string, que no se puede "castear" a char.

Resolviendo eso, te vas a encontrar también vas a necesitar revisar la lógica de tu algoritmo.

A modo de ejemplo, y porque puede resultar útil, pongo acá abajo una forma bastante habitual de llevar la cuenta de la cantidad de ocurrencias de elementos en una secuencia. Uso un std::map, que es un "contenedor asociativo" de la biblioteca estándar (http://www.cplusplus.com/reference/map/map/)

Código C++:
Ver original
  1. #include <string>
  2. #include <map>
  3. #include <iostream>
  4.  
  5.  
  6. int main()
  7. {
  8.     std::string texto1;
  9.     texto1 = "some text asd 123456";
  10.  
  11.     std::map<char, int> alfabeto;
  12.  
  13.     for(std::size_t i = 0; i<texto1.length(); ++i)
  14.         alfabeto[texto1[i]]++;
  15.  
  16.     // muestra cómo ha quedado el alfabeto:
  17.     typedef std::map<char, int>::iterator it;
  18.     for(it i=alfabeto.begin(); i!=alfabeto.end(); ++i)
  19.         std::cout << i->first << " --> " << i->second << '\n';
  20.  
  21.     return 0;
  22. }

Lareto :)
Lareto, la solucion que me mostraste funciona de maravilla y en muchas menos lineas de codigo. Estoy intentando entenderla completamente, ya que nunca he trabajado con map ni con std::, no entiendo bien cual es la funcion de ambas. Intentare tomar todo lo que pueda de alli para avanzar en mi codigo.
Sin embargo, de ser posible me gustaria saber como transformar ese std::string a un char simple, ya que solo tengo permitido utilizar estructuras de datos que sean creadas en su totalidad por mi y no estoy seguro de poder utilizar el map.
  #4 (permalink)  
Antiguo 16/10/2014, 19:55
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Error al comparar dos char en un If

Hola;

std:: es el nombre del espacio de nombres (namespace) donde se encuentran los nombres de cout, string, map, ... y todos los otros nombres del espacio de nombres standar. Tú los estás incluyendo a todos al poner using namespace std; que no es que esté mal, sólo que de esa manera vuelcas los miles de nombres del namespace std en la unidad que estás compilando. En general, using namespace std; sólo se usa en ejemplos simples (como este), pero no en la vida real. Como regla general, creo que podría decirse que ese using namespace std; puede ir en un .cpp (aunque no sea recomendable), pero nunca de los jamases en un .h

una std::string es un objeto que representa una secuencia de caracteres (o si pones ese ordinario using namespace std;, podrás poner la palabra string, sin especificar que se trata de la clase string del namespace std, ¿me explico?)

Bien, entonces, creas un objeto de tipo std::string con algo como
std::string texto = "Hola mundo!";

Y la función std::string::substr(); quiere decir que substr() es una función miembro de la clase string que se encuentra en el namespace std. Y esta función devuelve un nuevo objeto de tipo std::string.

Otra función miembro de la clase std::string es su std::string operator[std::size_t pos], que devuelve una referencia al elemento que se encuentra en la posición "pos".

Por ejemplo, si tienes
Código:
std::string texto = "Hola mundo!";
texto[0] es una referencia al primer carácter ('H');
texto[1] es una referencia al segundo carácter ('o');
etcétera.

En lugar de tratar de convertir una std::string (que es lo que devuelve substr()) en un carácter, puedes obtener cada uno de los caracteres de "texto" usando la función miembro
std::string operator[std::size_t pos];

Si no te molesta, yo te recomendaría que primero te asegures de que has entendido qué es una std::string y sus funciones miembro más usuales. Para eso nada mejor que un buen tutorial, o un buen libro introductorio al C++, por ejemplo. Yo perdí, y sigo perdiendo, muchísimo tiempo al saltarme los conceptos básicos dando por supuesto que más adelante los iba a entender en detalle, y por supuesto jamás resultó.

Lareto :)
  #5 (permalink)  
Antiguo 16/10/2014, 22:40
 
Fecha de Ingreso: abril-2012
Mensajes: 12
Antigüedad: 12 años
Puntos: 0
Respuesta: Error al comparar dos char en un If

Muchisimas gracias Lareto! Realmente habia estado buscando lo de std::, pero al parecer es algo tan basico que no se encuentra muy bien explicado en internet. Y tu explicacion fue bastante clara, seguire buscando al respecto para comprenderlo mejor, pero al menos ya entiendo lo que es y por que lo utilizan, y por que no tenia que utilizarlo yo (using namespace std). Tu ayuda ha sido invaluable, creelo.
  #6 (permalink)  
Antiguo 17/10/2014, 00:49
 
Fecha de Ingreso: abril-2012
Mensajes: 12
Antigüedad: 12 años
Puntos: 0
Respuesta: Error al comparar dos char en un If

Oye, Lareto, una ultima pregunta. Disculpa la molestia. En el algoritmo que me proporcionaste, esta clase "map" ordena automaticamente los elementos que le vas asignando de forma alfabetica? Como podria ser para que queden ordenados en cuanto a la frecuencia con que se repiten?
  #7 (permalink)  
Antiguo 17/10/2014, 13:50
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Error al comparar dos char en un If

Hola, y no es molestia, claro.

Te muestro una posible solución, relativamente común, aunque quizá no demasiada apta para principiantes, pero hagamos un esfuerzo:

Va el código y después trato de explicarlo
Código C++:
Ver original
  1. #include <string>
  2. #include <map>
  3. #include <set>
  4. #include <functional>  // para std::greater
  5. #include <iostream>
  6.  
  7. // muestra el contenido del alfabeto ordenado por frecuencias, de mayor a menor
  8. void muestra_alfabeto(const std::map<char, int>& alfabeto)
  9. {
  10.     std::set<std::pair<int, char>, std::greater<std::pair<int, char> > > frecuencias;
  11.  
  12.     typedef std::map<char, int>::const_iterator it;
  13.     for(it i=alfabeto.begin(); i!=alfabeto.end(); ++i)
  14.     {
  15.         frecuencias.insert(std::make_pair(i->second, i->first) );
  16.     }
  17.  
  18.  
  19.     typedef std::set<std::pair<int, char>, std::greater<std::pair<int, char> > >::iterator sit;
  20.     for(sit i=frecuencias.begin(); i!=frecuencias.end(); ++i)
  21.         std::cout << i->first << " --> " << i->second << '\n';
  22.  
  23. }
  24.  
  25. int main()
  26. {
  27.     std::string texto1;
  28.     texto1 = "some text asd 123456";
  29.  
  30.     std::map<char, int> alfabeto;
  31.  
  32.     for(std::size_t i = 0; i<texto1.length(); ++i)
  33.         alfabeto[texto1[i]]++;
  34.  
  35.     muestra_alfabeto(alfabeto);
  36.     return 0;
  37. }

La idea acá es armar un contenedor nuevo con el contenido del std::map; se necesita porque un map es un array asociativo organizado en pares (key, value) por definición, y ordenado de acuerdo a la "key" (aunque por defecto esas keys se ordenan de menor a mayor, puede indicarse que se ordenen con cualquier otro criterio que se defina, normalmente, en una función objeto -- ¿Qué qué es una función objeto? Bueno, no queda más remedio que estudiar)

Elegí para el ejemplo un std::set que es otro std::map, sólo que con la particularidad de que en él "key" y "value" son la misma cosa.

Invertí el contenido de los pares que se van insertando, ahora no es más <char, int> como en alfabeto, sino <int, char>, para que el primer criterio de ordenación sea la frecuencia y no el carácter. Y acá sí el orden lo establece la función objeto std::greater, para que los pares en el set se mantengan ordenados de mayor a menor.

Otra forma también podría ser ir agregando los apares a un std::vector, y después ordenar el vector con el mismo criterio.

Quizá quedaría mejor si además de mostrar el alfabeto ordenado por frecuencias, se mostraran también ordenado alfabéticamente; para eso, en lugar de usar el objeto greater, habría que escribir una función objeto propia (que te queda como ejercicio).

Lareto :)
  #8 (permalink)  
Antiguo 18/10/2014, 01:04
 
Fecha de Ingreso: abril-2012
Mensajes: 12
Antigüedad: 12 años
Puntos: 0
Respuesta: Error al comparar dos char en un If

Excelente Lareto! Disculpa la respuesta tardia, llevo horas y horas programando, tengo un gran dolor de cabeza y estoy cansado. Intentare implementar tu solucion al ordenamiento del map. Muchas gracias por tu ayuda, has sido super atento, y realmente he avanzado muchisimo gracias a ti.

Etiquetas: c++, char, comparacion, registros
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:31.