[TUTORIAL] Programando en C

15, 6, 7, 8, 9
aquilino escribió:
xXDraklordXx escribió:Si, se como funciona, por eso mi duda. Con un simple sleep(1) no reacciona, es necesario limpiar el buffer de salida - fflush(stdout) - para que funciona y eso es lo que no entiendo.


lo he probado asi
#include <stdio.h>
#include <windows.h>

int main() {
     int i;
     for (i=0; i<=10; i++) {
          printf("%i", i);
          //fflush(stdout);
          Sleep(1000); // En mili segundos 
     }
     return 0;
}


funciona bien prueba y me cuentas


No uso windows y sleep está definido en otra librería (unistd.h), quizás sea por eso.
xXDraklordXx escribió:
aquilino escribió:
xXDraklordXx escribió:Si, se como funciona, por eso mi duda. Con un simple sleep(1) no reacciona, es necesario limpiar el buffer de salida - fflush(stdout) - para que funciona y eso es lo que no entiendo.


lo he probado asi
#include <stdio.h>
#include <windows.h>

int main() {
     int i;
     for (i=0; i<=10; i++) {
          printf("%i", i);
          //fflush(stdout);
          Sleep(1000); // En mili segundos 
     }
     return 0;
}


funciona bien prueba y me cuentas


No uso windows y sleep está definido en otra librería (unistd.h), quizás sea por eso.


ok ,sleep esta definida en dos.h prueba con unistd.h usleep(20000); //include unistd.h 200000 = 2 segundos
ahora me paso ha linux y pruebo

#include <stdio.h>
//#include <windows.h>
#include <unistd.h>

int main() {
     int i;
     for (i=0; i<=10; i++) {
          printf("%i", i);
         // fflush(stdout);
          usleep(200000); //
     }
     return 0;
}

pues si que es necesario en linux fflush(stdout);
ya investigare
aquilino escribió:pues si que es necesario en linux fflush(stdout);
ya investigare


Pues yo me volví loco hasta dar con esa línea jajajajaja. Si consigues averiguar algo me avisas que tengo curiosidad ajjajajaja
xXDraklordXx escribió:
aquilino escribió:pues si que es necesario en linux fflush(stdout);
ya investigare


Pues yo me volví loco hasta dar con esa línea jajajajaja. Si consigues averiguar algo me avisas que tengo curiosidad ajjajajaja



me he vuelto loco pero ya esta
He leído esto: ¿Qué es el fflush( stdout )?. Pues bien, cuando usamos la función printf, no escribimos directamente en la pantalla, sino en una memoria intermedia (lo que llaman un bufer). Cuando este bufer se llena o cuando metemos un carácter '\n' es cuando se envía el texto a la pantalla. En este ejemplo yo quería que apareciera el mensaje Introduce una letra: y el cursor se quedara justo después, es decir, sin usar '\n'. Si se hace esto, en algunos compiladores el mensaje no se muestra en pantalla hasta que se pulsa una tecla (probar). Y la función fflush( stdout ) lo que hace es enviar a la pantalla lo que hay en ese bufer.

en resumen si pones un salto de linea = \n O endl; se imprimirán los números uno ha uno

#include <stdio.h> // función printf

#include <unistd.h>// sleep s minúscula


int main() {
     int i;
     for (i=0; i<=10; i++) {
         printf("%i\n", i);
         sleep(1); // en segundos 
         }
     return 0;
}
aquilino escribió:
xXDraklordXx escribió:
aquilino escribió:pues si que es necesario en linux fflush(stdout);
ya investigare


Pues yo me volví loco hasta dar con esa línea jajajajaja. Si consigues averiguar algo me avisas que tengo curiosidad ajjajajaja



me he vuelto loco pero ya esta
He leído esto: ¿Qué es el fflush( stdout )?. Pues bien, cuando usamos la función printf, no escribimos directamente en la pantalla, sino en una memoria intermedia (lo que llaman un bufer). Cuando este bufer se llena o cuando metemos un carácter '\n' es cuando se envía el texto a la pantalla. En este ejemplo yo quería que apareciera el mensaje Introduce una letra: y el cursor se quedara justo después, es decir, sin usar '\n'. Si se hace esto, en algunos compiladores el mensaje no se muestra en pantalla hasta que se pulsa una tecla (probar). Y la función fflush( stdout ) lo que hace es enviar a la pantalla lo que hay en ese bufer.

en resumen si pones un salto de linea = \n O endl; se imprimirán los números uno ha uno

#include <stdio.h> // función printf

#include <unistd.h>// sleep s minúscula


int main() {
     int i;
     for (i=0; i<=10; i++) {
         printf("%i\n", i);
         sleep(1); // en segundos 
         }
     return 0;
}


Pues entonces me surge otra duda, en lugar de '\n' usaba '\r', que es para sustituir la line completa en la que se encuentra el cursor y los números se mostraran sustituyendo al valor anterior, pruébalo si no me entiendes xD. Entonces ¿por qué no se mostraban en pantalla?
Efectivamente, lo que en sistemas Windows es "sleep(...);" en unix se define como "usleep(...);".
Nótese que el 'sleep' de windows es igual que el de unix 'usleep', operan en milisegundos. En cambio el 'sleep' de unix definido en 'unistd' toma el valor en segundos. Esto puede llevar a grandes confusiones.

El tema del carácter de escape '\r'. Lo que \r hace es situar el cursor al inicio de la misma línea. El problema es que como se ha comentado en linux se usa un estándar diferente, POSIX, y este a menos que hagas un retorno de línea, explícito, es decir \n, no manda el buffer a pantalla.
En C existen 3 bufferes: stdin, stdout y stderr. Como sus nombres indican: entrada, salida, error (respectivamente). Si quieres que se muestre en pantalla de forma "forzada" debes usar la función fflush utilizando el buffer adecuado, en el caso de 'printf' el 'stdout'. (stderr no utiliza buffer).
Esto lo habían explicado muy bien ya otros compañeros =P, pero bueno, era para aclarar un poco más jaja

Existe otra alternativa que es deshabilitar el uso del buffer. Ahí tienes que valorar que te sale más a cuenta: Utilizar un buffer implica menos uso de cpu ya que evitas estar actualizando la pantalla constantemente a menos que sea necesario, por otro lado, te fuerza a usar fflush en caso de que no uses nuevas lineas. Para desactivar un buffer tienes las siguiente funciones:
setbuf(stdout, NULL);

o
setvbuf (stdout, NULL, _IONBF, BUFSIZ);

Ambas son correctas y te darán el mismo resultado, los 'printf' serán enviados directamente en pantalla y no serán acumulados en ningún buffer, no siendo necesario el \n para actualizar.


También me gustaría decir que fuerais con cuidado con las fflush (no digo que no la uséis). Cada vez es más parte del 'estandar', pero en realidad la función 'fflush' no viene implementada por el propio lenguaje si no que es dependiente del compilador y la plataforma. En estándar POSIX no debería dar mucha guerra, pero trabajando en, por ejemplo, Windows, podéis encontraros algún día en que algún compilador no os la implemente bien. Ya digo que no es lo más normal, ya que cada vez es más común dicha función, pero más vale prevenir que curar =P


@xXDraklordXx
Perdón que no respondiera tu MP, lo vi pero no tuve tiempo de responder y luego se me olvidó. Ya te he respondido!
blipi escribió:Efectivamente, lo que en sistemas Windows es "sleep(...);" en unix se define como "usleep(...);".
Nótese que el 'sleep' de windows es igual que el de unix 'usleep', operan en milisegundos. En cambio el 'sleep' de unix definido en 'unistd' toma el valor en segundos. Esto puede llevar a grandes confusiones.


usleep usa microsegundos, no milisegundos.
Lord Braham escribió:usleep usa microsegundos, no milisegundos.


Si, totalmente verdad. Se me coló, perdonad, no acostumbro a trabajar en POSIX y se me paso totalmente por alto.

Mis disculpas,
Blipi
Hola blipi.

Hoy comienzo a leer tu tutorial desde cero. No tengo ni idea de programación así que espero adquirir unos conocimientos básicos gracias a tu esfuerzo y dedicación.

Muchas gracias por todo y ya te iré contando que tal me va. :)

Edito: me surge una duda. C, al ser un lenguaje de nivel medio... ¿no sería conveniente aprender antes un lenguaje de bajo nivel o incluso el lenguaje de la máquina?
hola, por lo que he visto este tutorial es bastante más didáctico que muchos libros de programación con los que me tocó estudiar c en su dia, muy recomendable para los principiantes.
saludos.
Haver tengo un dudilla ami me digieron que programa c++ es una mejora del c eso es verdad , son diferente codigos haber que diferencia hay ¿?
Tengo el siguiente código y me gustaría que alguien me ayudase a optimizarlo ya que me he comido demasiado la cabeza sin resultado y, aún sin terminar, es demasiado extenso.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char characters[128];

    printf("Use the next characters to generate the wordlist: ");
    fgets(characters, sizeof(characters), stdin);

    int bits = 0;

    int a;
    int b;
    int c;
    int d;
    int e;
    int f;
    int g;
    int h;
    int i;
    int j;
    int k;
    int l;
    int m;
    int n;
    int o;
    int p;
    int q;
    int r;
    int s;
    int t;
    int u;
    int v;
    int w;
    int x;
    int y;
    int z;

    for (a=0; a<(strlen(characters)-1); a++) {
        printf("%c\n", characters[a]);
        bits+=1;
        for (b=0; b<(strlen(characters)-1); b++) {
            printf("%c%c\n", characters[a], characters[b]);
            bits+=2;
            for (c=0; c<(strlen(characters)-1); c++) {
                printf("%c%c%c\n", characters[a], characters[b], characters[c]);
                bits+=3;
                for (d=0; d<(strlen(characters)-1); d++) {
                    printf("%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d]);
                    bits+=4;
                    for (e=0; e<(strlen(characters)-1); e++) {
                        printf("%c%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d], characters[e]);
                        bits+=5;
                        for (f=0; f<(strlen(characters)-1); f++) {
                            printf("%c%c%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d], characters[e], characters[f]);
                            bits+=6;
                            for (g=0; g<(strlen(characters)-1); g++) {
                                printf("%c%c%c%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d], characters[e], characters[f], characters[g]);
                                bits+=7;
                            }
                        }
                    }
                }
            }
        }
    }

    printf("\n%i bits\n%i bytes\n%i Mb\n%i Gb", bits, bits/8, (bits/8)/1024, ((bits/8)/1024)/1024);

    return 0;
}

Agradezco toda la ayuda que me podais dar. Un saludo!
(mensaje borrado)
Gran tutorial para inciarse, muy recomendable

saludos y gracias!
xXDraklordXx escribió:Tengo el siguiente código y me gustaría que alguien me ayudase a optimizarlo ya que me he comido demasiado la cabeza sin resultado y, aún sin terminar, es demasiado extenso.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char characters[128];

    printf("Use the next characters to generate the wordlist: ");
    fgets(characters, sizeof(characters), stdin);

    int bits = 0;

    int a;
    int b;
    int c;
    int d;
    int e;
    int f;
    int g;
    int h;
    int i;
    int j;
    int k;
    int l;
    int m;
    int n;
    int o;
    int p;
    int q;
    int r;
    int s;
    int t;
    int u;
    int v;
    int w;
    int x;
    int y;
    int z;

    for (a=0; a<(strlen(characters)-1); a++) {
        printf("%c\n", characters[a]);
        bits+=1;
        for (b=0; b<(strlen(characters)-1); b++) {
            printf("%c%c\n", characters[a], characters[b]);
            bits+=2;
            for (c=0; c<(strlen(characters)-1); c++) {
                printf("%c%c%c\n", characters[a], characters[b], characters[c]);
                bits+=3;
                for (d=0; d<(strlen(characters)-1); d++) {
                    printf("%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d]);
                    bits+=4;
                    for (e=0; e<(strlen(characters)-1); e++) {
                        printf("%c%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d], characters[e]);
                        bits+=5;
                        for (f=0; f<(strlen(characters)-1); f++) {
                            printf("%c%c%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d], characters[e], characters[f]);
                            bits+=6;
                            for (g=0; g<(strlen(characters)-1); g++) {
                                printf("%c%c%c%c%c%c%c\n", characters[a], characters[b], characters[c], characters[d], characters[e], characters[f], characters[g]);
                                bits+=7;
                            }
                        }
                    }
                }
            }
        }
    }

    printf("\n%i bits\n%i bytes\n%i Mb\n%i Gb", bits, bits/8, (bits/8)/1024, ((bits/8)/1024)/1024);

    return 0;
}

Agradezco toda la ayuda que me podais dar. Un saludo!


No sé que pretendes hacer exactamente, pero de primeras te diría que te sobran la mitad de variables xD Si utilizas el gcc y pones el comando -Wall te avisará de esas cosas. Otra cosa, creo que donde dices 'bits' quieres decir 'bytes'. Un char ocupa 1 byte. Y si quieres poner megabytes o gigabytes te sugiero que pongas MB o GB, o también puedes poner MiB o GiB.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_WORD_LENGTH 7

void imprime(int l, char characters[], char word[], int *bits) {
    int i, j;
    *bits+=l * (strlen(characters) - 1);
    for (i = 0; i < strlen(characters) - 1; ++i) {
        word[l - 1] = characters[i];
        for (j = 0; j < l; ++j) printf("%c", word[j]);
        printf("\n");
        if (l < MAX_WORD_LENGTH) imprime(l + 1, characters, word, bits);
    }
}

int main() {
    char characters[128];
    char word[MAX_WORD_LENGTH];

    printf("Use the next characters to generate the wordlist: ");
    fgets(characters, sizeof(characters), stdin);

    int bits = 0;

    imprime(1, characters, word, &bits);

    printf("\n%i bits\n%i bytes\n%i Mb\n%i Gb", bits, bits/8, (bits/8)/1024, ((bits/8)/1024)/1024);

    return 0;
}


anyWere escribió:Hola blipi.

Hoy comienzo a leer tu tutorial desde cero. No tengo ni idea de programación así que espero adquirir unos conocimientos básicos gracias a tu esfuerzo y dedicación.

Muchas gracias por todo y ya te iré contando que tal me va. :)

Edito: me surge una duda. C, al ser un lenguaje de nivel medio... ¿no sería conveniente aprender antes un lenguaje de bajo nivel o incluso el lenguaje de la máquina?


No, no es recomendable que aprendas un lenguaje de la máquina(ensamblador más bien) para escribir programas medianamente largos y cuando digo largos digo todos xDD Aprender ensamblador solo te puede llegar a servir para optimizar a saco, hacer cosas concretas que no quieres que toque el compilador, etc. Pero para programar es casi como pedirte que uses 0's y 1's

Robot escribió:Haver tengo un dudilla ami me digieron que programa c++ es una mejora del c eso es verdad , son diferente codigos haber que diferencia hay ¿?


C++ incluye todo lo que tiene C(o casi todo) y añade orientación a objetos que creo yo no es el objetivo de este tutorial. También tiene un lenguaje y librerías más fáciles que C para según que cosas. Además dentro de poco sale C++0x que añadirá más cosas aún. Pero para cosas básicas cualquiera te sirve.
Enhorabuena por el tutorial, es realmente intuitivo y facil. Saludos crack
El tutorial esta muy bien, pero en mi opinion, quizas tendrias que modificar el orden de los apartados, ya que algunos conceptos son mejor aprenderlos en el principio.
Un ejemplo, son las condicionales, pienso que tendrian que estar mas al principio ya que es un concepto bastante importante. Lo mismo ocurre con los bucles.
En cambio los arrays y los punteros mas para el final, es lo mas "dificil" de c++ asi que ponerlo en los primeros puntos es empezar la casa por el tejado.

Por lo demas perfecto! ;)
Shantotto está baneado por "utilizar clon para saltarse baneo temporal"
Bueno, te he cambiado un poquito el orden de salida, no se si es importante para tu aplicación (que creo que es con intenciones de hiena :P).

También te he quitado las lentísimas funciones printf que tienen que decodificar el formato y usamos la write sobre el stream 1 que es el stdout, ya
que tenemos acotada la longitud de salida y le vamos dando formato a nuestra cadena de forma trivial.

He evitado también las indexaciones sobre la cadena de salida, estamos sumando constantes a cada ciclo a la base del string y eso es innecesario.

Quizás tengas que cambiar los \n de la cadena por algo tipo retorno de carro y alimentar linea, pero eso lo puedes hacer tú mismo de manera fácil.

Igual hay algún error de sintaxis, no lo he pasado por ningún compilador.

Por ultimo, en el cálculo del tamaño no sé qué quieres hacer, pero se puede calcular al final dada la longitud de la entrada y no necesitamos ir sumando todo el rato el cálculo del tamaño.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
   char characters[128];
   char *a0, *a1, *a2, *a3, *a4, *a5, *a6;
   char myword[8];
   char *w0, *w1, *w2, *w3, *w4, *w5, *w6, *w7
   unsigned long bytes;
             
   printf("Use the next characters to generate the wordlist: ");
   fgets(characters, sizeof(characters), stdin);

   // Te faltaria eliminar los bytes repetidos para evitar palabras duplicadas
   // Tambien deberias comprobar que al menos hay 7 caracteres distintos
   // Sugerencia: hacer una funcion recursiva hasta l niveles para imprimir diccionarios de longitud l.
           
   myword[7]='\n';
   w0=myword;
   w1=w0+1;
   w2=w1+1;
   w3=w2+1;
   w4=w3+1;
   w5=w4+1;
   w6=w5+1;
   for (a0=characters; *w0=*a0; a0++) {
      for (a1=characters; *w1=*a1; a1++) {
         for (a2=characters; *w2=*a2; a2++) {
            for (a3=characters; *w3=*a3; a3++) {
               for (a4=characters; *w4=*a4; a4++) { 
                  for (a5=characters; *w5=*a5; a5++) {
                     for (a6=characters; *w6=*a6; a6++) write(1, myword, 8);
                     *w6='\n';
                     write(1, myword, 7);
                  }
                  *w5='\n';
                  write(1, myword, 6);
               }
               *w4='\n';
               write(1, myword, 5);
            }
            *w3='\n';
            write(1, myword, 4);
         }
         *w2='\n';
         write(1, myword, 3);
      }
      *w1='\n';
      write(1, myword, 2);
   }
   bytes=strlen(characters)+1;
   bytes=(bytes) + (bytes*bytes) + (bytes*bytes*bytes) + (bytes*bytes*bytes*bytes) + (bytes*bytes*bytes*bytes*bytes) + (bytes*bytes*bytes*bytes*bytes*bytes) + (bytes*bytes*bytes*bytes*bytes*bytes*bytes);
   printf("\n%ul bytes\n%ul MB\n%ul GB", bytes, bytes>>10, bytes>>20);
   return 0;
}
Esta bastante cambiado, entrada por parámetro y tal. La salida no saldrá totalmente ordenada.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void palabra(char word[], char chars[], int k, int len);

int main(int argc, char **argv)
{
  char word[255]; //-Contraseñas de 255 caracteres? - No hombre!
  memset(word, '\0', sizeof(word));
  palabra(word, argv[1], 0, atoi(argv[2]));
  return 0;
}

void palabra(char word[], char chars[], int k, int len)
{
  if (k < len){
    unsigned int i;
    for (i = 0; i < strlen(chars); i++){
      word[k] = chars[i];
      printf ("%s\n", word);
      palabra(word, chars, k+1, len);
    }
    word[k] = '\0';
  }
}


No se si compilará, no lo he probado.
Enhorabuena por el tutorial.

Saludos.
Hola compañeros. Muy bueno el tutorial, estoy empezando con c y me ha ayudado bastante en algunas cosillas. Vengo a pedir ayuda, estoy haciendo una practica sobre concurrencia de procesos y estoy atascado con algunos errores que no me dejan compilar. Si algún alma caritativa puede echarle un vistazo se lo agradeceria un monton.

Es una especie de servidor donde puedes dejar mensajes a usuarios que esten conectados. Hay dos partes, cliente y el servidor.
Este es el cliente:
#include <sys/msg.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sem.h>
#include <signal.h>
#include <time.h>

struct mensaje_1_2 {
   long type;
   char login[8];
};

struct mensaje_3 {
   long type;
   int num;
   char fileName[10];
};

struct user_info {
   char login[8];
};

key_t keyLista;
key_t keySem;

int Id_Cola;
int Id_Semaforo;
int Id_memoria_compartida;

struct user_info *memoria_compartida;

void readMsgFile(char *user);
void writeMsgFile(char *de, char *para, char *msg);
void sem(int index, int op);

void readMsgFile(char *user){ /* Funcion para leer mensajes */
   char line[200];
   FILE *msgFile;
   msgFile = fopen("msg.txt", "r");
   while (fgets(line, 200, msgFile) != NULL){
      char para[16];
      sprintf(para, "Para: %s", user);
      if (strstr(line, para) != NULL){
         printf ("%s\n", line);
      }
   }
}

void writeMsgFile(char *de, char *para, char *msg){ /* Funcion para escribir mensajes */

   /* Calculo la hora actual */

   time_t now = time(0);
   struct tm *tlocal = localtime(&now);
   char stnow [19];
   strftime(stnow, 19, "%d/%m/%y %H:%M:%S", tlocal);

   /* Escribo en el msg.txt */

   FILE *msgFile;
   msgFile = fopen("msg.txt", "a");
   fprintf(msgFile, "[%s] De: %s, Para: %s, Mensaje: %s.\n", stnow, de, para, msg);
   fclose(msgFile);
}

void sem(int index, int op){ /* Función para inicializar los semaforos */

   struct sembuf operacion;

   operacion.sem_num = index;
   operacion.sem_op = op;
   operacion.sem_flg = 0;
   semop(Id_Semaforo, &operacion, 1); /* Inicialmente desbloqueado */

}

int main(int argc, char *argv[]){

   char nombreUsuario[8];
   char otroUsuario[8];
   struct mensaje_1_2 m1;
   m1.type = 1;
   int opcion = 0;
   int i = 0;
   char msg[256];
   struct mensaje_1_2 m2;
   struct mensaje_3 m3;
   m3.type = 3;

    /* Se comprueba que son introducidos los argumentos correctos */

   if (argc != 3){
      printf("Error, numero incorrecto de argumentos.\n");
      exit(0);
   }

   keyLista = ftok(argv[1], atoi(argv[2]));

   Id_Cola = msgget(keyLista, 0777 | IPC_CREAT);

   printf("Introduzca su nombre de usuario, por favor:\n");
   fflush(stdin);
   scanf("%s", nombreUsuario);
   strcpy (m1.login, nombreUsuario);

   msgsnd(Id_Cola, (struct msgbuf *)&m1, sizeof(m1.login), IPC_NOWAIT);

   msgrcv(Id_Cola, (struct msgbuf *)&m3, sizeof(m3.num) + sizeof(m3.fileName), 3, 0);

   keySem = ftok(m3.fileName, m3.num);

   Id_Semaforo = semget(keySem, 2, 0600 | IPC_CREAT);

   /* Inicializar los semaforos a 1 */

   semctl(Id_Semaforo, 0, SETVAL, 1);
   semctl(Id_Semaforo, 1, SETVAL, 1);

   Id_memoria_compartida = shmget (keySem, sizeof(struct user_info)*100, 0777 | IPC_CREAT);

   memoria_compartida = (struct user_info *)shmat(Id_memoria_compartida, (char *)0, 0);

    /* Imprime el menu en pantalla */

   while (opcion != 4){
      printf("ELIJA UNA OPCION DEL MENU.\n");
      printf("1.- MOSTRAR USUARIOS CONECTADOS.\n");
      printf("2.- ENVIAR MENSAJE.\n");
      printf("3.- VER MENSAJES.\n");
      printf("4.- SALIR.\n");
      fflush(stdin);

      scanf("%d", &opcion);

      switch(opcion){
         case 1:
            printf("Los usuarios conectados son los siguientes:\n");
            sem(0, -1); /* Bloqueo sem0 */
            for (i = 0; i < 100; i++){
               if (strcmp(memoria_compartida[i].login, "") != 0){
                  printf( "%d = %s\n",i, memoria_compartida[i].login);
               }
            }
            sem(0, 1); /* Desbloqueo sem0 */
            printf("Fin de lista.\n");
            break;
         case 2:
            printf("Introduzca el destinatario, por favor:\n");
            fflush(stdin);
            scanf("%s", otroUsuario);

            sem(0, -1); /* Bloqueo sem0 para comprobar si el usuario que se ha introducido esta conectado */

            for (i = 0; i < 100; i++){
               if (strcmp(memoria_compartida[i].login, otroUsuario) == 0){
                  printf("El usuario %s esta conectado.\n", otroUsuario);
                  printf("Mensaje: \n");
                  fflush(stdin);
                  scanf("%*c%[^\n]", msg);
                  sem(1, -1); /* Bloqueo sem1 para mandar el mensaje */
                  writeMsgFile(nombreUsuario, otroUsuario, msg);
                  sem(1, 1); /* Desbloqueo sem1*/
                  break;
               }
            }
            sem(0, 1); /* Desbloqueo sem0 */
            break;
         case 3:
            printf("Ver mensajes.\n");
            sem(1, -1); /* Bloqueo sem1 para leer los mensajes */
            readMsgFile(nombreUsuario);
            sem(1, 1); /* Desbloqueo sem1 */
            break;
         case 4:
            m2.type = 2;
            strcpy(m2.login, nombreUsuario);
            msgsnd(Id_Cola, (struct msgbuf*)&m2, sizeof(m2.login), IPC_NOWAIT);
            break;
         default:
                printf("Opción no valida. Vuelva a intentarlo.\n");
      }
   }
   return 0;
   if (Id_memoria_compartida != -1){
      shmdt((char*)memoria_compartida);
   }
}

Este es el servidor:
#include <sys/msg.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/sem.h>

void liberarCola(int sig);
void sem(int index, int op);

key_t claveLista;
key_t claveSemaforos;

int Id_Cola;
int Id_Semaforo;
int Id_memoria_compartida;

struct user_info {
   char login[8];
};
struct user_info *memoria_compartida;

struct mensaje_3 {
   long type;
   int num;
   char fileName[10];
};

struct mensaje_1_2 {
   long type;
   char login[8];
};

void sem(int index, int op) {
   struct sembuf operacion;
   operacion.sem_num = index;
   operacion.sem_op = op;
   operacion.sem_flg = 0;
   semop(Id_Semaforo, &operacion, 1);
}

void liberarCola(int sig){

   if (signal(SIGINT, liberarCola)==SIG_ERR){
      perror("Llamada a SIGNAL erronea..\n");
           exit(-1);
   }

   msgctl(Id_Cola, IPC_RMID, (struct msqid_ds *)NULL);
   shmdt((char *)memoria_compartida);
   shmctl(Id_memoria_compartida, IPC_RMID, (struct shmid_ds *)NULL);
   exit(0);
}

int main(int argc, char *argv[]){
   int i;
   int j = 0;
   int k = 0;
   struct user_info user;
   struct mensaje_1_2 m1;
   struct mensaje_1_2 m2;
   struct mensaje_3 m3;
   struct user_info usAux;      // usuario auxiliar para borrar el login

   if (argc != 5){
      printf("Error, numero incorrecto de argumentos.\n");
      exit(0);
   }

   if (signal(SIGINT, liberarCola)==SIG_ERR){
      perror("Llamada a SIGNAL erronea..\n");
           exit(-1);
   }

   claveLista = ftok(argv[1], atoi(argv[2]));

   if (claveLista == (key_t)-1) {
         printf("Error al generar la clave de acceso a la cola de mensajes.\n");
         return -1;
   }

   Id_Cola = msgget(claveLista, 0777 | IPC_CREAT);
      if (Id_Cola == -1) {
         printf("Error al obtener identificador para la cola mensajes.\n");
         return -1;
      }

   claveSemaforos = ftok(argv[3], atoi(argv[4]));
   if (claveSemaforos == -1) {
            printf("Error al generar la clave de acceso.\n");
            return -1;
      }

   Id_Semaforo = semget(claveSemaforos, 2, 0600 | IPC_CREAT);
   if (Id_Semaforo == -1) {
            printf("Error al crear semaforo.\n");
            return -1;
      }

   semctl(Id_Semaforo, 0, SETVAL, 1);
   semctl(Id_Semaforo, 1, SETVAL, 1);

   Id_memoria_compartida = shmget (claveSemaforos, sizeof(struct user_info)*100, 0777 | IPC_CREAT);

   memoria_compartida = (struct user_info *)shmat(Id_memoria_compartida, (char *)0, 0);

   // inicializo la lista de usuarios en la zona de memoria compartida
   sem(0, -1);
   strcpy (user.login, "");
   for(i = 0; i < 100; i++){
      memoria_compartida[i] = user;
   }
   sem(0, 1);

   // inicializamos el fichero de mensajes.
   sem(1, -1);
   FILE *msgFile;
   msgFile = fopen("msg.txt", "w");
        fclose(msgFile);
   sem(1, 1);

   printf("El servidor comienza a funcionar.\n");

   while (1){

      if (msgrcv(Id_Cola, (struct msgbuf *)&m1, sizeof (m1.login), 1, IPC_NOWAIT) != -1){
         m3.type = 3;
         strcpy(m3.fileName, argv[3]);
         m3.num = atoi(argv[4]);
         msgsnd(Id_Cola, (struct msgbuf *)&m3, sizeof(m3.num) + sizeof(m3.fileName), IPC_NOWAIT);

         //guardamos el login del nuevo usuario en la lista de usuarios.

         sem(0, -1);
         while (j < 100 && (strcmp(memoria_compartida[j].login, "") != 0)) j++; // cuidado!
         strcpy(memoria_compartida[j].login, m1.login);
         sem(0, 1);
      }

      if (msgrcv(Id_Cola, (struct msgbuf *)&m2, sizeof (m2.login), 2, IPC_NOWAIT) != -1){
         sem(0, -1);
         for(k = 0; k < 100; k++){
            if(strcmp(memoria_compartida[k].login, m2.login)==0){
               strcpy(usAux.login, "");
               memoria_compartida[k] =  usAux;
            }

         }
         sem(0, 1);
      }
   }
   return 0;
}

Muchas gracias.
Este es el único mensaje que me da al compilar
cliente.c: En la función ‘main’:
cliente.c:121:4: aviso: declaración implícita de la función ‘shmget’ [-Wimplicit-function-declaration]
cliente.c:123:33: aviso: declaración implícita de la función ‘shmat’ [-Wimplicit-function-declaration]
cliente.c:187:7: aviso: declaración implícita de la función ‘shmdt’ [-Wimplicit-function-declaration]

Idem para el servidor.

Del man de shmget:
SHMGET(3P)                                  POSIX Programmer's Manual                                  SHMGET(3P)

PROLOG
       This manual page is part of the POSIX Programmer's Manual.  The Linux implementation of this interface may
       differ (consult the corresponding Linux manual page for details of Linux behavior), or the  interface  may
       not be implemented on Linux.

NAME
       shmget - get an XSI shared memory segment

SYNOPSIS
       #include <sys/shm.h>

       int shmget(key_t key, size_t size, int shmflg);


Por lo tanto te falta #include <sys/shm.h>
También tienes un parámetro sin usar en la función liberarCola.
Pues es que no lo entiendo porque a mi me salen concretamente 13 errores en sitios donde no deberia. Estoy usando codeblocks y los errores son estos:
Cliente.c:1:21: error: sys/msg.h: No such file or directory
Cliente.c:6:21: error: sys/sem.h: No such file or directory
Cliente.c:9:21: error: sys/shm.h: No such file or directory
Cliente.c:26: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'keyLista'
Cliente.c:27: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'keySem'
Cliente.c: In function 'sem':
Cliente.c:71: error: storage size of 'operacion' isn't known
Cliente.c: In function 'main':
Cliente.c:100: error: 'keyLista' undeclared (first use in this function)
Cliente.c:100: error: (Each undeclared identifier is reported only once
Cliente.c:100: error: for each function it appears in.)
Cliente.c:102: error: 'IPC_CREAT' undeclared (first use in this function)
Cliente.c:109: error: 'IPC_NOWAIT' undeclared (first use in this function)
Cliente.c:113: error: 'keySem' undeclared (first use in this function)
Cliente.c:119: error: 'SETVAL' undeclared (first use in this function)

No se me ocurre nada para solucionar esto.
Creo que esos #includes son solo para Linux, tendrás que buscar os equivalentes para Windows... o pasarte a Linux y dejar de tener problemas.
Juen escribió:Creo que esos #includes son solo para Linux, tendrás que buscar os equivalentes para Windows... o pasarte a Linux y dejar de tener problemas.

Acabo de probar en linux y todo perfecto. Quien me mandaria a mi confiar en windows teniendo ubuntu instalado... XD
Muchisimas gracias por la ayuda. [poraki]
Jur...

Desarchivado para corregir errores en el acceso al hilo.

Un saludo.
Tio que buen curro has hecho aqui! blipi te doy las gracias por que programar nunca fue mi hobby y me estoy enganchando bastante siguiendo tu tutorial.
Muy bueno el tutorial. Enhorabuena crack
Muy interesante y muy bien explicado.

Tienes pensado hacer más, en otros lenguajes por ejemplo?

Saludos
gracias por el tuto, queria empezar pero no sabia como...

PD: Puffff con el video....
muy buen tuto añado a favoritos y empiezo a leer,leer y leer

saludos!
eh_cuidao escribió:muy buen tuto añado a favoritos y empiezo a leer,leer y leer

saludos!


+1! Gracias por el currazo!
Esto es una señora guia, me voy a suscribir ya que me interesa mucho aprender C y he visto revistas y libros pero todos son complejos de entender no son para usuarios que no tengan mucha idea de C para empezar. El tuyo al partir desde 0 es una muy buena herramienta para empezar e interesarse y ya sabiendo algo pues optar por adquirir un libro o buscar guias mas avanzadas para progresar.
Alguien se maneja bien en el tema funciones y procedimientos? La verdad es que hasta ahi llegue, y me gustaría ver si me ayudan en algo,
kyo2009 escribió:Alguien se maneja bien en el tema funciones y procedimientos? La verdad es que hasta ahi llegue, y me gustaría ver si me ayudan en algo,



Tu dí tu problema/duda, nosotros trataremos de ayudarte.
Supongo que algún moderador lee esto, y ojalá alguien en puesto jerárquico más alto del staff.
Me gusta aportar, y que los aportes sean útiles.
Considero que este aporte en esta sección, no es especialmente útil ni consultado.

Me remito:
hilo_encuesta-subforo-quot-diseno-web-2d-3d-programacion-quot_1902000

Me voy el sábado, si antes hubiera algún movimiento o al menos alguien del staff dice algo, mejor que mejor.
¡Gracias por la atención!

PD: Hola Xerpi! ;)
Saludos a todos! Puedo hacer una pregunta sobre una duda que tengo en Java por acá?
Gracias Blipi por el pedazo de tutorial que te has currao. Tengo una duda,no hace falta decir q acabo de empezar (jejejeje ), os pongo una captura de pantalla y mi pregunta es :

¿Por que me da error y me dice que no encuentra el fichero main.exe ?


https://www.dropbox.com/s/x2fz4rbxuiqsya1/resized_imagen.jpg
Aikaryu escribió:Saludos a todos! Puedo hacer una pregunta sobre una duda que tengo en Java por acá?


No creo que sea el sitio adecuado para consultarlo, tienes cientos de foros sobre el tema que probablmente resolveran tu problema mas rapidamente (no controlo java por ahora).

Thepucnic escribió:Gracias Blipi por el pedazo de tutorial que te has currao. Tengo una duda,no hace falta decir q acabo de empezar (jejejeje ), os pongo una captura de pantalla y mi pregunta es :

¿Por que me da error y me dice que no encuentra el fichero main.exe ?


https://www.dropbox.com/s/x2fz4rbxuiqsya1/resized_imagen.jpg


Probablemente esto te este pasando porque a tu compilador le faltan cosas, como el main.exe intenta averiguar que has de descargar que no hayas echo ya. Yo para programar en C utilizo Geany que es muy ligero y cumple perfectamente su cometido, te lo recomiendo.

EDITO: Ahora que me fijo mejor el archivo que estas compilando se llama Main.cpp (que es C++ no C) y Main.exe debe de ser ese mismo archivo compilado, que por lo que sea no existe bien sea porque no has compilado (has ejecutado directamente) o porque el compilador no esta haciendo su trabajo.

Link descarga geany:


Un saludo!
Willyn escribió:
Aikaryu escribió:Saludos a todos! Puedo hacer una pregunta sobre una duda que tengo en Java por acá?


No creo que sea el sitio adecuado para consultarlo, tienes cientos de foros sobre el tema que probablmente resolveran tu problema mas rapidamente (no controlo java por ahora).

Thepucnic escribió:Gracias Blipi por el pedazo de tutorial que te has currao. Tengo una duda,no hace falta decir q acabo de empezar (jejejeje ), os pongo una captura de pantalla y mi pregunta es :

¿Por que me da error y me dice que no encuentra el fichero main.exe ?


https://www.dropbox.com/s/x2fz4rbxuiqsya1/resized_imagen.jpg


Probablemente esto te este pasando porque a tu compilador le faltan cosas, como el main.exe intenta averiguar que has de descargar que no hayas echo ya. Yo para programar en C utilizo Geany que es muy ligero y cumple perfectamente su cometido, te lo recomiendo.

EDITO: Ahora que me fijo mejor el archivo que estas compilando se llama Main.cpp (que es C++ no C) y Main.exe debe de ser ese mismo archivo compilado, que por lo que sea no existe bien sea porque no has compilado (has ejecutado directamente) o porque el compilador no esta haciendo su trabajo.

Link descarga geany:


Un saludo!


Gracias Wiillyn por tu contestación, se agredece. He resuelto el problema. El codigo original es este :

#include <stdio.h>

int main() {
unsigned long hexa1= 0xAABBCCDD;
char texto[100];
sprintf(texto, "0x%x", hexa1);
printf(texto);
getchar();
return 0;

}


Fijaros que el header va entre los caracteres < >. Sustituyendo estos caracteres por " ", se soluciona el cuadro de dialogo con el error.

Agradecería que alguien explicara la diferencia entre utilizar ambos caracteres.

Un saludo.
Si te refieres al #include <stdio.h>, se utilizan <> cuando la libreria que se pretende utilizar esta en la carpeta de sistema donde se alojan las librerias (/usr/include en linux) y cuando quieres usar una libreria que esta en la misma carpeta donde esta el ejecutable se utilizan comillas dobles (#include "stdio.h")

Quiza no encuentra esa libreria y por ello te lanza ese error que aparece al no haberse compilado y por tanto creado el archivo ejecutable pero me parece extraño que utilizando esa sintaxis el compilador no lo reconozca automaticamente, no se.. tampoco tengo mucha experiencia con otros compiladores pero yo cojo el codigo que pones tal cual y me compila bien (warning como que se usa %x y al ser long deberia de ser %lx).
https://www.dropbox.com/s/1fpv483g8gaygos/Captura%20de%20pantalla%20de%202013-08-04%2020%3A42%3A24.png

Un saludo!
ok Willyn. ¿ q tutoriales, libro o PDF estas utilizando o has utilizado para aprender c ?.

un saludo compañero y nuevamente gracias.
Pues empecé con un tutorial que se llamaba "Aprendiendo C en 21 dias" y termine aprendiendo en clase en un ciclo superior, pero hay muchos tutoriales de calidad por la red, la web c.conclase.net esta bastante bien.

Si eres catalan o entiendes el catalan aqui tienes los PDFs de la teoria que nos dieron en clase pero vaya tampoco se profundiza mucho mas de lo que aqui lo ha echo blipi, alguna cosa mas como el tratamiento de ficheros con funciones como fopen/fwrite/fread, entorno grafico con Ncurses y poca cosa mas :
https://www.dropbox.com/s/eaaxmulf3nptma9/TeoriaC.zip

Cualquier duda, ya sabes, asi refresco.. xD

Un saludo!
Hola Willyn. Lamentablemente no hablo catalan aunque entendía un poco ya que trabajé durante unos años en la Terra Alta (Tarragona). Fue una experiencia cojonuda y allí dejé muchos y buenos amigos.
Un saludo para mi colega "Rovira", era su mote, jejejeje.
Willyn yo sigo con este tuto, estoy terminando los pointers.

Un saludo.
Willyn escribió:Pues empecé con un tutorial que se llamaba "Aprendiendo C en 21 dias" y termine aprendiendo en clase en un ciclo superior, pero hay muchos tutoriales de calidad por la red, la web c.conclase.net esta bastante bien.

Si eres catalan o entiendes el catalan aqui tienes los PDFs de la teoria que nos dieron en clase pero vaya tampoco se profundiza mucho mas de lo que aqui lo ha echo blipi, alguna cosa mas como el tratamiento de ficheros con funciones como fopen/fwrite/fread, entorno grafico con Ncurses y poca cosa mas :
https://www.dropbox.com/s/eaaxmulf3nptma9/TeoriaC.zip

Cualquier duda, ya sabes, asi refresco.. xD

Un saludo!


D'on ets??

---

Hace tiempo hice unas clases via IRC de programación, donde se resolvían bastante más dudas (de principiantes) que aquí. Personalmente no tengo los logs, pero si rebuscáis lo suficiente entre la gente de demonhades, quizás los encontráis. Estaban bastante bien.

---

Al tema, me he cansado un poco de EOL y su deferencia a la programación. Si alguien quiere ayuda, el tema aquí (incorrectamente) está. Por mi parte, no voy a responder dudas en este hilo.

Disculpas a todos ya que no es culpa de los usuarios, sino de la administración.
Doncs soc de Tarragona :-P y tu?

Que tiempos del IRC (irc-hispano.NET/.ORG), alli empece con la programacion en mIRC Scripting con apenas 12 años y tras unos 10 años desconectado del mundillo retome los estudios para dedicarme a esto, por suerte gracias a gente como tu es facil encontrar informacion y educarse de forma independiente.

Un saludo!
Por si a alguien le interesa existe un libro muy bueno que fue con el cual logre aprender, se llama Como programar en C de DEITEL( Es facil de conseguir ), es interesante este tema de la programación requiere de mucha paciencia y logica, pero nunca se rindan, yo ahora intento aprender Java saludos y suerte :)
De barcelona ;)

Este no es el foro adecuado para aprender a programar, según postea la staff.
A menos que alguien quiera C específicamente, que tire a C++.
448 respuestas
15, 6, 7, 8, 9