[TUTORIAL] Programando en C

14, 5, 6, 7, 8, 9
el_itineranT escribió:
xXDraklordXx escribió:Prefiero empezar por aquí para tener claro como hacer el resto ya que si luego encuentro una forma mejor de pasar los argumentos tendría que volver a escribir todo lo que llevase hecho


Lo de ingenieria del software va por aqui, si tienes que volver a esribir codigo para hacer modificaciones, eso se considera un error de diseño, su escalabilidad es nula, y eso tambien es un error de programacion.Yo procuraria hacer muchos metodos que realicen las acciones simples, y el modulo principal, solo hace las llamadas a los metodos(estos metodos a su vez tienen que tener otros metodos), de manera que añadir funcionalidades nuevas o modificaciones no tengas que empezar de nuevo el codigo.

decir, que soy estudiante de ing.informatica (en curso) y que puedo estar metiendo la pata hasta el fondo, si me equivoco agradezco a qualquiera que me corrija.


Eso mismo he hecho. Lo primero que quería dejar claro con mi código es la manera en la que el usuario llamará a las funciones para que sea la mas sencilla de cara al usuario y la mas eficiente de cara al código. Empecé por implementar a la función principal un "identificador" del comando introducido que a su vez, una vez identificado, llame a la función correspondiente, para hacerlo de una manera metódica, es decir, siempre igual para todas las funciones y con el resultado que cada función por separado deba dar. No pongo este código porque no está escrito integramente en C, sino que usa parte de código en Objective-C y no es bueno liar al personal xD.
Wow me voy unos días y la que me liáis xdd nah, es coña =P
Me he leído todas vuestras respuestas y tengoun par de aportaciones.

1. a la pregunta de: Como hacer una array del tamaño exacto de la "orden introducida en consola":
Hasta donde yo se no existe ninguna solución fácil ha esto que propones, pues existe la función gets() que obtiene el texto en pantalla, pero el buffer ya debe estar declarado previamente. Posible solución (no probada, esta improvisado así que no se hasta que punto es útil)
char *commandBuffer = (char*)malloc(8096);
/*declaramos un buffer suficientemente grande como para obtener un comando largo *

gets(commandBuffer); // Obtenemos orden consola

char *subBuffer = (char*)malloc(strlen(commandBuffer));
/* Creamos un 2o buffer del tamaño de la orden (que no es el mismo que el del 1r buffer) */

strcpy(subBuffer, commandBuffer);
//strcpy se encuentra en "string.h"
/* Copiamos el contenido del 1r buffer al 2o */

free(commandBuffer); //Liberamos la memoria del primer buffer

Otra idea, puesto que upongo que comprobaras continuamente si el user pone una orden, crearas un loop
char *commandBuffer = (char*)malloc(8096);
/*declaramos un buffer suficientemente grande como para obtener un comando largo */
while(1){ //bucle infinito!!
     gets(commandBuffer);
     //..... Operaciones
     //Ejemplo para salir del loop

     if(strstr(commandBuffer, "quit"))
          break;
     //strstr en "string.h"
     /* si el texto contiene (si contiene, no si es igual a) "quit" sale del loop */

     memset(commandBuffer, 0,  8096);
     /*Ponemos cada 1 de las posiciones de memoria de la array commandBuffer a 0 para prepararlo para el siguiente loop. Solo utilizamos 8096 de memoria, o el tamaño que tu le des */
}


Otras soluciones, pero mucho mas complicadas, y que realmente dudo que valgan la pena, seria el uso de "timers" o de un "thread" y la función "clock()" mas el uso de getkeyascink() (o parecido, no me acuerdo del nombre dela función) para comprobar si se pulsan letras. Pero sinceramente, lo considero una perdida de tiempo y de recursos.

Lo mejor que puedes hacer es quizás una combinación entre los 2 ejemplos anteriores, pero ten presente que en el 1o, el uso de free() implica borrar ese trozo de memoria, así que deberías hacer un malloc de nuevo.

2. A la pregunta: como partir un texto según X carácter
Ejemplo:
char txt[] = "hola cruel mundo";

char *str = strtok(txt, " ");
//strtok en "string.h"
/* Divide la cadena según el carácter (o caracteres) del 2o parámetro. Aquí es el espacio " ".
Nota: NO devuelve una array, sino cada ocurrencia por separado. Continua leyendo el ejemplo */

while(str){
     printf("%s\n", str);

     str = strtok(NULL, " ");
     /* Fijate en el NULL, ya no hemos puesto la "txt". Esto indica que queremos la siguiente ocurrencia de la string previa. Si teníamos la 1, nos da la 2, si era la 2, la 3. Si no hay mas, devuelve NULL, y de aquí el while(str), que es lo mismo que while(str != NULL) */
}
//RESULTADO:
//hola
//cruel
//mundo


3. Nota general:
No se a quien, pero he visto usar la palabra "new". Esta existe SOLO en c++, y aunque un compilador quizás os la acepte, en C debemos hablar de "malloc", no de "new".
No pasa nada, pero a bien clarificar.

@xXDracklordXx
Para la función ls()
Te recomiendo que le eches una ojeada al archivo "dirent.h" y "stat.h" (de hecho es: "sys/stat.h"). El primero sirve para listar directorios y archivos, mientras que el segundo para obtener información de un archivo. En caso de que estés en Windows es mucho mas que probable que no tengas estos 2 archivos. Si te interesan avisa y te los paso encantado.

Ánimos y espero que este tostón sirva de algo =P (mas que nada porque lo he escrito desde un iPod, y no te imaginas la currada mas brutal que esto supone xd)

@el_itineranT
Permitidme un poco de oftopic, sry
Has dicho que hacías eng. Infomatica no? Que tal esta? Me estaba planteando de pillarmela el año que viene para la uni, pero he oído que con el plan Bolonia no ha salido muy bien parada. Me podrías iluminar un poco? Jeje
Gracias!
Gracias por las librerías blipi, me han sido de mucha ayuda. Mi función ls() ya realiza el trabajo de la función normal. Me queda pulirla y meterme con la siguiente, que no sé cual será. Buscaré una facilita para ir tirando y adelantar trabajo. Gracias una vez mas [oki]
blipi escribió:No se a quien, pero he visto usar la palabra "new". Esta existe SOLO en c++, y aunque un compilador quizás os la acepte, en C debemos hablar de "malloc", no de "new".
No pasa nada, pero a bien clarificar.

Sorry blipi, fui yo xD. Es que últimamente estoy más metido en C++ y se me coló que en C no "existe".

Thankz! ;)
jaja tranquilo no pasa nada =P

Acabo de darme cuenta de un error que cometí en el ejemplo 2, en el memset
debería poner:
memset(commandBuffer, 0, 8096); //O el tamaño que le des


Y no
memset(commandBuffer, 0, sizeof(commandBuffer));

Como antes, puesto que sizeof(commandBuffer) = 4, ya que todos los punteros son de tamaño 4.

Ya lo he editado en el ejemplo.


POST DATA:
Tengo un proyecto entre manos, de nombre "Routin3". Viene a ser un "intérprete de C", pero le llamaremos, a partir de ahora, lenguaje para simplificar. Mediante una consola en C interpreta un código de programación muy parecido al Basic pero con retoques para orientarlo hacia C. Su objetivo es facilitar el aprendizaje de la sintaxis básica, arrays y punteros (aunque aun no tiene nada de esto porque lo estoy programando)
Ejemplo:
function main
   var a = 2
   var b = "ool"
   var c = 9.9

   var d="ool"

   var m =              "lo l"
   var n = "\n dod" 

   print m
   print n & m
   print "baaaaaaaaaab" &  " caac " & n
   print 2 & " " & m & "\n" & " " & OMFG
endfunction


No requiere compilar ni nada, un simple archivo TXT (o del formato que tu quieras) conteniendo eso, y un comando: "exec archivo.txt", y se ejecuta tu propio programa.
El tamaño total (de momento) de este intérprete es de 16,0 kb, así que, es perfectamente portable.
No esperéis gran cosa, esta orientado a enseñar, no a ser un lenguaje superpotente, tan siquiera compila binarios.

Por el momento hace:
  • Declara variables (var a = 8) (var b)
  • Guarda valores en variables (a = 10)(b = "aaaa")
  • Detecta funciones (function main ... endfunction)
  • Enseña contenido en consola (print "contenido")(print a)(print a & b -> enseña las 2 variables seguidas)(print a & " " & b)
  • Crea una consola propia para el programa (CreateConsole)
  • Detecta errores (de todo tipo) y muestra la linea donde se encuentra (ejemplo, última linea, no existe la variable OMFG)
Menudos marrones en los que me meto. La función ls()... bueno, me está costando demasiado código con lo cual algo fallará o podría estar mejor. Cuando la termine la pondré. Pero el tema es que no me quiero ni imaginar en las que me quedan por delante, que solo llevo 3 comandos terminados xDDDD. Eso sí, aprender estoy aprendiendo lo mires por donde lo mires. blipi, siento darte por cu** viendo que estás tu tambien con lo tuyo. Eso sí, si la llego a acabar y consigo que funcione para una primera "beta" y la termino subiendo a cydia os mencionaré a todos porque me habéis hecho el trabajo prácticamente jajaja.

Lo dicho, luego pongo el código de ls() a ver si se puede mejorar; si no; si es un desastre... xD

Edit: Se me olvidaba. Parte de el código esta escrito en Objective-C así que no lo posteare. Vere que puedo hacer para mejorarlo por mi mismo [oki]
jajaj tranquilo que no me estás dando por ningún lado =P
Si no tengo internet, solo escasos minutos cuando mis padres me lo dan, por eso no puedo ampliar el tuto. Pero cuando me lo dan, me gusta entrar al hilo y responder las dudas, ver que hay gente como tú que tiene ganas de aprender y de hacer cosas me da más ánimos para continuar.

Respecto al tema Objective-C, porqué motivo lo usas? Personalmente no es un lenguaje que me llame mucho la atención, puesto que antes que usar este me decanto más por C++. Pero bueno, a lo que iba. Postealo de todas formas si quieres, y le echo una ojeada. Aunque la sintaxis sea diferente se entiende bien, así que supongo que te podría ayudar en algo.

Para que iOS lo estás haciendo? Porqué yo estoy ansioso por tener un terminal en iOS 4.x, que la ultima versión se quedo para el 3.x. Ya me contarás =P

Mirate esto, quizás (casi seguro que sí) te sirva. Es parte de mi proyecto:
void listFiles(char *commandBuff){
   /*commandBuff es esto:   
   gets-> ls -a -b
               [-a -b] = commandBuff, son los parámetros

   Usa dirent.h y sys/stat.h
   */
   if(strstr(commandBuff, "-h")){
      printf("\tFuncionamiento:\n");
      printf("\tls ~ Obtener listado de archivos y carpetas\n");
      printf("\tls [-f] ~ Obtener listado de archivos\n");
      printf("\tls [-d] ~ Obtener listado de carpetas\n");
      printf("\tls [-a] ~ Obtener listado detallado\n");
      return;
   }

   DIR *dir;
   struct dirent *ent;
   
   /*fullPath es la ruta a la carpeta*/
   printf("P-\t%s\n\n", fullPath);

   int displayFiles = 0;
   if(strstr(commandBuff, "-f") || commandBuff == NULL)
      displayFiles = 1;

   int displayFolders = 0;
   if(strstr(commandBuff, "-d") || commandBuff == NULL)
      displayFolders = 1;

   int displayDetail = 0;
   if(strstr(commandBuff, "-a") || commandBuff == NULL)
      displayDetail = 1;

   if(displayFiles == 0 && displayFolders == 0)
      displayFiles = displayFolders = 1;

   dir = opendir (fullPath);
   if (dir != NULL){
      while ((ent = readdir (dir)) != NULL){
         struct stat g;
         char filename[2048];
         
         /* Si el último carácter de la ruta no es \ ('\\'), lo añadimos */
         strcpy(filename, fullPath);         
         if(filename[strlen(filename)-1] != '\\')
            strcat(filename, "\\");
         
         /* SISTEMAS UNIX, TERMINACIÓN '/'
         if(filename[strlen(filename)-1] != '/')
            strcat(filename, "/");
         */

         strcat(filename, ent->d_name);

         int displayItem = 0;

         if(stat(filename, &g) >= 0){
            //NOTA: _S_IFDIR = S_IFDIR = DT_DIR -> Depende del OS y del compilador
            //S_ISREG -> Para comprobar archivos, si fuera necesario
            if (_S_IFDIR & g.st_mode){
               if(displayFolders == 1){
                  printf ("D-");
                  displayItem = 1;
               }
            }else{
               if(displayFiles == 1){
                  printf ("F-");
                  displayItem = 1;
               }
            }
         }

         if(displayItem){
            if(displayDetail)
               printf("\t-%d%d", ent->data.nFileSizeHigh, ent->data.nFileSizeLow);
            printf("\t\t%s\n", ent->d_name);
         }

      }
         
      closedir (dir);
   }
}


Suerte y ánimos con el proyecto! Y si lo subes a cydia avisa, que lo probaré!
blipi escribió:jajaj tranquilo que no me estás dando por ningún lado =P
Si no tengo internet, solo escasos minutos cuando mis padres me lo dan, por eso no puedo ampliar el tuto. Pero cuando me lo dan, me gusta entrar al hilo y responder las dudas, ver que hay gente como tú que tiene ganas de aprender y de hacer cosas me da más ánimos para continuar.

Respecto al tema Objective-C, porqué motivo lo usas? Personalmente no es un lenguaje que me llame mucho la atención, puesto que antes que usar este me decanto más por C++. Pero bueno, a lo que iba. Postealo de todas formas si quieres, y le echo una ojeada. Aunque la sintaxis sea diferente se entiende bien, así que supongo que te podría ayudar en algo.

Para que iOS lo estás haciendo? Porqué yo estoy ansioso por tener un terminal en iOS 4.x, que la ultima versión se quedo para el 3.x. Ya me contarás =P

Mirate esto, quizás (casi seguro que sí) te sirva. Es parte de mi proyecto:
void listFiles(char *commandBuff){
   /*commandBuff es esto:   
   gets-> ls -a -b
               [-a -b] = commandBuff, son los parámetros

   Usa dirent.h y sys/stat.h
   */
   if(strstr(commandBuff, "-h")){
      printf("\tFuncionamiento:\n");
      printf("\tls ~ Obtener listado de archivos y carpetas\n");
      printf("\tls [-f] ~ Obtener listado de archivos\n");
      printf("\tls [-d] ~ Obtener listado de carpetas\n");
      printf("\tls [-a] ~ Obtener listado detallado\n");
      return;
   }

   DIR *dir;
   struct dirent *ent;
   
   /*fullPath es la ruta a la carpeta*/
   printf("P-\t%s\n\n", fullPath);

   int displayFiles = 0;
   if(strstr(commandBuff, "-f") || commandBuff == NULL)
      displayFiles = 1;

   int displayFolders = 0;
   if(strstr(commandBuff, "-d") || commandBuff == NULL)
      displayFolders = 1;

   int displayDetail = 0;
   if(strstr(commandBuff, "-a") || commandBuff == NULL)
      displayDetail = 1;

   if(displayFiles == 0 && displayFolders == 0)
      displayFiles = displayFolders = 1;

   dir = opendir (fullPath);
   if (dir != NULL){
      while ((ent = readdir (dir)) != NULL){
         struct stat g;
         char filename[2048];
         
         /* Si el último carácter de la ruta no es \ ('\\'), lo añadimos */
         strcpy(filename, fullPath);         
         if(filename[strlen(filename)-1] != '\\')
            strcat(filename, "\\");
         
         /* SISTEMAS UNIX, TERMINACIÓN '/'
         if(filename[strlen(filename)-1] != '/')
            strcat(filename, "/");
         */

         strcat(filename, ent->d_name);

         int displayItem = 0;

         if(stat(filename, &g) >= 0){
            //NOTA: _S_IFDIR = S_IFDIR = DT_DIR -> Depende del OS y del compilador
            //S_ISREG -> Para comprobar archivos, si fuera necesario
            if (_S_IFDIR & g.st_mode){
               if(displayFolders == 1){
                  printf ("D-");
                  displayItem = 1;
               }
            }else{
               if(displayFiles == 1){
                  printf ("F-");
                  displayItem = 1;
               }
            }
         }

         if(displayItem){
            if(displayDetail)
               printf("\t-%d%d", ent->data.nFileSizeHigh, ent->data.nFileSizeLow);
            printf("\t\t%s\n", ent->d_name);
         }

      }
         
      closedir (dir);
   }
}


Suerte y ánimos con el proyecto! Y si lo subes a cydia avisa, que lo probaré!

Respondiendo a lo primero, uso Objective-C porque tengo más conocimiento de este lenguaje que de C o C++ aunque los uso de apoyo.

Lo segundo. Lo estoy haciendo para iOS 4.2 aunque al estar escrito también en C es y será portable a anteriores y futuros firms si se diera el caso.

Y no te preocupes que sé que entendible es, pero como este hilo no hace referencia a este lenguaje no quería poner un código que no tenga nada que ver con el tema.

Y por tu código. Es básicamente igual que el mío según veo, así que de momento lo dejaré como está ya que funciona bien.

Ahora estoy en otro embrollo y me temo tener que volver a escribirlo. No se como acceder desde un archivo de cabecera a los objetos de una clase creada en Objective-C... [buuuaaaa] Espero encontrar la forma xD.

Edit: Al final he optado por volver a escribirlo todo (suerte que llevaba poco) para ordenarlo y comentar el código para que quede claro y no tenga que volver a hacer esto. Es una costumbre que me cuesta adquirir jeje. Bueno, por suerte solo es "pasar a limpio" así que pronto estará.

Edit 2: Pues ya está. Todo pasado a limpio. Ya puedo seguir con el trabajo. La próxima función: echo() XD. Un descansito que con las que llevo ya estoy bastante saturado. Cuando quieras te la mando para que la pruebes blipi. Aunque no esté terminada es completamente funcional (o eso creo XD).

Edit 3: Me ha surgido un problema un tanto "molesto". Cuando añado texto a una cadena, y reitero, añado, el programa se bloquea durante algunos segundos cuando hay una gran cantidad de texto en el. Por ejemplo: al realizar un strcat(texto_base, texto_a_añadir), cuando ya hay una gran cantidad de texto en texto_base el programa se bloquea unos segundos y luego añade el contenido. Supongo que será por temas de memoria pero no sé como solucionarlo. A ver si me dais alguna idea porque de momento es el fallo mas evidente que le encuentro.

P.D: blipi, yo también quería un terminal para iOS4+ y como no salía o daba fallos me hago uno. ¿No dicen que cuando quieres algo bien hecho tienes que hacerlo tu mismo? Pues veremos a ver que sale xD.
Blipi, pues me he leido y releido lo de los punteros pero ahí me pierdo y no se para que sirven ni en que podría utilizarlo :(
@xXDraklordXx
El problema esta en el strcat() o al hacer printf? Me extraña que strcat de problemas. El tamaño de tu buffer es suficientemente grande como para alojar el texto_base + el texto_añadir? Compruébalo.
Sino, todo lo que se me ocurre es que hagas tu mismo una función:
void custom_strcat(char *in, char* add){
if(!in || !add) return;
in += strlen(in);
while(*add)   *(in++) = *(add++);
*in = '\0';
}

Está bastante comprimida, pero no realiza ninguna operación innecesaria y funciona a la perfección. Mientras el texto_base (in) tenga el tamaño suficiente como para alojar también el tamaño de texto_añadir (add), no debería haber ningún problema, pues esta función simplemente reescribe la memoria.
Prueba liberando memoria también con free() si tienes algún malloc(), y asegúrate de no realizar malloc() innecesarios. Siempre puedes reutilizar un puntero hecho a base de malloc() con el memset(), así evitas ocupar más memoria y puedes simplemente reescribir la ya existente.


@jorwipuc
Primero de todo tienes que tener presente la estructura (básica) de la memoria de un ordenador. Una memoria se compone de direcciones, digamos que es una enumeración. Va desde 0 hasta X (en hexadecimal), depende de muchos factores, dígale ram.
Una variable normal es esto (los ejemplos a continuación no están probados pero deberían funcionar tal y como se indica):
int var_normal = 1;

Que podemos decir de esta variable? Simplemente esta variable se encuentra en una posición de memoria (una dirección).
Un puntero lo que hace es CONTENER una dirección de memoria. Si te has leído el capítulo entero, sabrás que con & podemos obtener la dirección de una variable; a método de aclaración:
&var_normal = 0x8792C /*Esto que acabo de hacer no tiene ningún sentido a nivel de programación, pero es para que se entienda*/

Imagínate que queremos guardar ese valor, necesitamos los punteros:
int *puntero_a_var; //Declaramos un puntero con *
puntero_a_var = &var_normal; //Le guardamos la dirección de var_normal


Utilidades... básicamente, si dominas los punteros, puedes hacer de todo (prácticamente xd):
No se si has llegado al apartado de funciones, pero, imagínate que hacemos esto:
void cambiar_valor(int variable){ variable = 10; }
int main(){
int a = 8;
printf("%d\n", a); //Enseñamos el valor de a
cambiar_valor(a); //Se supone que le cambiamos el valor
printf("%d\n", a); //Enseñamos el valor de a
sytem("pause");
}

Resultado:
8
8
Presione...


¿Porqué? La función cambia el valor de la variable llamada "variable". Te preguntarás, ?no es la misma que "a", puesto que la hemos pasado como parámetro? No, lo que hemos pasado es una copia de "a". Nada tiene que ver una con la otra.
Entonces, si quisiéramos cambiar el valor de "a" con una función, ¿como lo haríamos?
Hay una cosa que por más que copies, sigue siendo la misma, las direcciones de memoria. Pues, por ejemplo, 0x8A, seguirá siendo 0x8A te guste o no.
Entonces, podríamos pasar la dirección de la variable "a" a esa función, en vez de pasarle una copia. ¿Y eso como se hace? La respuesta es: PUNTEROS
void cambiar_valor(int *variable){
//Fíjate en el parámetro, un puntero

*variable = 10; 

/*Fíjate en el *, si tenemos un puntero ya declarado, en este caso "variable", y le añadimos delante *, lo que modificamos no es el valor del puntero (la dirección), sino aquello que está dentro de esa dirección:
PUNTERO = 0x88E;
si hacemos PUNTERO = 10, lo único que hacemos es cambiarle la dirección a 0xA (10 en decimal = 0xA en hexadecimal)
*PUNTERO = 10
Esto hace:
1. PUNTERO = 0x88E, asi que, vamos a esa dirección
0x88E => aquí se encuentra la variable "a" (hipotéticamente)
a = 10
*/
}
int main(){
int a = 8;
printf("%d\n", a); //Enseñamos el valor de a
cambiar_valor(&a); //Es un puntero lo que nos pide, así que, le damos la dirección de a
printf("%d\n", a); //Enseñamos el valor de a
sytem("pause");
}

Resultado:
8
10
Presione...


Espero quede todo un poco más claro.

Salu2,
Blipi

PD: Dentro de poco tendréis noticias de mi proyecto, y si hay suerte, el código también.
blipi escribió:@xXDraklordXx
El problema esta en el strcat() o al hacer printf? Me extraña que strcat de problemas. El tamaño de tu buffer es suficientemente grande como para alojar el texto_base + el texto_añadir? Compruébalo.


Por falta de memoria no es, hay de sobra. El problema sé que está en strcat() porque al omitirlo el "lag" desaparece. Ademas, en lugar de strcat() uso strcpy(), salvo que elimina el texto anterior, el resultado es el mismo y sin lag.

Total, veré que puedo hacer con eso si no se me ocurre nada mas.

Por otra parte. Me tomé un descansito y le añadí un Easter Egg bastante curioso XD.

Offtopic: Vaya, he iniciado yo las 4 últimas páginas.. ¿no estaré siendo un poco pesado? XD
xXDraklordXx escribió:Por falta de memoria no es, hay de sobra. El problema sé que está en strcat() porque al omitirlo el "lag" desaparece. Ademas, en lugar de strcat() uso strcpy(), salvo que elimina el texto anterior, el resultado es el mismo y sin lag.

Total, veré que puedo hacer con eso si no se me ocurre nada mas.


Mmmm... me extraña, prueba a ver con mi función, en teoría no debería causar lag alguno.
strcpy() significa string_copy, es decir, te copia la 2a en la 1a, por eso te lo elimina.

Si sigue dando lag, haz un printf primero, y luego usa strcpy, a malas, eso funciona seguro por lo que has dicho.

xXDraklordXx escribió:Offtopic: Vaya, he iniciado yo las 4 últimas páginas.. ¿no estaré siendo un poco pesado? XD

De eso se trata precisamente, de que posteéis vuestras dudas, código, explicaciones, sugerencias, etc.
Si llenas cuatro páginas, pos mejor, queda demostrado que tienes interés en tu proyecto y en aprender.

PD: Cuando quieras mándame la app, subela en multiupload o alguno de eso y pasame la dirección por mp, que le echaré una ojeada =P

Venga, me voy que tengo 2 exámenes T_T
Salu2 y animos!
blipi escribió:strcpy() significa string_copy, es decir, te copia la 2a en la 1a, por eso te lo elimina.


¿Me estás llamando tonto? Nah es broma [oki] ya lo sabía por eso lo anoté como salvedad. Por otra parte, sigue dando lag tanto almacenando el texto y el añadido en otra variable y luego imprimiendolo en pantalla, como mostrandolo todo directamente en pantalla sin pasar por variables, e incluso almacenando el texto en una variable y el añadido el otras y mostrandolos por printf. Supongo que será debido a la gran cantidad de texto que maneja... Lo unico que se me ocurre es crear un proceso o subproceso que se encargue de esa tarea para evitar que la aplicacion se bloquée. ¿Como lo ves?
Visto que hagas lo que hagas se bloquea, sí, no lo veo tan mala solución.
Crear un proceso en si mismo no se a que te refieres, sin embargo, mirate el tema de los threads. No se hasta que punto deja iOS 4.x gestionar threads, pero si lo hace, esa podría ser tu solución.
Un thread es una "subrutina" que se ejecuta como parte de tu proceso pero no consume la memoria del thread principal (dígase programa).

En windows es algo tan sencillo como:
void miThread(){
while(1){
    sleep(20); //Evitar que se sobrecargue
}
}

int main(){
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)miThread, NULL, NULL, NULL);
while(1) sleep(20); //evitar que se salga del programa
}
blipi escribió:Visto que hagas lo que hagas se bloquea, sí, no lo veo tan mala solución.
Crear un proceso en si mismo no se a que te refieres, sin embargo, mirate el tema de los threads. No se hasta que punto deja iOS 4.x gestionar threads, pero si lo hace, esa podría ser tu solución.
Un thread es una "subrutina" que se ejecuta como parte de tu proceso pero no consume la memoria del thread principal (dígase programa).

En windows es algo tan sencillo como:
void miThread(){
while(1){
sleep(20); //Evitar que se sobrecargue
}
}

int main(){
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)miThread, NULL, NULL, NULL);
while(1) sleep(20); //evitar que se salga del programa
}

Exacto, me refería a subrutina, no me acordaba del nombre xDD. Bueno, a partir de iOS 3.0, creo, eliminaron la posibilidad de crear subrutinas de manera "legal" con lo cual tengo que copiar la librería que me lo permite. Ya he hecho esto antes y funciona sin ningún problema con lo cual no creo que me de quebraderos de cabeza. En cuanto solucione ese tema te la mando para que le eches un ojo.

Edit: Tengo la cabeza hecha un lio. Yo te hablaba de subprocesos que se ejecutan de forma paralela al programa, el cual espera los resultados de este para continuar, pero estamos en las mismas, seguiría produciendo lag. Tu solución, es decir, crear un thread que se encargue del trabajo es, a priori, lo que necesito (ya veremos si luego reacciona como pretendo). Ya he encontrado la documentación para usarlos en iOS así que veremos a ver si cuela xD.

Edit 2: Sigue igual, ni con los threads puedo hacer que no se pause al añadir el texto. Es mas complicado de lo que pensaba, voy a intentar explicar los "sintomas" lo mejor posible:
- Tengo una ventana en la que muestro el texto.
- Cuando ejecuto por primera vez la función ls() todo parece ir perfecto.
- El problema surge al ejecutarla varias veces e imprimir el texto en la misma ventana.
- En cambio si uso cualquier otra función de las que he programado no hay lag.
- Si uso la funcion clear() para borrar el texto de la ventana y vuelvo a usar ls() otra vez marcha perfecto.
- Hasta donde puedo entender el problema viene al añadir el texto a la ventana puesto que si en lugar de mostrarlo
por pantalla lo muestro por consola directamente no se produce lag alguno.

He revisado varias veces el código y lo he probado por separado y nada. Con un fallo tan tonto como este y provocando la pausa del proyecto =( xD debo de ser muy inutil jajaja.
Blipi, cómo que para guardar un valor necesitamos los punteros? Un valor no es una variable? Y la variable que yo sepa se alberga en la memoria directamente así que no se de que puede servir exactamente
Exactamente, ¿que longitud de cadena te produce lag? Además, ¿estás haciendo pruebas en el ordenador o sobre el móvil?

Entiendo que usas una cadena como buffer de consola, ¿que estas usando para pintar en ventana el texto, un widget tipo TextEdit?
La verdad es que me dejas un poco perdido con el último mensaje que has puesto, dices que el retardo desaparece cuando lo muestras directamente por consola (¿entiendo que estás usando el ordenador?), ¿lo que muestras por consola es el resultado del strcat o sólo algo tipo printf(ls())?

De cualquier manera, si quieres, le echo un ojo al código.

@jorwipuc
Un puntero sirve, por ejemplo, para tener varios "nombres" para la misma zona de memoria. Además la "creación de variables" en tiempo de ejecución solo se puede realizar mediante la reserva de memoria dinámica, espacio que será accesible únicamente a través de un puntero. Leete esto y verás claramente la utilidad (más bien algo de la utilidad) de los punteros.
Se podría decir que con un puntero puedes "nombrar" cualquier zona de la memoria y además, y aquí es donde está toda la gracia del tema, la zona "nombrada" puede cambiar durante la ejecución de un programa (es decir, un puntero es un "alias" de una zona de memoria) cosa que no se puede realizar con las variables convencionales (variables estáticas) pues siempre "nombran" la misma zona. Estudia detenidamente la pagina de la Wikipedia y verás que no es posible montar esa estructura sin punteros.
Juen escribió:Exactamente, ¿que longitud de cadena te produce lag? Además, ¿estás haciendo pruebas en el ordenador o sobre el móvil?

Entiendo que usas una cadena como buffer de consola, ¿que estas usando para pintar en ventana el texto, un widget tipo TextEdit?
La verdad es que me dejas un poco perdido con el último mensaje que has puesto, dices que el retardo desaparece cuando lo muestras directamente por consola (¿entiendo que estás usando el ordenador?), ¿lo que muestras por consola es el resultado del strcat o sólo algo tipo printf(ls())?

...

De cualquier manera, si quieres, le echo un ojo al código.

@jorwipuc
Un puntero sirve, por ejemplo, para tener varios "nombres" para la misma zona de memoria. Además la "creación de variables" en tiempo de ejecución solo se puede realizar mediante la reserva de memoria dinámica, espacio que será accesible únicamente a través de un puntero. Leete esto y verás claramente la utilidad (más bien algo de la utilidad) de los punteros.
Se podría decir que con un puntero puedes "nombrar" cualquier zona de la memoria y además, y aquí es donde está toda la gracia del tema, la zona "nombrada" puede cambiar durante la ejecución de un programa (es decir, un puntero es un "alias" de una zona de memoria) cosa que no se puede realizar con las variables convencionales (variables estáticas) pues siempre "nombran" la misma zona. Estudia detenidamente la pagina de la Wikipedia y verás que no es posible montar esa estructura sin punteros.

Si, uso el ordenador para pruebas, si lo mismo lo hago en el movil el lag es aun mayor. El problema del código (y por lo que no lo posteo para que le hecheis un ojo) es que está en Objective-C. La verdad es que me tiene la cabeza loca el tema este, no entiendo en que falla. Un ultimo apunte: uso el mismo metodo para mostrar el texto en pantalla en todas las funciones y solo en esa me da lag

P.D: El texto lo muestro en un textView que sería algo parecido a lo que tu dices.
A ver, vamos por partes:
- Primero de todo. La misma pantalla es un buffer, del tamaño de esta misma. Todo el contenido que vayas a mostrar y que se vea en ese momento, se guarda en ese buffer. El otro, en el caso de printf, (supongo, pues nunca he mirado este), guarda el valor de tu variable. (lo que se sostiene mediante el hecho de que si eliminas un texto o puntero en el código, sigue saliendo en pantalla).
Dicho esto, esta claro que el problema no es del dispositivo, pues la gestión de su buffer de pantalla no puede causar lag. Siendo así, veo dos posibles problemas:

1- Mala gestión de la memoria en el programa, alojando demasiada y no liberandola. Aunque lo veo improbable, porque esto en todo caso provocaría que no se pudieran declarar mas variables, y no lag.
2- Tal como he dicho, la consola (o un textbox) tiene un buffer interno. Me parecería raro, pero asegurare de que en tu función no leas todo el buffer primero y luego añadas, o algo por el estilo.
Si en la consola te funciona bien, y en el textView va lento, todo parece indicar que el problema esta en la función para añadir texto a dicho widget, que se comportase como he dicho antes.

Si además dices que solo una función te produce el lag, la del ls(), no podría ser que el lag te lo produciera el while() para leer los directorios? (aunque muchos directorios reveían haber). Asegurare de chequear esa función entera.

Aunque este en objective-c, iría bien que postearas, o si lo prefieres manda por mp, el codigo. Sino es como ir dando palos de ciego.
Bien pues ahora estoy en el movil pero en un momento os dejo el código. Todo sea por resolver este enredo. Gracias una vez mas por la ayuda que he recibido por todos vosotros, se ve que queda buena gente XD

He aqui el codigo:
- (int)ls:(NSArray *)args {
   if ([args count]>3) {
      [cmdView setText:[[cmdView text] stringByAppendingString:@"\tInvalid use. Type help for more info."]];
   } else {
      struct dirent *entry;
      DIR *dir;
      
      // ls() sin archivos ocultos
      if ([args count]==1) {
         dir = opendir(getcwd(NULL, 0));
         if (dir) {
            while (entry = readdir(dir)) {
               if (entry->d_name[0]!='.') {
                  [cmdView setText:[[cmdView text] stringByAppendingString:
                                [NSString stringWithFormat:@"\t%s\n", entry->d_name]]];
               }
            }
            [self delLastChar]; // Borra el ultimo caracter ('\n') tras añadir el texto
         } else {
            [cmdView setText:[[cmdView text] stringByAppendingString:@"\tNo such file or directory."]];
         }
         closedir(dir);
      }
   }
}

Como digo, al ejecutar varias veces esta función (es solo un trozo de código puesto que el código total de la función ls() incluye mas argumentos pero use el que use -o ninguno- produce dicho lag). Sin embargo ejecutando la misma función introduciendo un valor incorrecto, para que la primera sentencia if se cumpla, no se produce lag. Ejecutando cualquier otra función no se produce lag. Limpiando el textView (cmdView) y ejecutando la función nuevamente desaparece el lag. Eliminando la sentencia [cmdView setText:[[cmdView text] stringByAppendingString:
[NSString stringWithFormat:@"\t%s\n", entry->d_name]]];
y sustituyendola por printf("\t%s\n", entry->d_name); Los resultados se muestran por consola sin ningún tipo de lag. Y como toque final y para enredar mas las cosas decir que uso la misma sentencia para añadir el texto en TODAS las funciones y ninguna salvo esta producen lag. Yo me he quedado sin soluciones salvo volver a escribir el programa con otra estructura a ver si lo soluciono [buuuaaaa]

Añadir que (NSArray *)args es una cadena de texto introducida por el usuario y dividida y almacenada en un array cuyos objetos se obtienen de la cadena separando los elementos por un espacio.
Si es necesario explico el código linea por linea para evitar malentendidos. Según creo no es por el tema de gestión de memoria puesto que en el código no se declara ninguna variable que deba ser liberada.
El problema está, tal y omo supuse, en que cada vez que añades texto haces una lectura del buffer de dicho textView, en [cmdView text]. Claro, a cada llamada pasa lo siguiente. Suponiendo que el texto que se añade es siempre de 100 chars:
1a llamada: Leer buffer: 0 ; Añadir 100
2a llamada: Leer buffer: 100 ; Añadir 100
10a llamada: Leer buffer: 900 ; Añadir 100
Etc. Leer todo el buffer implica tiempo. A mas buffer, mas tiempo. No se como funcionan las appendString con o sin Format en Objective-C, pero parece ser que lo leen todo. En medida de lo posible, yo usaría una variable char* (o NSArray*) como único buffer. Usaría strcat explícitamente en ese buffer, y luego añadiría todo ese buffer al textView, sin leer el contenido de este ultimo.
Si sigue dando lag, estaría claro que el problema es que el textview no soporta gran cantidad de texto, ya que para poder enseñarlo tiene que leer todo el buffer, y lo hace de manera lenta e inefectiva.

Espero sea de ayuda,
Salu2!
blipi escribió:El problema está, tal y omo supuse, en que cada vez que añades texto haces una lectura del buffer de dicho textView, en [cmdView text]. Claro, a cada llamada pasa lo siguiente. Suponiendo que el texto que se añade es siempre de 100 chars:
1a llamada: Leer buffer: 0 ; Añadir 100
2a llamada: Leer buffer: 100 ; Añadir 100
10a llamada: Leer buffer: 900 ; Añadir 100
Etc. Leer todo el buffer implica tiempo. A mas buffer, mas tiempo. No se como funcionan las appendString con o sin Format en Objective-C, pero parece ser que lo leen todo. En medida de lo posible, yo usaría una variable char* (o NSArray*) como único buffer. Usaría strcat explícitamente en ese buffer, y luego añadiría todo ese buffer al textView, sin leer el contenido de este ultimo.
Si sigue dando lag, estaría claro que el problema es que el textview no soporta gran cantidad de texto, ya que para poder enseñarlo tiene que leer todo el buffer, y lo hace de manera lenta e inefectiva.

Espero sea de ayuda,
Salu2!


Pensaba lo mismo pero no sabía como solucionarlo. He encontrado una funcion similar a strcat() que me permite trabajar directamente con (NSString *) asi que en cuanto corrija el código veremos que tal. Gracias por tu respuesta blipi me has abierto los ojos [oki]

Edit: Pues ya está todo solucionado. Ahora tira perfecta. De momento he programado estos comandos. A ver cual me falta o cual sobra:

help
cd(path)
ls(-a all files, -i info)
pwd
clear
read(text file, -b bin file)
echo(text, -f file, -b bin file)
about
chname(shell name)
exit

Evidentemente faltan unas cuantas pero quiero saber cuáles consideráis mas utiles para añadirlas primero.
Me alegro que al final se haya solucionado el problema!
Pues mira, a mi gusto, (si puedo pedir jeje), me encantaría una función mkdir (para crear directorios) y funciones para mover/copiar/eliminar archivos. Para mi estas son casi esenciales, eran las que mas usaba (junto cd) con el antiguo terminal =P

Quería comentar que he intentado editar el tutorial y ponerle más cosas des del iPod, pero parece ser que un 2g se muere en el camino de intentar procesarlo xd Si consigo meterme en el portatil, porque del mio ya me puedo olvidar, lo ampliaré bastante.

Salu2
T_T al probarlo en el simulador todo iba perfecto pero al hacerlo en el iPhone pasa mas o menos lo mismo que antes, sigue habiendo lag solo que ahora es mucho menos evidente. Tengo otra idea en la cabeza con la que posiblemente evite de una vez almacenar el texto en un buffer y acabe así con el lag pero mientras tanto voy a tirar con esto para terminar de escribir las funciones y cuando acabe ya probaré esto.
Quiero empezar a aprender un poco de programación en C y me gustaria saber con que programa puedo simular el código que llevo.

Un saludo
toni_23 escribió:Quiero empezar a aprender un poco de programación en C y me gustaria saber con que programa puedo simular el código que llevo.

Un saludo

Depende para la plataforma que quieras o hayas preparado el código.
Mediante esas líneas de código se genera un ejecutable (compilación) que después puedes "simular" como bien dices en la plataforma correspondiente.

Lo que tienes que hacer es instalarte un IDE (Entorno de Desarrollo) y compilar el código. Para Windows yo uso WxDev-C++ que es libre, gratuito y está bastante bien.

De todas formas, dinos para que plataforma te interesa desarrollar y te echamos un cable. Te recomiendo que empieces por PC ya que es lo más estándar y documentado.

Un saludo! ;)
@toni_23
Hay infinidad de IDE y entornos de programación. En las páginas 1-15, no me acuerdo, ya se comentaron varios.
Además, en el capítulo 5 del tutorial, justo al principio de todo, describo como utilizar Visual C++ Express 2010 (o inferior), un IDE.

@xXDraklordXx
Pues entonces no me queda más que pensar que el problema es el propio textView. Realmente, hay alguna necesidad de usarlo? Quiero decir, no puedes simplemente tirar de la consola?
Si consigues resolverlo, ya me contarás como, que tengo curiosidad ya jeje

Salu2!
blipi escribió:@toni_23
Hay infinidad de IDE y entornos de programación. En las páginas 1-15, no me acuerdo, ya se comentaron varios.
Además, en el capítulo 5 del tutorial, justo al principio de todo, describo como utilizar Visual C++ Express 2010 (o inferior), un IDE.

@xXDraklordXx
Pues entonces no me queda más que pensar que el problema es el propio textView. Realmente, hay alguna necesidad de usarlo? Quiero decir, no puedes simplemente tirar de la consola?
Si consigues resolverlo, ya me contarás como, que tengo curiosidad ya jeje

Salu2!


Es necesario usarlo, sino el usuario no puede ver la respuesta a los comandos que introduce. A no ser que se me ocurra otra manera... De momento lo que hare sera probar con un webView en lugar de con un textView y según los resultados volveré a escribirlo o no con la idea que tengo en mente.
Qarl escribió:
toni_23 escribió:Quiero empezar a aprender un poco de programación en C y me gustaria saber con que programa puedo simular el código que llevo.

Un saludo

Depende para la plataforma que quieras o hayas preparado el código.
Mediante esas líneas de código se genera un ejecutable (compilación) que después puedes "simular" como bien dices en la plataforma correspondiente.

Lo que tienes que hacer es instalarte un IDE (Entorno de Desarrollo) y compilar el código. Para Windows yo uso WxDev-C++ que es libre, gratuito y está bastante bien.

De todas formas, dinos para que plataforma te interesa desarrollar y te echamos un cable. Te recomiendo que empieces por PC ya que es lo más estándar y documentado.

Un saludo! ;)


Gracias.

Y sí, empezaria a programar en PC que es lo más básico.

He usado el programa que me has recomendado y me ha funcionado [oki]

@blipi, gracias por el tuto.
Se que a la mayoría esto les va a importar poco, pero este es el estado actual de mi proyecto "Routin3". Para los que no lo leyeron, Routin3 será un intérprete o meta-lenguaje de programación, enfocado a aprender C de manera sencilla. La sintaxis se basa en la de Basic, pero incluirá modificaciones para adaptarla a C.

Se basa en un simple ejecutable de 20 kb de tamaño y un archivo de texto (o en cualquier formato) conteniendo el código. Se ejecuta mediante una simple orden "exec" (coge por defecto el archivo "routine.txt" en el directorio actual), o "exec [ruta]".

Estado actual:
  • Declara variables
  • Guarda valores a variables, tanto directamente, como (var a = "A"), como mediante funciones, (var b = obtenerValor())
  • Se pueden declarar funciones con argumentos, y pasar dichos argumentos
  • Implementada función print
  • Corrector de sintaxis
  • Llamadas a funciones

A hacer (por orden de prioridad):
  • Detección de error al declarar string con más de 2 "", (esto: "hola "amigo"" y esto: "hola "amigo" es válido, pero no debería serlo)
  • Aun no se acepta el rango de variable local / global. -> Después de esto sacaré un versión pública.
  • Operaciones matemáticas y lógicas (+, -, pow, etc)
  • Operaciones de condicionales y bucles (if, else, y bucles)
  • Codificación de punteros de memoria
  • Codificación de arrays
  • Codificación de structs
  • Codificación de clases

Aquí tenéis una foto del proyecto:
Imagen
La verdad que tiene pinta que te lo estás currando bastante :)
Pero... qué finalidad buscas con este proyecto? a parte de aprender (que para mí suele ser lo más importante) por supuesto.

Salu2 y ánimo! ;)
blipi escribió:Se que a la mayoría esto les va a importar poco, pero este es el estado actual de mi proyecto "Routin3". Para los que no lo leyeron, Routin3 será un intérprete o meta-lenguaje de programación, enfocado a aprender C de manera sencilla. La sintaxis se basa en la de Basic, pero incluirá modificaciones para adaptarla a C.

Se basa en un simple ejecutable de 20 kb de tamaño y un archivo de texto (o en cualquier formato) conteniendo el código. Se ejecuta mediante una simple orden "exec" (coge por defecto el archivo "routine.txt" en el directorio actual), o "exec [ruta]".

Estado actual:
  • Declara variables
  • Guarda valores a variables, tanto directamente, como (var a = "A"), como mediante funciones, (var b = obtenerValor())
  • Se pueden declarar funciones con argumentos, y pasar dichos argumentos
  • Implementada función print
  • Corrector de sintaxis
  • Llamadas a funciones

A hacer (por orden de prioridad):
  • Detección de error al declarar string con más de 2 "", (esto: "hola "amigo"" y esto: "hola "amigo" es válido, pero no debería serlo)
  • Aun no se acepta el rango de variable local / global. -> Después de esto sacaré un versión pública.
  • Operaciones matemáticas y lógicas (+, -, pow, etc)
  • Operaciones de condicionales y bucles (if, else, y bucles)
  • Codificación de punteros de memoria
  • Codificación de arrays
  • Codificación de structs
  • Codificación de clases

Aquí tenéis una foto del proyecto:
Imagen

¿Como eres capaz de suponer que no nos importa? Viendo lo que me has ayudado... Macho todo lo que hagas será un referente para mi xD. Pensaba hacer algo similar en mi consola para ejecutar scripts así que a ver que sale. Por supuesto será cuando solucione lo del "lag" que me tiene hasta las narices xD. Un saludo blipi y animo con tu proyecto macho jeje.

Edit: Me habeis robado 2 páginas... =( xD naaaah jeje

Edit 2: Tal como pensaba y como tu bien intuiste blipi. El lag era debido a la capacidad del textView para almacenar gran cantidad de texto. Lo que he hecho para solucionarlo es almacenar el texto (con estructura HTML) en un webView y ahí tira sin problemas. Le meto las funciones que me dijiste y te la mando para que le des caña y me des consejos para mejorarla. Un saludo hermano jaja [oki]
¿Finalidad? Realmente ninguna, simplemente no sabía que programar, y me dije a mi mismo, voy a hacer un "lenguaje" (si así se le puede llamar) de programación. Ahora por ahora me lo estoy pasando genial programando eso, cada problema, cada nueva instrucción, cada linea, para mi es increíble xd
Quizás la finalidad más práctica que le podré encontrar: tengo la intención de todo ese script o meta-lenguaje pasarlo a Assembler y crear binarios, (.exe). Lo que se vendría diciendo, hacer un compilador. Nunca he llegado a eso, tan siquiera me había planteado nunca la posibilidad de hacer un proyecto como este.
Y poco más la verdad, si luego alguien lo usa bien, y si no, pos mira, un proyecto más a mi lista de proyectos xd.

Jajaj, lo de que no os importase no iba para todos hombre xd solo que a la mayoría supongo que esto no les afectará mucho. Bueno, me alegro de que ya funcione tu shell.
Si vas al final de este mismo post, te explico como estructuro el programa:

Abajo de esto, descarga.

Estado actual:
  • Declara variables
  • Guarda valores a variables, tanto directamente, como (var a = "A" ; a = "B"), como mediante funciones, (var b = obtenerValor())
  • Se pueden declarar funciones con argumentos (max. 10 argumentos), y pasar dichos argumentos
  • Implementada función print
  • Corrector de sintaxis
  • Llamadas a funciones
  • Identificación del rango de una variable (por ahora solo locales y argumentos)
  • Array implementada
var mi_array[20] = "A"
Inicializa toda la array a "A"
mi_array[5] = "B"
Cambia el elemento 5 (empezando des del 0)
function test(var una_array[])
La función pide como parámetro 1, una array
test(mi_array)


A hacer (por orden de prioridad):
  • Declarar arrays sin inicializarlas
  • Variables globales
  • Operaciones matemáticas y lógicas (+, -, pow, etc)
  • Funciones recursivas (funcion(funcion(funcion)))
  • Operaciones de condicionales y bucles (if, else, y bucles)
  • Codificación de punteros de memoria
  • Codificación de arrays
  • Codificación de structs
  • Codificación de clases

Código de ejemplo:
function main()
   var a[5] = "B\n"

   print "MAIN1: " & a[2]
   submain_1(a, "I\n\n")

   a[2] = just_a_test()

   submain_2(a[2])

   print "\n\n"

   var c = print_custom("TEST\n")
   print c
endfunction

function submain_1(var b[], var m)
   print "SUBMAIN_1: " & b[2] & " " & m
endfunction

function submain_2(var b)
   print "SUBMAIN_2: " & b
endfunction

function just_a_test()
   return "OMFG!"
endfunction


function print_custom(var value)
   print value
   return value
endfunction



Descarga desde: http://www.multiupload.com/SGS9SJL7QK
Nota: Para ejecutar comando "exec", busca automaticamente en la ruta actual el archivo "routin3.txt", si lo indicas tu:
exec ./archivo.txt  //en la misma ruta
exec C:/archivo.txt  //otra ruta


Breve explicación del funcionamiento. Para poder almacenar las variables utilizo linked list, luego te enseño que son. Entonces, el procedimiento que uso es el siguiente:
  1. Mapeado del archivo de código (guardo cada línea, ya que el lenguaje opera por líneas) y guardo donde empieza cada función
  2. Ejecuto la función main()
  3. Leo línea a línea la función. Si encuentro una llamada a otra función, la ejecuto.
  4. Cuando se acaba la función, elimino las variables creadas en dicha función y los argumentos.

A partir de esto tengo funciones para todo:
mappedFuncExists()
varExists()
getArray()
getValue()
getFunction()
getLine()
lineParser()
executeFunction()
mapFile()
executeProgram()

Además de las funciones para validar la sintaxis y las declaraciones y un par de adaptaciones que he hecho a strtok porque no acaba de satisfacerme como funcionaba.

Cuanto más delimitado este el programa, y más bien lo organices, mejor. El mio, si no lo hubiera organizado así, estaría repitiendo el mismo código a cada 10 lineas.

Y esta es la organización de mi proyecto, a base de linked list:
struct _PROGRAM_STACK;
struct _PROGRAM_FUNCS_MAP;
struct _PROGRAM_FUNCS_CURRENT;
struct _PROGRAM_VAR;
struct _PROGRAM_LINES;
struct _PROGRAM_COMMANDS;

//La parte más importante. Mantiene la cuenta de todo en cuanto pasa.
struct _PROGRAM_STACK{
   int lineCount;
   int mainFunc;

   void *retVal;

   _PROGRAM_VAR *parametersStack;
   _PROGRAM_FUNCS_CURRENT *pCurrentFunc;

   _PROGRAM_FUNCS_MAP *pMainMap;
   _PROGRAM_FUNCS_MAP *pMap;
   _PROGRAM_FUNCS_MAP *lastMap;

   _PROGRAM_VAR *pVars;
   _PROGRAM_VAR *lastVar;

   _PROGRAM_LINES *pLines;
   _PROGRAM_LINES *lastLine;

   _PROGRAM_COMMANDS *cCommands;
};

//Cada una de las funciones mapeadas
struct _PROGRAM_FUNCS_MAP{
   int lineNum;
   int endLineNum;

   _PROGRAM_LINES *openLine;
   
   char *funcName;
   int numArgs;
   char *argName[10];
   int argType[10];

   _PROGRAM_FUNCS_MAP *next; //Siguiente variable
   _PROGRAM_FUNCS_MAP *prev; //Anterior variable
};

//Función ejecutandose, por ejemplo: Test2->Test1->Main (hemos empezado desde main haciendo llamada a Test1 y luego desde Test1 a Test2, funciona como una pila)
struct _PROGRAM_FUNCS_CURRENT{
   _PROGRAM_FUNCS_MAP *pFunc;
   _PROGRAM_FUNCS_CURRENT *prev;
};

//Cada una de las variables que se declaran
struct _PROGRAM_VAR{
   int varType;

   int arrayType; //array type
   int arrayMaxLen;
   _PROGRAM_VAR *arrayValue;
   _PROGRAM_VAR *lastArrayValue;
   //
   //1. INT
   //2. FLOAT
   //3. DOUBLE
   //4. CHAR
   //5. ARRAY
   //
   char *varName;
   void *varValue;
   char varRange[500];

   _PROGRAM_VAR *next;
   _PROGRAM_VAR *prev;
};

//Cada una de las línea del programa
struct _PROGRAM_LINES{
   int lineNum;
   char *lineLine;
   int lineType;
   //
   //1. Simple command
   //2. Function start
   //3. Function end
   //4. Composed command
   //
   int lineComposedReference;

   _PROGRAM_LINES *next;
   _PROGRAM_LINES *prev;
};
Muchas gracias! Cuando pueda le echo un vistazo ;)
Shantotto está baneado por "utilizar clon para saltarse baneo temporal"
Blipi, te sugiero que cuanto antes empieces a usar árboles, con binarios hay suficiente. Si cada línea es un árbol, es inmediato implementar las jerarquías de los operadores, funciones recursivas, poda en los ifs cuando se cumple la primera condición y demás.
Luego dar el paso a funciones que sean un árbol de árboles es bastante sencillo.

Dicho esto, me quito el sombrero. Quizás de aquí a 30 años en vez de estar leyendo el Kerninghan & Ritchie la gente estará leyendo el Blipi & Blipi.
jaja, ya estoy usando arboles binarios de expresiones. Lo que pasa es que no tengo mucho tiempo para dedicarle, y cuando publiqué eso, no me preguntes porque, lo había hecho sin arboles. (Yo tampoco lo entiendo xd). La verdad es que es mucho más cómodo trabajar con árboles, no se porqué me compliqué tanto la vida xd
En realidad, he hecho una aplicación de árbol binario, pero con acceso a su padre, que me es más útil para añadir hijos.

De momento realizo un parseado de una sola pasada sin optimización, y estoy en proceso de convertir las instrucciones a ASM, pero mi nivel de asm es mas bien limitado, hace muy poco que lo toco en profundidad, y bueno, me lleva su tiempo. Me tengo que volver a leer mi libro de asm, porque cuando lo hice no practiqué, y ahora ya casi ni me acuerdo, solo de operaciones muy básicas.

Gracias por el soporte!
blipi siento no haberte mandado la app todavía. Estoy teniendo varios problemas a la hora de optimizar la interfaz y he vuelto a coger mi libro para ver que puedo hacer, pero en cuanto esté lista prometo mandartela. Un saludo gente.
Ya que este es el hilo de programación, me sacan esta duda, se pueden utilizar este tipo de sentencias:
  if (iguales = (x == y)? 1:0)
cltomas escribió:Ya que este es el hilo de programación, me sacan esta duda, se pueden utilizar este tipo de sentencias:
  if (iguales = (x == y)? 1:0)

Pues así a simple vista no... que quieres hacer?? ponlo en pseudocódigo y te digo como sería en C.
Qarl escribió:
cltomas escribió:Ya que este es el hilo de programación, me sacan esta duda, se pueden utilizar este tipo de sentencias:
  if (iguales = (x == y)? 1:0)

Pues así a simple vista no... que quieres hacer?? ponlo en pseudocódigo y te digo como sería en C.

Es este el programa:
Crear un programa que use el operador condicional para dar a una variable llamada
  “iguales” (entera) el valor 1 si los dos números que ha tecleado el usuario son iguales,
  o el valor 0 si son distintos.

Así lo hice yo:
#include <stdio.h>

int main()
{
int x, y, iguales,distintos;
printf("\nDame un numero =>");
scanf("%d", &x);
printf("Dame otro número =>");
scanf("%d", &y);
if (iguales = (x == y)? 1:0)
printf("\nLos numeros son iguales %d\n", iguales);

else
printf("\nLos números no son iguales %d\n", iguales);
getchar();
return 0;
}
no exactamente, lo que tu quieres hacer es así:
iguales = ((x == y)?1:0)


@xXDraklordXx
Tranqui, cuando lo tengas avisame =)
blipi escribió:no exactamente, lo que tu quieres hacer es así:
iguales = ((x == y)?1:0)


Eso lo sé blipi,
Antepuse el if para poder insertar la sentencia del else, ya que no se me ocurrio como colocar ese printf sin el else.... [snif]
soy autodidacta, así que imaginate la cantidad de dudas que se me presentan y no tengo a nadie a quien preguntar, así que a prueba de errores voy tirando para delante
¿pero al hacerlo como tu dices, como agrego el printf del else??...
mmm no puedes, de esa forma solo puedes asignar valores. Si quieres poner un else con instrucciones, no te queda mas remedio que construir un if. Por jemplo:
iguales = ((x == y)?1:0);
if(iguales == 0) printf("No iguales");


o
if(x == y)
iguales = 1;
else{
iguales = 0;
printf("No iguales");
}


EDITO: De hecho, si hay una solución más, creo, puesto que no lo he comprobado:
if((iguales = ((x == y)?1:0)) == 0)
printf ("No iguales);
else printf("Iguales");
blipi escribió:EDITO: De hecho, si hay una solución más, creo, puesto que no lo he comprobado:
if((iguales = ((x == y)?1:0)) == 0)
printf ("No iguales);
else printf("Iguales");

Uf pero yo con eso, ya me pierdo.. y al momento de depurar creo que me traería muchos dolores de cabeza [looco] [looco]
Tengo otro souce, me hechas un cable, pero me salta una duda:
#include <stdio.h>

/*Dados como entrada 3 enteros representando la fecha como dia ́ mes, año, imprimir la fecha del dia anterior.
Por ejemplo para una entrada como: 1 3 1992 La salida seria: Fecha anterior a 1-3-1992 es 29-02-1992 */
                                                       
                                       
int main()
{
    int dia;
    int mes;
    int anno;
    int dia2, mes2;
    int fecha;
    int anno2;
   
    printf("\nIntroduce el Día del mes=>\n");
    scanf("%d", &dia);
    getchar();
    printf("\nIntroduce el mes [numerario]=>\n");
    scanf("%d", &mes);
    getchar();
    printf("\nIntroduce el año =>\n");
    scanf("%d", &anno);
    getchar();
   
     dia2=dia-1;
     mes2=mes-1;
     anno2=anno-1;
   
    /* como restringir la entrada del dia y mes a 2 digitos y año a 4 digitos*/
   
     if((dia2 == 0) && (mes2 == 0) && (anno != 0)) //caundo fecha sea del tipo 1-1-1977
     
      {
         dia2 = 30;
         mes2 = 12;
       
         printf("\n[1º] La fecha anterior a %d-%d-%d es %d-%d-%d\n", dia, mes, anno, dia2, mes2, anno2);
      }
    else
        if ((dia2 > 0) && (mes2 == 0) && (anno != 0))// cuando fecha sea del tipo 12-1-1977
   
      {
           dia2=dia - 1;
           mes2=mes2 + 1;
         
           printf("\n[2º]La fecha anterior a %d-%d-%d es %d-%d-%d\n", dia, mes, anno, dia2, mes2, anno);
        }
     else
         if ((dia2 == 0) && (mes2 > 0) && (anno != 0))// cuando  fecha sea del tipo 1-12-1977
       {
           dia2= 30;
           mes2=mes -1;
           
          printf("\n[3º]La fecha anterior a %d-%d-%d es %d-%d-%d\n", dia, mes, anno, dia2, mes2, anno);
       }
     else
        if ((dia2 > 0) && (mes2>0) && (anno != 0))//cuando fecha  sea del tipo 16-4-1977
       {
          dia2=dia -1;
          mes2=mes2 + 1;
         
          printf("\n[4º]La fecha anterior a %d-%d-%d es %d-%d-%d\n", dia, mes, anno, dia2, mes2, anno);         
        }
     else
           if ((dia == 0) || (mes == 0) || (anno == 0))
      {     
          printf("\n[5] ERROR ..Has introducido un 0.. \n");
      }
     else
      {
           printf("\nERROR!!!! (día, mes, año negativo?)\n");//para números negativos LoL!!!!
      } 
   getchar();
    return 0;
}

Mi duda es ¿como restringir la entrada del dia y mes a 2 digitos y año a 4 digitos?
p.d= Sé que me fui por las ramas con el código, pero estoy aprendiendo [+risas]
La forma más fácil que veo para hacer lo que comentas cltomas es la siguiente:
#include <stdio.h>

int main()
{
   int x, y;
   
   printf("Dame un numero => ");
   scanf("%d",&x);
   printf("Dame otro número => ");
   scanf("%d",&y);
   
   if(x == y)
      printf("\nLos numeros son iguales.\n", iguales);
   else
      printf("\nLos números no son iguales.\n", iguales);
   
   getchar();
   return 0;
}


Salu2 ;)
Qarl escribió:La forma más fácil que veo para hacer lo que comentas cltomas es la siguiente:
#include <stdio.h>

int main()
{
   int x, y;
   
   printf("Dame un numero => ");
   scanf("%d",&x);
   printf("Dame otro número => ");
   scanf("%d",&y);
   
   if(x == y)
      printf("\nLos numeros son iguales.\n", iguales);
   else
      printf("\nLos números no son iguales.\n", iguales);
   
   getchar();
   return 0;
}


Salu2 ;)

Lo sé Qarl, pero te piden que utilices el operador condiconal
?
Disculpa, es que si te digo la verdad nunca he usado ese operador condicional (ni si quiera lo conocía :O ).
Lo he estado mirando un poco y así debería de tirar:
int main()
{
   int x, y, iguales;

   printf("Dame un numero => ");
   scanf("%d",&x);
   printf("Dame otro número => ");
   scanf("%d",&y);

   iguales = ((x==y) ? (1:0));

   if(iguales == 1)
      printf("\nLos numeros son iguales.\n", iguales);
   else
      printf("\nLos números no son iguales.\n", iguales);

   getchar();
   return 0;
}
Ya lo había resuelto, pero te comento:
El código esta bien excepto por esto, esta línea la tienes mal, aquí te muestro la correcta:
   iguales = (x==y) ?  1:0;

Lo otro es que al compilar me da unos warning ¬_¬ ....Y no sé a que se deben, pero lo compila y lo ejecuta bien..
$ gcc -o igual igual.c
igual.c: In function ‘main’:
igual.c:5: warning: incompatible implicit declaration of built-in function ‘printf’
igual.c:6: warning: incompatible implicit declaration of built-in function ‘scanf’

[comor?] [comor?]
Por esto era el error [+risas] [+risas] , por hacer copy/paste y no darme cuenta que faltaba la libreria stdio.h XD
#include <stdio.h>
Mucho me temo que:
   iguales = (x==y) ?  1:0;

es lo mismo que
   iguales = ((x==y) ?  1:0);

que es lo mismo que
   iguales = ((x==y) ?  (1:0));

y que muchas mas variantes que se pueden escribir.

Salu2
blipi escribió:Mucho me temo que:
   iguales = (x==y) ?  1:0;

es lo mismo que
   iguales = ((x==y) ?  1:0);

que es lo mismo que
   iguales = ((x==y) ?  (1:0));

y que muchas mas variantes que se pueden escribir.

Salu2

Efectivamente, los paréntesis solo son para entender y asociar mejor los datos. Siempre y cuando estén bien cerrados puedes poner todos los que quieras ;)
448 respuestas
14, 5, 6, 7, 8, 9