elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Sigue las noticias más importantes de seguridad informática en el Twitter! de elhacker.NET


  Mostrar Mensajes
Páginas: 1 ... 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [25] 26
241  Programación / Programación C/C++ / Re: Como elevar una potencia en C en: 6 Febrero 2014, 00:29 am
Correcto, y yo añadiría que en lugar de

Código
  1. system("PAUSE");
  2.  

usaras

Código
  1. getchar();
  2.  

pues lo que la gente no sabe es que las órdenes system no son en "C puro", sino que "se salen de C" y hacen una petición por medio del procesador de comandos del sistema operativo. Esto puede hacer que tu programa no sea compatible en otros sistemas (computadores). Prefiere usar:

Código
  1. getchar( );
  2.  

incluido en <stdio.h>, la cual sí es estándar y portable.
242  Programación / Programación C/C++ / Re: ¿a que se debe este error en el codigo? en: 6 Febrero 2014, 00:22 am
Si revisas atentamente el mensaje dado por el compilador verás que dice algo "before if", o sea antes del "if". Y yo creo que a la línea:
Código:
det = pow (b,2)-4*a*c
que va justo antes del if le falta el punto y coma final.

Por otra parte, recuerda que como dijeron antes el tipo por defecto de main en int. No es apropiado declarar main() sin tipo de retorno, debes poner int main().

Y finalmente, no uses system("PAUSE"), de hecho, procura nunca usar system. Rrecuerda que la orden system invoca una llamada al sistema operativo, y como el SO puede cambiar de una máquina a otra, tu programa no será portable. Prefiere siempre el uso de funciones estándares de C, como lo es getchar() que realiza la misma función de esperar que el usuario pulse una tecla, y sí es estándar.

Yoel.
243  Programación / Programación C/C++ / Re: [Duda] Unsigned int y enumeraciones en: 6 Febrero 2014, 00:14 am
Insisto, los enum son agrupaciones de constantes, lo cual significa que una vez declares su valor, NO lo puedes cambiar. Por ejemplo, sea:

Código:
enum {A=3, B, C};

Ya está definido el valor constante de A = 3. Si luego intentas poner por ejemplo:

Código:
A = 5
el compilador arroja un error, en mi caso el compilador gcc de GNU que es acorde a la especificación oficial ISO/IEC 9899:1999, conocida como C99:
Código:
test1.c: In function ‘main’:
test1.c:18: error: lvalue required as left operand of assignment
es decir, que A no es un "lvalue", su valor no se puede cambiar. Así que no la "puedes manipular a tu antojo". Lo que sí puedes es asignar su valor a una variable, algo como
Código:
int x;
x = A;

Recuerden que cuando declaras un identificador constante muchos compiladores (si respetan el estándar) intentarán ubicarlo en una zona de memoria donde su valor no pueda ser modificado.

Ahora, otra cosa es que estés usando algún compilador "flexible" que soporte funcionalidades no estándares, lo cual alienta a prácticas inadecuadas de programación que no serán compatibles con otras plataformas. ¿Sería este el caso?
244  Programación / Programación C/C++ / Re: Error al imprimir caracteres en: 5 Febrero 2014, 04:46 am
Hola José, estuve probando el código y veo que agrega bien la cédula y el precio, pero no el nombre.

El error está en la asignación del campo nombre. Recuerda que para copiar una cadena en otra no se puede simplemente con el operador de asignación (=), sino que debes hacerlo con strcpy, o mejor aún, para prevenir desbordamiento, con strncpy.

La función
Código:
strncpy( char* dest, char *src, size_t n )
copia un máximo de n caracteres de la cadena origen a la cadena destino. y luego debes agregar manualmente el nulo de terminación. En el código de la función Insertar, la línea:

Código:
nuevo->nombre[20] = no[20];

debe reemplazarse por

Código:
strncpy( nuevo->nombre, no, 20);
(nuevo->nombre)[20] = '\0';

donde los paréntesis en (nuevo->nombre) son necesarios puesto que el operador "[]" tiene mayor precedencia que el de acceso de miembro "->". Con ésto ya tu programa debe quedar bien :)

===================
Por cierto, recomiendo poner un getchar() al final de Imprimir, de manera que la lista permanezca impresa en pantalla hasta que el usuario presione una tecla.
También recuerda que getch() no es una función estándar de C, sino que funciona principalmente en compiladores de C para Windows. Usa getchar().
245  Programación / Programación C/C++ / Re: problemas con fseeks en: 5 Febrero 2014, 03:49 am
Ok, ahora vamos a poner todo junto, a mí me salió en apenas 89 líneas de código. Y creé un fichero de texto de prueba con el mismo contenido que tú dices, y me imprimió la tabla perfecta ;D

Es cuestión de ser hábil combinando las cosas, así puedes lograr mucho con poco ... Bueno, espero te sirva, aquí tienes el fuente completo con el main() y todo, sólo de copiar, pegar, compilar y probar.

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. #define CR 10
  5. #define LF 13
  6.  
  7. typedef enum {INS, OP, DIR, MAQ, CALCULADO, CALCULAR, TOTAL} tabla;
  8.  
  9. void readLine ( FILE *, char * );
  10. char * readField( char ** );
  11.  
  12. int main()
  13. {
  14. char * buffer, * old_buffer;
  15. char * field;
  16. FILE * hc12;
  17.  
  18. if ( ( buffer = (char *) malloc( 101 * sizeof(char) ) ) == NULL ) return -1;
  19. if ( ( field = (char *) malloc( 101 * sizeof(char) ) ) == NULL ) return -1;
  20.  
  21. if ( ( hc12 = fopen( "file1.txt", "r") ) == NULL ) return -1;
  22.  
  23. while ( !feof( hc12) ) {
  24. readLine( hc12, buffer);
  25. old_buffer = buffer;
  26. while ( ( field = readField( &buffer ) ) != NULL ) {
  27. printf("%s\t", field);
  28. }
  29. printf("\n");
  30. buffer = old_buffer;
  31. }
  32.  
  33. fclose( hc12 );
  34.  
  35. return 0;
  36. }
  37.  
  38. void readLine ( FILE *hc12, char *buffer ) {
  39.  
  40. char c;
  41. int i;
  42.  
  43. i = 0;
  44. while ( !feof(hc12) && (c = fgetc(hc12)) != CR && c != LF )  
  45. buffer[i++] = c;
  46.  
  47. buffer[i] = '\0';
  48.  
  49. /* avanzamos hasta que no haya CR ni LF */
  50. while ( ( c = fgetc(hc12) ) == CR || c == LF )
  51. ;
  52. /* devolvemos el último carácter leído */
  53. if ( !feof(hc12) ) ungetc(c, hc12);
  54. }
  55.  
  56. /* Lee un campo del búfer, considerando un campo como toda sucesión de
  57.    caracteres de no espacio. Devuelve NULL si no hay más campos que leer */
  58. char * readField( char ** buffer_ptr ) {
  59.  
  60. int i;
  61. char c;
  62. char * buffer = *buffer_ptr;
  63.  
  64. if ( *buffer == '\0' ) return NULL;
  65.  
  66. /* elimina los espacios iniciales */
  67. while ( *buffer == ' ' || *buffer == '\t' )
  68. buffer++;
  69.  
  70. /* ahora toma la porción inicial de la cadena hasta encontrar
  71.   espacio o tabulador */
  72. i = 0;
  73. while ( (c = buffer[i]) != '\0' && c != ' ' && c != '\t' )
  74. i++;
  75.  
  76. /* finaliza la sub-cadena donde halló el carácter espacio o tabulador */
  77. buffer[i] = '\0';
  78.  
  79. /* y si hay más sub-cadenas que leer, avanza el búfer */
  80. if ( c != '\0' )
  81. *buffer_ptr = buffer + i + 1;
  82. else
  83. *buffer_ptr = buffer + i;
  84.  
  85. if ( i > 0 )
  86. return buffer; /* leyó al menos un carácter */
  87. else
  88. return NULL; /* no leyó nada */
  89. }
  90.  

Pruébalo y me dices!!

==========================================
Por cierto y aparte, noté que tienes en el código original una sentencia que no entiendo bien:
Código
  1. dir = (char**)malloc(sizeof(char*));
  2. dir[i] = Tabla_Operandos(hc12,DIR);
  3.  
Ok, ve. Con el malloc defines un arreglo dir de UN único elemento del tipo puntero a char, que luego rellenas con el string que produce la función Tabla_Operandos. Ahora, dos preguntas: ¿Dónde reservas el espacio de la memoria para los restantes elementos del arreglo dir, aparte del primero?
Además, si dir contendrá un string, ¿dónde reservas la memoria para dicho arreglo de caracteres? Eso tiene que hacerse de la siguiente manera:

Código
  1. /* Reservando el arreglo dir como arreglo de cadenas */
  2. / *  (dir_length es la longitud que esperas para dir ) */
  3. dir = (char **) malloc( dir_length * sizeof (char *) );
  4.  
  5. /* ahora se reserva memoria para cada string dentro del arreglo */
  6. for ( i = 0; i < dir_length; i++ )
  7.    dir[i] = (char *) malloc( s_length * sizeof(char) );
  8. /* donde s_length es la longitud deseada para cada string */
  9.  

De hecho, no se cómo el programa no te produjo un error de "violación de segmento" en tiempo de ejecución ... :o

De, hecho, cada vez que se usa malloc uno tiene que comprobar si la asignación de memoria se produjo con éxito (casi siempre así sucede, pero no se puede dar por sentado). Si no se pudo asignar memoria, se debe salir del programa:

Código
  1. /* Reservando el arreglo dir como arreglo de cadenas */
  2. / *  (dir_length es la longitud que esperas para dir ) */
  3. dir = (char **) malloc( dir_length * sizeof (char *) );
  4. if ( dir == NULL ) return -1;
  5.  
  6. /* ahora se reserva memoria para cada string dentro del arreglo */
  7. for ( i = 0; i < dir_length; i++ ) {
  8.    dir[i] = (char *) malloc( s_length * sizeof(char) );
  9.    if ( dir[i] == NULL ) return -1;
  10. }
  11.  
y esto te evitará cualquier "comportamiento inesperado" del programa, para que no te pase como a Windows que se cuelga a cada rato jeje.

Saludos, y quedo a la orden para cualquier cosa .... Yoel

246  Programación / Programación C/C++ / Re: problemas con fseeks en: 5 Febrero 2014, 03:34 am
Continuando con el tema, ahora queremos una función que tome un búfer de línea del archivo, y sepa encontrar los distintos campos separados por espacios. Aquí la tienes, su código es breve pero maneja unos conceptos un poquito complicados de apuntadores, como por ejemplo el apuntador pasado por referencia o puntero-a-puntero del tipo char **. Si no lo entiendes me lo preguntas luego y te lo explico bien.:

Código
  1. /* Lee un campo del búfer, considerando un campo como toda sucesión de
  2.    caracteres de no espacio. Devuelve NULL si no hay más campos que leer */
  3. char * readField( char ** buffer_ptr ) {
  4.  
  5. int i;
  6. char c;
  7. char * buffer = *buffer_ptr;
  8.  
  9. if ( *buffer == '\0' ) return NULL;
  10.  
  11. /* elimina los espacios iniciales */
  12. while ( *buffer == ' ' || *buffer == '\t' )
  13. buffer++;
  14.  
  15. /* ahora toma la porción inicial de la cadena hasta encontrar
  16.   espacio o tabulador */
  17. i = 0;
  18. while ( (c = buffer[i]) != '\0' && c != ' ' && c != '\t' )
  19. i++;
  20.  
  21. /* finaliza la sub-cadena donde halló el carácter espacio o tabulador */
  22. buffer[i] = '\0';
  23.  
  24. /* y si hay más sub-cadenas que leer, avanza el búfer */
  25. if ( c != '\0' )
  26. *buffer_ptr = buffer + i + 1;
  27. else
  28. *buffer_ptr = buffer + i;
  29.  
  30. if ( i > 0 )
  31. return buffer; /* leyó al menos un carácter */
  32. else
  33. return NULL; /* no leyó nada */
  34. }
  35.  
247  Programación / Programación C/C++ / Re: problemas con fseeks en: 5 Febrero 2014, 01:57 am
Bueno x64Core particularmente no soy partidario de usar depuradores o cosas por es estilo, prefiero ir "a manita limpia", y me ha funcionado bien porque así ejercitas más el cerebro, jeje :laugh:

El problema al parecer es que te mueves para adelante y para atrás en el archivo, abusando de fseek. Un buen programador debe ser cauto, debe simplemente evitar andar por terrenos peligrosos, y el estilo de tu programación está siendo definitivamente muy vulnerable. Cualquier error o descuido y tienes un comportamiento completamente impredecible.

Usa el principio de "divide y vencerás". Ve, hazlo así. Coje una línea del archivo txt, y la pasas a una función que analice sintácticamente para detectar sus divisiones en columnas con el carácter tabulador, es decir, lo que hace tablaOperandos. Pero que tablaOperandos y listaTABOP NO SE MUEVAN juntas por el mismo archivo. Eso NUNCA se hace, cada función debe tener su espacio de trabajo "privado". ¿Entiendes la filosofía subyacente?

Entonces, vamos a hacer una función que vaya cogiendo una línea del archivo, y la copie a un arreglo tipo búfer, y se la pase a tablaOperandos, así esta última lee del búfer y no se mete para nada con el archivo original (reduciendo el riesgo de conflictos).

En tu código original tenías un problema porque tablaOperandos al leer la línea avanzaba el indicador de posición de archivo, luego tenías que devolverlo a su posición original con [ttfseek[/tt], etc ....  muy engorroso. Con esta solución no tienes que hacer nada de eso:

Código:

#define CR 13
#define LF 10

void readLine ( FILE* hc12, char *buffer ) {

cchar c;
int i;

i = 0;
while ( !feof(hc12) && (c = fgetc(hc12)) != CR && c != LF )  
buffer[i++] = c;

buffer[i] = '\0';

/* avanzamos hasta que no haya CR ni LF */
while ( ( c = fgetc(hc12) ) == CR || c == LF )
;
/* devolvemos el último carácter leído */
if ( !feof(hc12) ) ungetc(c, hc12);
}

y listo, agarras ese buffer y se lo pasas a tablaOperandos. Claro, antes debes haber definido el buffer como un arreglo con la suficiente longitud para contener cualquier posible línea del archivo (no se, 100 caracteres quizás). Ahora acomoda tablaOperandos para que trabaje sobre un arreglo y no sobre un fichero.

Te explico la última parte del código antes mostrado. En ficheros de texto el fin de línea se hace con una sucesión de dos caracteres, generalmente el <i>carriage return</i> CR seguido de <i>linefeed</i> LF. Entonces, si alcanzas digamos el CR, pues cierras el búfer. Pero al invocar el nuevo la función, leerá el LF y cerrará el búfer ... ¡vacío! O sea, que después de una llamada exitosa a readLinea la próxima llamada que ejecutes devolverá un búfer vacío. Para evitar eso, se bede avanzar el indicador de posición de archivo hasta no encontrar ni CR ni LF, luego de cerrar el búfer de línea. Es lo que hace el:

Código:
	/* avanzamos hasta que no haya CR ni LF */
while ( ( c = fgetc(hc12) ) == CR || c == LF )
;
/* devolvemos el último carácter leído */
if ( !feof(hc12) ) ungetc(c, hc12);

Te voy a explicar algo, el uso de ungetc(). Supón que tienes un fichero así:

Código:
Pedro
Maria

entonces empieza a leer la línea Pedro, hasta que haya la secuencia CR + LF. Primero lee CR, entonces sabe que debe continuar hasta que no haya ni CR ni LF. Así leee CR, luego LF, luego la M inicial de "Maria". Ahí sabe que se terminó la primera línea. Pero hemos agarrado la 'M', luego tenemos que "devolverla" al fichero, por eso usamos ungetc. Es algo parecido a lo que hacías con fseek( hc12, -1, SEEK_CUR ).
    
248  Programación / Programación C/C++ / Re: Duda Constructores C++ en: 5 Febrero 2014, 00:35 am
Escucha, no, no se sobrescriben los valores (los diseñadores del lenguaje C++ no fueron tan tontos, jeje  :rolleyes:)

Cada objeto o "instancia" de una clase tiene su espacio privado de variables, es decir, su porción específica e INDIVIDUAL de memoria asignada a sí mismo dentro del programa. Si creas dos objetos:

Código:
LibroCalificaciones oLibroCalificaciones1 (string_1);
LibroCalificaciones oLibroCalificaciones2 (string_2);

pues cada uno tiene su propia variable nombreCurso, independiente de la del otro objeto. Puede asignar un valor al nombreCurso del primer objeto, y otro valor al nombreCurso del segundo objeto, sin ningún problema.

Espero haberte aclarado .... :)
249  Programación / Programación C/C++ / Re: Como instalar programa en C en: 5 Febrero 2014, 00:27 am
Hola Hacklink,

Me parece excelente la iniciativa de crear un programa auto-instalable. Ahora, no entiendo bien si me dices cuando hablas de "root" (lo que me hace pensar en UNIX), y por otra parte das a entender que lo instalarás en Windows (por la extensión .exe por ejemplo). En Windows no existe usuario root, por lo que no tienes que preocuparte por ese problema.

En cuanto a conocer el nombre particular del usuario, en los Sistemas Operativos existe algo llamado "variables de entorno". Son como nombres nombres simbólicos que se "expanden" o reemplazan por el procesador de comandos (el símbolo de sistema de Windows) por el valor apropiado. Para ver una lista de todas las variables de entorno en Windows escribe el comando "set" en la cónsola.

El nombre que identifica al usuario actual si mal no recuerdo (revisa, porque podría estar recordando mal) es USERNAME . Para obtener si valor debes escribir entre signos de porcentaje así:

Código:
echo %USERNAME%

y te debe imprimir (en la consola) el nombre de usuario actual. Entonces, para C deberías recuperar el valor de esta variable mediante una solicitud al SO con el comando system. Debe ser algo más o menos como:

Código:
;
char username[100];

char cad[100]="copy ";
char path[100];
getcwd(path,255);
strcat(cad,path);

/* aquí pones el nombre el usuario */
strcpy( username, system("echo %USERNAME%") );
strcat(cad,"\\miprograma.exe C:\\Users\\%s", username);

/* luego ejecutas el copy */
system(cad);

Bueno, espero haber aclarado tu duda, y cualquier cosa comenta o pregunta :)

Por cierto, ¿sabes lo que son scripts de batch para Windows? Se utilizan para automatizar tareas que requieren del SO, y en mi opinión creo que son preferibles a códigos de C porque pueden llamar a órdenes directas de la consola de comandos ....

===============
P.D. Por favor coméntame sobre tu avance en este proyecto que me parece muy interesante ...
250  Programación / Programación C/C++ / Re: [Duda] Unsigned int y enumeraciones en: 5 Febrero 2014, 00:13 am
Respondo: Según el libro Deitel&Deitel "Como programar en C/C++", una enumeración es un conjunto de constantes numéricas enteras, representadas por ciertos nombres o identificadores. O sea, una enumeración es como un arreglos de CONSTANTES. Dice además que el valor de cada constante de enumeración puede ser definido explícitamente durante su declaración. Ejemplo:

enum letras {A = 1, B = 3, C = 8};

Ahora, si son "constantes" su valor no se puede cambiar una vez declarado. Entonces ¿cómo lo vas a cambiar? Cualquier instrucción de asignación de un valor luego de la declaración de la enumeración sería ilegal. Yo creo que no puedes. De hecho, estuve probándolo y el compilador me da un error en cuanto intento asignar un valor a alguna de las constantes fuera de la declaración del enum.

Si quieres poder cambiar los valores a los campos debes usar otro tipo de dato, como un struct por ejemplo.
Páginas: 1 ... 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [25] 26
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines