Título: [Duda C#]Suma y Resta en un String Publicado por: Reent en 26 Febrero 2020, 11:48 am Hola a todos!
Quiero hacer una suma y resta en un solo string. Solo que la idea que tengo por el momento solo me deja hacer una de las 2 cosas... Código
ejemplo: "10+20-13+10" char[] numPos {10,20,10}; char[] numNeg {13}; Si alguien tiene alguna idea, me vendria bien una mano. Saludos! [MOD] Usar la etiqueta GeSHi adecuada. Título: Re: [Duda C#]Suma y Resta en un String Publicado por: ThunderCls en 26 Febrero 2020, 18:26 pm En estos casos las expresiones regulares son tus aliadas
Código En el grupo "positivos" tendrias los numeros positivos y en el grupo "negativos" los negativos Suerte Título: Re: [Duda C#]Suma y Resta en un String Publicado por: Reent en 27 Febrero 2020, 14:26 pm Gracias al mod!! no sabia que esa funcion existia.
@Thunder tu idea la entendi pero tu codigo no. Título: Re: [Duda C#]Suma y Resta en un String Publicado por: ThunderCls en 27 Febrero 2020, 14:41 pm tu idea la entendi pero tu codigo no. Solo te he pasado la expresion regular que debes usar, todo lo que tienes que hacer es usarla en tu lenguaje https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=netframework-4.8 Título: Re: [Duda C#]Suma y Resta en un String Publicado por: EdePC en 27 Febrero 2020, 22:36 pm - Wow, me he hecho líos para realizarlo usando RegEx y Split, en mis libros de Visual Basic .NET no hay nada de Expresiones Regulares, he tenido que echar mano de mis libros de C# donde se toca el tema en detalle. De momento solo tengo Visual Basic .NET 2005 y lo he implementado así:
Código
- He usado una RegEx más corta, me parece que le basta ..., luego voy concatenando una String para los positivos y otra para los negativos, unidas mediante una "coma", al final se usa esa misma coma para hacerle un Split quitando las vacias. - Tengo entendido que pasarlo a C# es bastante sencillo, haber si me llega a descargar el C# 2005 para mañana y pasarlo si es que aún hay dudas. Título: Re: [Duda C#]Suma y Resta en un String Publicado por: **Aincrad** en 27 Febrero 2020, 23:00 pm - Tengo entendido que pasarlo a C# es bastante sencillo, haber si me llega a descargar el C# 2005 para mañana y pasarlo si es que aún hay dudas. Siempre puedes usar el conversor de Telerik Code Converter (http://converter.telerik.com/) Nunca falla, yo mismo he pasado codigos de C# a vb . y funcionan correctamente. Codigo Convertido : Código
Título: Re: [Duda C#]Suma y Resta en un String Publicado por: ThunderCls en 28 Febrero 2020, 00:29 am - He usado una RegEx más corta, me parece que le basta ..., luego voy concatenando una String para los positivos y otra para los negativos, unidas mediante una "coma", al final se usa esa misma coma para hacerle un Split quitando las vacias. Tienes razon, la expresion se puede simplificar. Algun motivo por el que no usas un List/ArrayList directamente? En mi opinion la concatenacion/split de cadenas estaria de mas. Código
Saludos Edit: Supongo que seria mas util devolver la cantidad de matches en lugar de un bool :silbar: Título: Re: [Duda C#]Suma y Resta en un String Publicado por: Serapis en 28 Febrero 2020, 01:31 am Es mucho más potente (y sobre todo cómodo cuando la gente no domina las expresiones regulares), realizar un automáta que haga justo la parte que se precisa...
Podremos reconocer algo tan complejo como: " 22 -134 +45 - 087 +170 voy a beber +44j82k" cuya salida sería: 22 -134 +45 -87 +170 +44 +82 = lo que sume " + 232"= 232 "+23" = 23 "23 " = 23 " 23" = 23 " 2323tf" = 2323 " ++++23" = 23 " +-+-+23" = 23 " +-+-23" = -23 " --- 23ffhj"= -23 " 23.34" = +23 +34 (OJO: no se ha contemplado reconocer decimales, ni con punto ni con coma). ...etc... con negativos... ...cosa que para una expresión regular sería más complejo, dada una falta de uniformidad en el texto... Nótese que si hay números en el ejemplo que no debieran ser reconocidos, debe ser expresado en las reglas más abajo de la forma conveniente... Como es un ejemplo, no voy a abordarlo en profundidad, lo dejo simple pero que se entienda y el interesado que lo amplíe a sus necesidades. Es decir, no considero 3 casos: decimales ni separadores de miles, tampoco otras bases numéricas que la decimal, una vez entendido el ejemplo, no debería resultar complicado al interesado ampliarlo para admitir tales casos. Las reglas para número son (uno debe ternerlas claro y hacer los cambos precisos): regla "=" componentes // comentario -------------------------------------------- entero = [signo] [spcs] digitos // el signo es opcional y puede haber o no espacios entre el signo y los digitos signo = (positivo|negativo) positivo = "+" // en ausencia de '-' se entenderá que es positivo. negativo = "-" spcs = espacio [spcs] // uno o más espacios espacio = " " digitos = digito [digitos] // uno o más dígitos digito = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" // los digitos decimales, aunque si fuera preciso podrían separararse por bases numéricas, y reconocer números hexadecimales, binarios, octal, etc... * Como es un ejemplo, no contemplo números con signo (en el pseudocódigo, aquí sería modificar numero y reconocer el caracter separador del decimal. Se ha elegido como separador decimal, la comilla simple como usamos en español (cambiese al gusto). numero = [signo][spcs] digitos ["'" digitos] // un número es un entero o un decimal. * Tampoco contemplo separadores de miles, con las mismas consideraciones que para decimales, se ha elgido el punto como se acostumbra a usar en español: entero = [signo][spcs] gruposDig gruposDig = primeGrpDig [gruposDigitos] primeGrpDig = digito [[digito] digito] //esto es 1, 2 ó 3 digitos gruposDigitos = grupoDigitos [gruposDigitos] // uno o más grupos de 3 digitos grupoDigitos = ["."] digito digito digito // 3 digitos antecedidos o no, por un punto. El peudocodigo pués empieza por una enumeración y luego un array que contenga a dicha enumeración. Código: enumeracion TokenDeNumero //tipo byte Ahora las funciones de reconocimeinto del número: Código: // Si devuelve true, valor contiene un número en caso contrario, se debe ignorar y finalmente la función que interesada en ello: Código: entero = funcion ParseStringToSumasYRestas(arrayBytes Data() ) Esto siempre será más veloz que una expresión regular, además recoge, casos muy distintos de lo que se considera números, que contemplarlos en una expresión regular complicacría y por tanto ralentizaría su resultado. Claro que usarlo o no, depende de si es muy necesario o no, a veces un código menos eficiente (sin llegar a ser deficiente), expresado en 4 líeas e spreferible a otro más eficiente exresado en 200 líneas: " + 232"=232 "+23" = 23 "23 " = 23 " 23" = 23 " 2323tf" = 2323 " ++++23" = 23 " +-+-+23" = 23 " +-+-23" = -23 " --- 23ffhj"= -23 " 23.34" = +23 +34 (OJO: no se ha contemplado reconocer decimales, ni con punto ni con coma). ...etc... con negativos... Por último, notar que en el pseudocódigo tampoco se ha contemplado la posibiidad de desbordamiento, evidentemente un número declarado de tipo entero, dará desbordamiento si se intenta parsear con "987654321987654321987654321". Se supone que son valores coherentes 'sumables', en un rango fijado a ser aceptado en el tipo de datos numérico apropiado. Si fuera el caso, podría llevarse una cuenta de los dígitos que se van hallando y cuando se alcance uno más de lo permitido devolver un error... si se contempla posibles errore,s la funció debería llamarse TryParse... y no Parse... p.d.: Añado nota, para despistados: "// ojo: si el valor es 0... dejo a tu esfuerzo resolver el caso." Título: Re: [Duda C#]Suma y Resta en un String Publicado por: **Aincrad** en 28 Febrero 2020, 01:51 am @NEBIRE eres el dios del Pseudocodigo ? :v
Título: Re: [Duda C#]Suma y Resta en un String Publicado por: Serapis en 28 Febrero 2020, 14:53 pm Bueno, lo hice del tirón y con prisas pués tenía sueño.
Ahora despejado del cansancio y con más calma veo que se me han escapado algunos detalles... saco un tiempo y lo corrijo. pongo corregido como cita, para colorear donde haya cambios (las tiquetas code, no dejan, y (razonablemente) no hay geshi para pseudocodigo. Citar // Si devuelve true, valor contiene un número en caso contrario, se debe ignorar Buleano = Funcion SiguienteToken(arraybytes Data(), porreferencia entero Indice, porreferencia entero Valor) TokenDeNumero tkn buleano negativo // false de entrada Si SaltarEspaciosEIgnorarDesconocidos(data, indice) = FALSE devolver FALSE tkn = CharsToken(data(indice)) si (tkn AND TOKEN_SIGNO) luego // <--- este condicional debía ir por encima del bucle Hacer negativo = (tkn = TOKEN_SIGNO_NEG) //true si el signo es negativo indice += 1 Si SaltarEspacios(data, indice) = FALSE devolver FALSE tkn = CharsToken(data(indice)) si (tkn = TOKEN_DIGITO) salir del bucle sino negativo = FALSE // se invalida el resultado previo, hay caracteres desconodicos tras el signo que se encontró. Si SaltarEspaciosEIgnorarDesconocidos(data, indice) = FALSE devolver FALSE tkn = CharsToken(data(indice)) // <----linea olvidada fin si repetir mientras ( tkn <> TOKEN_DIGITO) // <---- la condición de reentrada va mejor abajo // visto que al inicio entra si signo, y repite hasta encontrar un dígito, es básicamente lo mismo pero queda más claro así fin si // proveo la solución a los dígitos '0' a la derecha (simplemente se filtran antes): Hacer mientras (data(indice) = 48) // 48 es el valor ASCII del cero. indice += 1 si (indice = Data.Length) devolver FALSE repetir Si (CharsToken(data(indice)) = TOKEN_DIGITO) // tras los ceros, podría haber caracteres no dígitos, se resolverá en otra llamada Hacer indice += 1 valor *= 10 + (data(indice) - 48) // <---- Faltaba el -48, tratamos con valores ASCII... si (indice = Data.Length) Salir del bucle repetir mientras (CharsToken(data(indice)) = TOKEN_DIGITO) // <--- faltaba el CharsToken(...) para obtener el tipo de token, si no evaluabamos un byte... // si no es negativo, se asume que es positivo. si (negativo = TRUE) valor = - valor // <--- este condicional es preferible bajo el bucle de digitos, // (para no complicar la simplicidad del bucle), si no, daría error con negativos: ejemplo: -87; --> -8 * 10 + 7 = -73; --> -73 es distinto de -87 Devolver TRUE //y valor contiene el valor correcto, si devuelve false, se ignora el valor que contenga... sino Devolver FALSE fin si fin funcion en la siguiente función simplemente sobra una línea: Citar entero = funcion ParseStringToSumasYRestas(arrayBytes Data() ) entero total, valor, indice Hacer mientras SiguienteToken(Data, Indice, valor ) = TRUE total += valor si (indice = Data.Length) salir del bucle // <--- esta línea no sobra, pero podrría omitirse si se recibe info extra de vuelta // el último dígito de un número podría ser también el último del string... repetir Devolver total fin funcion Finalmente indicar que es posible optimizarlo más... si uno se fija bien, podría llegar a haber un chorro de multiplicaciones "*10", tantos como dígitos haya, por cada número... técnicamente solo es necesario una única multiplicación, el resto pueden ser convertidas en sumas. Tiene su tiempito hacer dicha modificación, por lo que lo dejo al esfuerzo de los interesados... |