|
102
|
Programación / Programación C/C++ / Re: Archivos en C
|
en: 26 Agosto 2016, 04:59 am
|
1.-Si leo un archivo en binario (por ejemplo un pdf) y lo copio a otro archivo, que guardo como pdf, el documento resulta ilegible. Entiendo que ésto es porque el archivo original tiene un formato determinado, que al copiar bit a bit no se mantiene o que hay que interpretar de algún modo. Imagino la copia (bueno de hecho así la veo cuando la abro con el editor de texto) como una montaña absurda de caracteres descabellados que hay que organizar de algún modo, pero intuyo que es algo bastante complejo. Eso es rotundamente falso. Si abres un archivo en binario, copias byte a byte y lo guardas en otro archivo con la misma extensión, debería ser una copia exacta, y como tal, no debería haber problemas con la copia. Te dejo un código que copia exactamente un archivo a otro: #include <string.h> #include <stdio.h> #define MAX_PATH 4096 int main() { // Puedes poner MAX_PATH como quieras, o saber este valor a través de librerías // no estándares char ruta_entrada[MAX_PATH]; char ruta_salida[MAX_PATH]; FILE *entrada; FILE *salida; char byte; int salir = 0; // Obtenemos rutas fprintf(stdout , "Introduzca la ruta del archivo a copiar: "); fgets(ruta_entrada , MAX_PATH , stdin ); ruta_entrada [strlen(ruta_entrada ) - 1] = '\0'; fprintf(stdout , "Introduzca la ruta del archivo de destino: "); fgets(ruta_salida , MAX_PATH , stdin ); ruta_salida [strlen(ruta_salida ) - 1] = '\0'; // Abrimos archivos entrada = fopen(ruta_entrada , "rb"); if(NULL == entrada) { fprintf(stderr , "Error abriendo archivo de entrada en '%s'\n", ruta_entrada ); return -1; } salida = fopen(ruta_salida , "wb"); if(NULL == salida) { fprintf(stderr , "Error abriendo archivo de salida en '%s'\n", ruta_salida ); return -1; } // Copiando datos while(0 == salir) { fprintf(stderr , "Error leyendo|escribiendo byte\n"); return -1; } } else { salir = 1; } } // Terminando... fprintf(stdout , "La copia de archivos ha finalizado\n"); return 0; }
Evidentemente, esto no es lo más básico, sino que es una forma "muy segura" de copiar archivos (se podrían haber omitido la comprobación de que los archivos existen, los mensajes de error...) Espero que te sea de ayuda. PD.: Probé el código con un PDF, y funcionó perfectamente
|
|
|
104
|
Programación / ASM / [NASM] (Duda) El registro DS no funciona como debería
|
en: 25 Agosto 2016, 03:07 am
|
Hola, muy buenas. Estaba viendo cómo se hacía una unidad de arranque desde ensamblador (NASM), pero tengo problemas con el registro DS. Muestro este código para mostrar mi duda: BITS 16 start: xor ax, ax ; Set data segment to where we're loaded mov ds, ax mov ax, text_string add ax, 7C00h mov si, ax ; Put string position into SI call print_string ; Call our string-printing routine jmp $ ; Jump here - infinite loop! text_string: db 'This is my cool new OS!', 0 print_string: ; Routine: output string in SI to screen mov ah, 0Eh ; int 10h 'print char' function .repeat: lodsb ; Get character from string cmp al, 0 je .done ; If char is zero, end of string int 10h ; Otherwise, print it jmp .repeat .done: ret times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s dw 0xAA55
Es un código sencillito, pero funciona. El problema está en que si hago que el registro DS valga 0x07C0, el ordenador no arranca con esta unidad de arranque, pero si calculo manualmente la dirección de la cadena de texto y hago que DS valga 0, el ordenador si que arranca con esta unidad. Código con el que funciona: BITS 16 start: xor ax, ax ; Lo ponemos como 0 mov ds, ax mov ax, text_string ; Calculo manualmente la dirección de la caedna add ax, 7C00h mov si, ax ; La guardo en SI ...
Código con el que no funciona: BITS 16 start: mov ax 0x07C0 ; Lo ponemos como 0 mov ds, ax mov ax, text_string ; El cálculo debería ser DS * 0x10 + SI, lo que es lo mismo que ; 0x07C0 * 0x10 + SI, lo que es lo mismo que 0x7C00 + SI, que ; a su vez es lo mismo que el cálculo manual antes expuesto mov si, ax ; La guardo en SI ...
O hay algo que se me escapa, o es muy extraño todo... Gracias de antemano!
Vale, me he dado cuenta de que xor limpia parte/todo el registro FLAGS He obtenido el registro con LAHF. Antes de usar xor, LAHF retornaba, en binario, 01000110, y después de usar xor, LAHF retornaba 00000000. He intentado hacer lo siguiente, pero sigue sin funcionar: mov ah, 0x00 SAHF CLC CLD CLTS mov ax, 0x07C0 mov ds, ax
Pero con este código si que funciona (algo hace XOR de lo que no me doy cuenta...): xor ax, ax ; Algo más tiene que hacer XOR, porque aun reemplazando el valor de ax, sin XOR no funciona mov ax, 0x07C0 ; Aquí reemplazamos todo ax mov ds, ax
Espero que me puedan ayudar
|
|
|
105
|
Programación / Programación General / (Consulta) (Bajo nivel) ¿Las variables se guardan en la pila o en el ejecutable?
|
en: 24 Agosto 2016, 23:54 pm
|
Hola, muy buenas, me explico. La pregunta que tengo es dónde se guardan las variables. Yo tenía entendido que se guardan en un especie de bloque de memoria asignado para cada programa llamado 'pila', pero según estoy leyendo por ahí, las variables pueden ser guardadas entre código y código del ejecutable. En ensamblador, por ejemplo, podríamos escribir 'mylabel: db 'Message here', 0' (ejemplo de Internet). En ese espacio del ejecutable, se guarda una serie de bytes que contienen "Message here", por lo que podrías decir que esa memoria está entre código y código, no en la 'pila'
Espero que mi duda se haya entendido, no sabía muy bien como explicarla... ¡Muchas gracias de antemano!
|
|
|
107
|
Programación / Programación C/C++ / Cómo codificar con estilo (broma)
|
en: 24 Agosto 2016, 20:44 pm
|
Si eres como esas personas que codifican sin poner tabulaciones, espacios, deja los códigos super comprimidos y la gente no le gusta tu estilo, ¡¡aquí te traigo la forma de seguir con tu estilo y además de una forma bonita!! #include<stdio.h> int main( ){float rad=0.0f; float peri; float areac =.0f; const float pi_2= 1.5707f;char*areas= "Area";fprintf(stdout ,"Radio: ");scanf("%f", &rad); peri= 4.00f *pi_2 *rad; areac =2.0f *pi_2 *rad* *&rad ;fprintf (stdout, "Perimeter: %f\n",peri);fprintf(stdo\ ut,"%s: %f",areas, areac); return 0;}
Para aquel que se lo pregunte, como si no estuviera claro, este código te pide un radio para calcular su perímetro y área asociado ¡Espero que adoptéis este estilo tan maravilloso de programación!
|
|
|
108
|
Programación / Programación C/C++ / Re: Problema con la derivación de clases c++
|
en: 24 Agosto 2016, 20:28 pm
|
Yo acabo de compilar el código, y hay MUCHIIISIMOS más errores que los que mencionas... Simplemente voy a poner un ejemplo para que no se me tome por mentiroso: C:/MinGW64/mingw64/x86_64-w64-mingw32/include/c++/ostream:574:5: note: templat e argument deduction/substitution failed: clasesvehiculo/vehiculo.cpp:109:52: note: cannot convert 'Vehiculo::mostrarPre cio()' (type 'void') to type 'const unsigned char*' cout << "Precio: " << mostrarPrecio() << endl; ^ Ese error viene de este fragmento: void Vehiculo::mostrarPrecio() { return precio; } [...] void Vehiculo::mostrarVehiculo() { [...] cout << "Precio: " << mostrarPrecio() << endl; }
La función, en teoría, tendría que retornar algo, pero le pusiste que retornara void... Por si quieres la lista completa de errores lanzada por MinGW, aquí la tienes: http://www.mediafire.com/download/lcchftx34bpjhah/log.txtPara que veas la cantidad de errores, el archivo ocupa 211 KB XDD
|
|
|
109
|
Programación / Programación General / Re: No puedo usar acentos ni ñ en Python 2.7.7
|
en: 23 Agosto 2016, 11:43 am
|
El código ASCII como tal solo recoge los primeros 127 caracteres de la tabla, en la cual no están ni la ñ ni las vocales acentuadas. Por lo tanto, en la cabecera de tu programa tendrás que especificar que vas a usar una codificación ASCII extendida, la codificación UTF-8. Aquí tienes lo que tienes que incluir: #!/usr/bin/env python # -*- coding: utf-8 -*-
|
|
|
110
|
Programación / Programación General / Re: Resto de un numero natural de 200 digitos
|
en: 23 Agosto 2016, 06:22 am
|
Aquí dejo un programa que hice en C para un problema de Project Euler. El programa calcula la suma total de los dígitos de factorial de 200 (en realidad, el ejercicio pedía de 100, pero puse 200 para que tuviera más de 200 dígitos). En el programa, para obtener los dígitos, tengo que sacar el módulo, así que funciona correctamente (lo digo porque Project Euler dictaminó que mi respuesta era buena). #include <stdlib.h> #include <stdio.h> typedef struct { unsigned char *bytes; unsigned int num_bytes; } big_int; void set_big_int(big_int *result, unsigned char number); void multiply(big_int *result, unsigned char number); void divide(big_int *result, unsigned char denominator); unsigned char get_module(big_int *result, unsigned char denominator); void factorial(big_int *result, unsigned char number); int is_zero(big_int *big_integer); int main() { big_int big_integer = {NULL, 0}; unsigned char digit; unsigned int num_digits = 0; unsigned int result = 0; fprintf(stdout , "Adding all digits of 200!...\n"); factorial(&big_integer, 200); while(is_zero(&big_integer) == 0) { num_digits++; digit = get_module(&big_integer, 10); fputc(digit + '0', stdout ); result += digit; divide(&big_integer, 10); } fprintf(stdout , "\n\nDigit sum result: %u\n", result ); fprintf(stdout , "Number of digits: %u", num_digits ); return 0; } void set_big_int(big_int *result, unsigned char number) { if(result->bytes != NULL) result ->bytes = malloc(sizeof(unsigned char)); result->bytes[0] = number; result->num_bytes = 1; } void multiply(big_int *result, unsigned char number) { register int i; unsigned int rest = 0; for(i = 0; i < result->num_bytes; i++) { rest = result->bytes[i] * number + rest; result->bytes[i] = rest & 0x000000FF; rest >>= 8; if(rest != 0 && i+1 == result->num_bytes) { result->num_bytes += 1; realloc(result ->bytes , result ->num_bytes ); result->bytes[i+1] = 0; } } } void divide(big_int *result, unsigned char denominator) { register int i; unsigned int module = 0; unsigned int new_size = result->num_bytes; for(i = result->num_bytes-1; i >= 0; i--) { module = (unsigned int)result->bytes[i] + (module << 8); result->bytes[i] = module/denominator; module %= denominator; } for(i = result->num_bytes-1; i >= 0 && result->bytes[i] == 0; i--) new_size--; if(new_size != result->num_bytes) { result->num_bytes = new_size; } } unsigned char get_module(big_int *result, unsigned char denominator) { register int i; unsigned int module = 0; for(i = result->num_bytes-1; i >= 0; i--) module = ((unsigned int)result->bytes[i] + (module << 8))%denominator; return module; } void factorial(big_int *result, unsigned char number) { unsigned char i; set_big_int(result, 1); for(i = 2; i <= number; i++) multiply(result, i); } int is_zero(big_int *big_integer) { register unsigned int i; unsigned int result = 1; for(i = 0; result == 1 && i < big_integer->num_bytes; i++) result = big_integer->bytes[i] == 0; return result; }
Además, le he agregado para que imprima los dígitos en Little Endian, así que la salida del programa para calcular el factorial de 200 sería... 00000000000000000000000000000000000000000000000002747379830732698722222987169785 80071532604230714091306220668659755047521230423093757042424257723584928247221314 68192330452042466154126544229349889693732713367072758264311139928259426629160501 73624209724675203883691983121277140932648911048240302924330436994495344233524749 2362371786779531592260581239312363255305097463768756887
Digit sum result: 1404 Number of digits: 375
|
|
|
|
|
|
|