HackPR.NET

Webmasters => Programación General => Topic started by: el_mejor_demolidor on September 09, 2005, 11:21:26 PM

Title: programacion C/C++
Post by: el_mejor_demolidor on September 09, 2005, 11:21:26 PM
Esta mensage és una especie de mini-FAQ con los errores más comunes o las preguntas más frecuentes que se dan al empezar a pogramar  C o C++
Si quereis proponer algun añadido al FAQ ponedlo en este hilo.

PREGUNTAS Y ERRORES MÁS FRECUENTES

1.- Valores de retorno y parámetros de la función main()

Según el estándar, la función main sólo tiene un posible valor de retorno: int. Ni void, ni un valor indeterminado (es decir, no poner nada) ni ningún otro.
Si te fastidia tener que escribir un return al final de la ejecución de la función main(), te alegrará saber que, al menos en C++, no es necesario escribir una instrucción return de forma explícita, ya que el compilador asume por defecto un return 0, que se considera que la ejecución ha finalizado correctamente.
Por el momento no tengo información acerca de lo que dice el estándar de C, así que si quieres estár seguro de que sigues el estándar tendrás que poner un return 0 en la función main() (venga, que no son tantos caracteres)
Adicionalmente los únicos parámetros estándar a la función main son, o bien ninguno: int main () {} (para los programadores de C, no hay que poner void) o bien: int main (int argc, char * argv[]) {}

En este link está la opinión de Bjarne Stroustrup - creador del lenguaje C++ - al respecto: http://www.research.att.com/~bs/bs_faq2.html#void-main



2.- Uso de la biblioteca conio.h

La biblioteca conio.h no es estándar sino que es propiedad de Borland, y está incluida en sus compiladores. Es una biblioteca de manejo de entrada y salida de datos en la consola para el sistema DOS. Que no sea estandar significa que no la encontrarás implementada -o al menos totalmente- en muchos compiladores, y más importante, en otros sistemas, lo que reduce la portabilidad de tu código. Por otro lado la biblioteca se considera obsoleta, y es posible que algunas de las funciones que incluye no funcionen o lo hagan incorrectamente.
Pero lo más importante es darse cuenta de que esta biblioteca no es estrictamente necesaria para programar. Por experiencia las funciones más usadas de esta biblioteca son, con diferencia, clrscr() gotoxy() y getch().
clrscr() borra la pantalla, algo que por lo general no es necesario; si estás ejecutando un programa en línea de comandos es fácil y rápido teclear un comando (cls, clear) que borre la pantalla en cuestión si lo necesitas. Por contra puede que sea molesto que un programa tome la iniciativa y borre la pantalla, ya que quizá tenga datos que el usuario quiera conservar. Es decir que no pasa nada si no borras la pantalla. Normalmente la persona que usa un programa de línea de comandos no espera que eso ocurra.
gotoxy() el cursor en una determinada posición de la pantalla. Esto puede resultar útil en ocasiones, pero seamos sinceros: no suele ser muy necesario mover el cursor por la pantalla, o al menos no extrictamente necesario. Por ejemplo si estás aprendiendo a programar, eso es completamente supérfluo. Si programas una aplicación avanzada es casi seguro que tendrá un interface Gráfico. En último caso, si estás programando una aplicación avanzada en consola, prosiblemente a esas alturas ya sabrás cómo hacer tú mismo esta función utilizando llamadas al sistema, lo que tiene el beneficio de que puedes encapsular esa función de cara a la portabilidad, en vez de confiar en una función de biblioteca dependiente del sistema.

getch() recoge un carácter de la entrada estándar. Para eso tienes cerca de miles de funciones estándar que lo hacen. Vale, quizá no tantas, pero tienes al menos una en C getchar() y otra en C++  std::cin.get() ¿Porque usar getch() que NO es estándar cuando puedes usar una función estándar que hace exactamente lo mismo?
Antes de que me llameis mentiroso, hay que reconocer que getch() no hace exactamente lo mismo que las otras dos funciones. getch() NO presenta el caracter capturado por la pantalla y la entrada es sin buffer (lo que viene a decir que no hace falta pulsar enter) Sin embargo no creo que eso por lo general sea un grave problema, es más, una entrada sin buffer puede ser incluso un problema: no puedes corregir la entrada si te equivocas.


3.- ¿Cómo aprendo a programar en C/C++?

Aquí tienes dos buenos manuales, uno para C:
http://mec21.etsii.upm.es/ayudainf/aprendainf/AnsiC/leng_c.pdf

y otro para C++.
http://mec21.etsii.upm.es/ayudainf/aprendainf/Cpp/manualcpp.pdf



4.- ¿Y qué hago para programar?

Para poder llevar a la práctica lo que aprendas necesitarás un editor para escribir el código, como puede ser el bloc de notas o emacs. Un compilador para construir los ejecutables. Si además quieres depurar tus programas necesitarás un depurador. A menudo el editor, el compilador y el depurador vienen en un sólo programa conocido como Entorno de Desarrollo Integrado o IDE (Integrated Development Environment)


5.- Quiero un IDE ¿qué IDE puedo usar?
Deberías haber mirado el tema pegado en el que puedes encontrar entornos de programación y compiladores para todos los lenguajes, pero ya que no lo has hecho puedes descargar el dev cpp de la siguiente página:

http://www.bloodshed.net/devcpp.html

Tienes además un manual de instalación y primeros pasos con dev cpp hecho por el mismísimo Zheo en:

http://www.hispabyte.com/biblioteca/index.php?action=file&id=319

Editado: No hace falta aprender C para saber C++ (de hecho puede crear malos vicios)Por otro lado IDE estaba bien escrito









Errores Comunes:

*Olvidarse poner el & referenciando un lugar de memoria:


Código:
...
//Mal
           scanf ("%d", numero);

//Bien
           scanf ("%d", &numero);
...


*No Abrir/Cerrar correctamente Parentesis:


Código:
//MAL !!

Void main ()
{
...         
           for (...)
           {
                         ....
                          while (...)
                          {
                                    ....
}} //dos parentesis, falta uno de cierre !!!


//Bien 

Void main ()
{
...         
           for (...)
           {
                         ....
                          while (...)
                          {
                                    ....
                           }
           }
}


Si se tiene una indentación adecuada, no surgen este tipo de error.


*Mal uso de operadores:
Un ejemplo tipico es usar el operador unario ++ en cualquier lado y no poner bien los parentesis.


Código:
si a =1, b = 4, c = 5 -->

resultado = a + b / --c;    //Total --> 2

resultado = (a + b) / (c - 1);    //Total --> 5/4 > 2

Hay que saber bien las Precedencias de los operadores. Y poner   parentesis es un segundo de vida que les cuesta, pero es un minuto ganado en cuando a la legibilidad del programa.
Title: Re: programación C/C++
Post by: el_mejor_demolidor on September 09, 2005, 11:21:55 PM
                       Crear un escaner

Este enlace, contiene el código fuente de una utilidad PING codeada en C++, héchale un ojo, parece muy interesante.
http://www.el-lolo.net/codigo/ping.zip (http://www.el-lolo.net/codigo/ping.zip)
Title: Re: programación C/C++
Post by: el_mejor_demolidor on September 09, 2005, 11:22:28 PM
Bueno, aquí os pongo un source que hice para manejar parte de los procesos.

Concretamente, puede listarlos junto con el pid de cada uno, cerrarlos por su pid/nombre, obtener información, y obtener el pid a partir del nombre.


Código:
/*

-------------------------------------------------------------------------------------
|| Name: Process Administration Tool 1.0                                                        ||
|| Description: Programa para listar procesos, matar procesos por id/nombre,       ||
||     obtener información sobre un proceso determinado, y obtener el PID         ||
||              a través del nombre del Módulo.                                                  ||
|| Autor: el_mejor_demolidor                                                                      ||
||                                                                                                            ||
||                                                                                                            ||
||                                                                                                            ||
-------------------------------------------------------------------------------------


D:\>Process.Administration.Tool.1.0.exe

  Process Administrator Tool 1.0 - Coded by el_mejor_demolidor
----------------------------------------------------

[!] Argumentos incorrectos

Opciones:
    + Listar procesos:                -l
    + Cerrar proceso mediante PID:    -kpid pid
    + Cerrar proceso mediante nombre: -kname nombre
    + Informacion sobre un proceso:   -i pid
    + Buscar PID:                     -pid nombre

D:\>
*/
#include <stdio.h>//I/O
#include <windows.h>//Para usar con Tlhelp32.h
#include <Tlhelp32.h>//CreateToolhelp32Snapshot, Process32First, Process32Next,PROCESSENTRY32
#include <string.h>//strlen

/*CIERRA UN PROCESO MEDIANTE SU PID*/
int CierraPID(DWORD pid);
/*devuelde la descripción del error, a partir de su código*/
char *MensajeError(DWORD error_num);

void main(int argc, char *argv[])
{
/*LISTA LOS PROCESOS ACTUALES*/
int ListarProcesos();
/*BUSCA EL PID DE UN PROCESO*/
int BuscaPid(char *nombre);
/*DA INFORMACION SOBRE UN PROCESO*/
int InfoProc(DWORD pid);
//para cojer la salida de algunas funciones
int datos;

printf("\n  Process Administrator Tool 1.0 - Coded by Lympex");
printf("\nContact: lympex[at]gmail[dot]com & http://l-bytes.tk");
printf("\n----------------------------------------------------\n");

if(argc<=1)
{
printf("\n[!] Argumentos incorrectos");
printf("\n
Opciones:");
printf("\n    + Listar procesos:                -l");
printf("\n    + Cerrar proceso mediante PID:    -kpid pid");
printf("\n    + Cerrar proceso mediante nombre: -kname nombre");
printf("\n    + Informacion sobre un proceso:   -i pid");
printf("\n    + Buscar PID:                     -pid nombre\n");
return;
}

//LISTAMOS LOS PROCESOS
if(!strcmp(argv[1],"-l"))
{
printf("\nPROCESO                       PID");printf("\n---------------------------------\n");ListarProcesos();
printf("\n");
return;
}

//CERRAR PROCESO MEDIANTE PID
if(!strcmp(argv[1],"-kpid"))
{
if(argc<2)
{
printf("\n[!] Debes indicar un PID\n");
}else{
CierraPID(atoi(argv[2]));
}
return;
}

//CERRAR PROCESO SEGÚN EL NOMBRE
if(!strcmp(argv[1],"-kname"))
{
if(argc<2)
{
printf("\n[!] Debes indicar un PID\n");
}else{
datos=BuscaPid(argv[2]);
if(datos!=-1)
{
CierraPID(datos);
}else{
printf("\n[!] No existe el proceso \x22%s\x22\n",argv[2]);
}
}
return;
}

//DA INFORMACIÃ"N SOBRE UN PROCESO
if(!strcmp(argv[1],"-i"))
{
if(argc<2)
{
printf("\n[!] Debes indicar un PID\n");
}else{
InfoProc(atoi(argv[2]));
}
return;
}

//CERRAR PROCESO SEGÚN EL NOMBRE
if(!strcmp(argv[1],"-pid"))
{
if(argc<2)
{
printf("\n[!] Debes indicar un PID\n");
}else{
datos=BuscaPid(argv[2]);
if(datos!=-1)
{
printf("\n
PID de \x22%s\x22 --> %d\n",argv[2],datos);
}else{
printf("\n[!] No existe el proceso \x22%s\x22\n",argv[2]);
}
}
return;
}

printf("\n[!] Argumentos incorrectos\n");
}

/*LISTA LOS PROCESOS ACTUALES*/
int ListarProcesos()
{
char *mid(char *str1, unsigned int inicio, unsigned int fin);
/*cargamos todos los procesos*/
HANDLE proc=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
/*para almacenar los datos de cada proceso*/
PROCESSENTRY32 datos;
/*para almacenar el código del error*/
int errorn;
/*para bucles*/
unsigned int i;

/*miramos si el handle se ha creado*/
if(proc==INVALID_HANDLE_VALUE)
{
printf("\n[!] Error al crear el handle\n");
return 1;
}

Process32First(proc,&datos);
printf("\n%s",datos.szExeFile);
/*creamos un bucle cada vez que tenemos que mostrar un proceso, para saber cuántos espacios tenemos que colocar,
para mostrar los pid´s alineados*/
for(i=0;i<30-strlen(datos.szExeFile);i++)
{
printf("_");
}printf("%d",datos.th32ProcessID);

for(;
{
Process32Next(proc,&datos);

errorn=GetLastError();
if(errorn>0)
{
if(errorn!=ERROR_NO_MORE_FILES)
{
printf("\n[!] Error %d - %s",errorn,MensajeError(errorn));
}
return 0;
}

if(strlen(datos.szExeFile)>=26)
{
printf("\n%s",mid(datos.szExeFile,0,26));
}else{
printf("\n%s",datos.szExeFile);
}

/*creamos un bucle cada vez que tenemos que mostrar un proceso, para saber cuántos espacios tenemos que colocar,
para mostrar los pid´s alineados*/
if(strlen(datos.szExeFile)>=26)
{
for(i=0;i<4;i++)
{
printf("_");
}printf("%d",datos.th32ProcessID);
}else{
for(i=0;i<30-strlen(datos.szExeFile);i++)
{
printf("_");
}printf("%d",datos.th32ProcessID);
}
}

CloseHandle(proc);
return 0;
}

//CIERRA UN PROCESO MEDIANTE SU PID
int CierraPID(DWORD pid)
{
//handle para manejar el proceso
HANDLE proceso;

//abrimos el proceso
if((proceso=OpenProcess(PROCESS_TERMINATE,FALSE,pid))==NULL)
{
//lo anunciamos
printf("\n[!] Error al abrir el proceso con PID=%d # %s",pid,MensajeError(GetLastError()));
return 1;
}

//cerramos el proceso
if(TerminateProcess(proceso,0)==TRUE)
{
printf("\n
Proceso cerrado!\n");
}else{
printf("\n
Error al cerrar el proceso # %s\n",MensajeError(GetLastError()));
}

CloseHandle(proceso);
return 0;
}

/*BUSCA EL PID DE UN PROCESO*/
int BuscaPid(char *nombre)
{
/*cargamos todos los procesos*/
HANDLE proc=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
/*para almacenar los datos de cada proceso*/
PROCESSENTRY32 datos;
/*para almacenar el código del error*/
int errorn;
/*devuelde la descripción del error, a partir de su código*/
char *MensajeError(DWORD error_num);

/*miramos si el handle se ha creado*/
if(proc==INVALID_HANDLE_VALUE)
{
printf("\n[!] Error al crear el handle\n");
return -1;
}

Process32First(proc,&datos);

if(!strcmp(nombre,datos.szExeFile))
{
return datos.th32ProcessID;
}

for(;
{
Process32Next(proc,&datos);

errorn=GetLastError();
if(errorn>0)
{
if(errorn!=ERROR_NO_MORE_FILES)
{
printf("\n[!] Error %d - %s",errorn,MensajeError(errorn));
}
return 0;
}

if(!strcmp(nombre,datos.szExeFile))
{
return datos.th32ProcessID;
}
}

CloseHandle(proc);
return 0;
}

/*DA INFORMACION SOBRE UN PROCESO*/
int InfoProc(DWORD pid)
{
HANDLE proc;
/*estructuras que recojen información del proceso*/
MODULEENTRY32 datos;
/*función que nos indica la descripcion de un error*/
char *MensajeError(DWORD error_num);

printf("\n
Creando handle...");
//abrimos el proceso
proc=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pid);//con posibilidad para acceder a todo
if(proc==INVALID_HANDLE_VALUE)
{
printf("ERROR - %s",MensajeError(GetLastError()));
return 0;
}printf("OK");

if(Module32First(proc,&datos)==FALSE)
{
printf("\n[!] Error al obtener los datos\n");
CloseHandle(proc);
return 0;
}

//obtenemos los datos
printf("\n
Obteniendo datos del pid=%d...",pid);
if(Module32First(proc,&datos)==FALSE)
{
printf("\n[!] Error al obtener los datos\n");
CloseHandle(proc);
return 0;
}printf("OK");

//mostramos la info
printf("\n\n
Informacion sobre el proceso con pid=%d",pid);
printf("\n-----------------------------------------------");
printf("\n    + Nombre el ejecutable: %s",datos.szModule);
printf("\n    + Ruta del ejecutable: %s",datos.szExePath);
printf("\n    + PID: %d",datos.th32ProcessID);
printf("\n    + Tam. Modulo: %d bytes",datos.modBaseSize);
printf("\n-----------------------------------------------");

printf("\n\n
Cerrando handle...");
//cerramos el handle
if(CloseHandle(proc)!=0)
{
printf("OK\n");
}else{
printf("\nERROR - %s\n",MensajeError(GetLastError()));
}
return 0;
}

//devuelde la descripción del error, a partir de su código
char *MensajeError(DWORD error_num)
{
char *lpMsgBuf;

//cojemos el mensaje del error
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error_num,
0,
(LPTSTR) &lpMsgBuf,
0,
NULL
);

return lpMsgBuf;
}

//parte una string desde 'inicio' hasta 'fin'
char *mid(char *str1, unsigned int inicio, unsigned int fin)
{
char *resultado;
unsigned int i;

if(inicio>fin)
{
return NULL;
}

resultado=(char *) malloc((fin-inicio)*sizeof(char));

for(i=inicio;i<fin;i++)
{
resultado[i-inicio]=str1;
resultado[(i-inicio)+1]='\0';
}

return resultado;
}
Title: Re: programación C/C++
Post by: el_mejor_demolidor on September 19, 2005, 06:53:43 PM
EL LENGUAJE DE PROGRAMACIÃ"N C.
M. en C. Luis Rubén Rusiles Zamora


CONTENIDO

Capítulo 1. INTRODUCCIÃ"N GENERAL
Capítulo 2. TIPOS OPERADORES Y EXPRESIONES
Capítulo 3. CONTROL DE FLUJO
Capítulo 4. FUNCIONES Y LA ESTRUCTURA DEL PROGRAMA
Capítulo 5. APUNTADORES Y ARREGLOS
Capítulo 6. ESTRUCTURAS
Capítulo 7. ENTRADA Y SALIDA
INDICE ALFABÉTICO

Capítulo 1. INTRODUCCIÃ"N GENERAL


A continuación se muestra un programa para imprimir
hello, world



--------------------------------------------------------------------------------

#include <stdio.h>
main(){


printf("hello, ");
printf("world ");
printf("\n");

}



--------------------------------------------------------------------------------

Algunos caracteres escape


\t tabulador
\b retroceso
\" comillas
\\ diagonal



Tipos de datos básicos

int entero
float real
char character
short entero corto
long entero largo
double real doble precisión


Proposición while
La sintaxis de la proposición while es la siguiente:
while (fahr <= upper)
{
...
}

Constantes simbólicas


#define LOWER 0
#define UPPER 30
#define STEP 20



Algunos Ejemplos de programas simples en C



--------------------------------------------------------------------------------

main() /* copia la entrada a la salida, versión 2 */
{


int c;
while ((c=getchar)!=EOF)
putchar(c);

}



--------------------------------------------------------------------------------

main() /* Table Farenheit-Celsius */
{
int fahr;
for (fahr=0; fah<=300; fahr=fahr+20)
printf("4d %6.1f\n",fahr,(5.0/9.0)*(fahr-32));
}

--------------------------------------------------------------------------------

main() /* cuenta los caracteres leídos */
{
double nc;
for (nc=0; getchar()!=EOF; ++nc)
;
printf("%.0f\n",nc);
}

--------------------------------------------------------------------------------

Asignación multiple.
Se propaga de derecha a izquierda, por ejemplo:
nl=nw=nc=0;
se entiende como:
nc=(nl=(nw=0)));

OR
if (c==' ' || c=='\n' || c=='\t')

if
if (expresión)
proposición 1
else
proposición 2

Declaración de un vector de 10 enteros. El primero es ndigit[0];
int ndigit[10];

Funciones
Formato de una función:
[tipo] nombre (lista de argumentos si los hay)
{
declaraciones;
proposiciones;
}
solo se usa "tipo" si se regresa un valor.

Ej. Función "power"
--------------------------------------------------------------------------------

power(int x, int n)
{
int i, p;
p=1;
for (i=1; i<=n; ++i)
p=p*x;
return (p);
}

Ej. Uso de la función "power"
--------------------------------------------------------------------------------

#include
main()
{
for (i=0; i<10; ++i)
printf("%d %d %d\n", i, power(2,i), power (-3,i));
}

--------------------------------------------------------------------------------

Las llamadas en C son por valor.
Lo que permite modificar las copias privadas y temporales, es decir, las variables automáticas.
Cuando se usa un arreglo como argumento, se pasa la dirección del mismo.

Cadenas de caracteres.
Tienen un caracter nulo al final ('\0').
Ej. "hello\n" -> h e l l o \n \0

Tipos de variables
Entre los tipos de variables se cuentan:
Automáticas
Externas
Las variables automáticas...
- aparecen y desaparecen con la llamada de la función.
Las variables externas...
- se declaran globalmente: extern int max;
- se definen fuera de las funciones: int max;
- se declaran dentro de las funciones: extern int max;

Capítulo 2. TIPOS OPERADORES Y EXPRESIONES

Nombres de las variables
Letra (Letra o Dígito)* -> 31 caracteres
Las mayúsculas son diferentes de las minúsculas
Es práctica común de C, denotar con
- MAYUSCULAS las constantes
- minúsculas las variables

Tipos
char
int -> (CALIFICADORES: short, long, unsigned)
float
double

Constantes
Simbólicas (Preprocesamiento)
Ej. #define PI 3.14159265359

#define MAXLINE 1000
char line [MAXLINE+1]

#define FORMFEED '\014'
Variables constantes:
Ej. const float pi=3.14159265359;
Alfanuméricas:
Se evalúan en tiempo de compilación, no de ejecución.
Ejs. 3.14159265359
123.456e-7
0.12E3
'0' -> ASCII 48, EBCDIC 240

Declaraciones:
Se pueden declarar varias variables en pocos renglones:
int lower,upper,step;
char c, line[1000];
También se pueden escribir más explicitamente, para agregar comentarios:
int lower; /* algunos comentarios */
int upper;
int step;
char c;
char line[1000];

Inicialización de variables:
char backslash='\\';
int i=0;

Operadores aritméticos:
+ - * / %(módulo)
Ej. (uso del módulo)
if (year%4==0 && year%100!=0 || year%400==0)
es un año bisiesto;
else
no lo es;

Operadores relacionales y lógicos:
> >= <= < == !=
El operador que convierte en 0 algo distinto de 0, y en 1, el cero, es !. Ej.
if (!inword)
if (inword==0)

Conversiones de Tipos
Se hacen conversiones automáticas cuando tiene sentido. Ej.
float + int -> float
"char" e "int" se manejan indiscrimidamente. Ej.
int atoi(char s[]) /* convierte s a int */
{
int i,n;
n=0;
for (i=0; s>='0' && s<='9';++i)
n=10*n+s-'0';
return (n);
}

Conversión coaccionada "cast"
Se puede forzar la conversión de un tipo en otro. El formato es:
(nombre-de-tipo) expresión
por ejemplo:
sqrt( (double) n)

Operadores de incremento y decremento
si n=5, entonces x=n++; -> x=5 n=6
x=++n; -> x=6 n=6

Operadores lógicos para manejo de bits:
& AND lógico
| OR lógico
^ XOR lógico
<< desplazamiento a la izquierda
>> desplazamiento a la derecha
~ complemento a uno (unario)
Ejs:


--------------------------------------------------------------------------------

c = n & '\077';
x = x | MASK;
x = x & ~'\077';

Ej. Función para tomar n bits a partir de la posición p
--------------------------------------------------------------------------------

getbits(unsigned int x, p, n)
{
return ((x>>(p+1-n)) & ~(~0 << n));
}
Nota: (~0 << n) es 11..100..0 con n ceros a la derecha
~(~0 << n) es 00..011..1 con n unos a la derecha
--------------------------------------------------------------------------------


Operadores y expresiones de asignación
La expresión
e1 op= e2
es idéntico a
e1 = e1 op e2
donde "op" es un operador como {],-,*,/,%,<<,>>,&,^,|}
Por ejemplo: i=i+2; es idÚntico a i+=2;

Expresiones condicionales
Tienen el siguiente formato
e1 ? e2 : e3;
si e1 es verdadero se evalúa e2, si e1 es falso, se evalúa e3.
z=(a>b) ? a : b; /* z=max(a,b) */
Precedencia y orden de evaluación

OPERADOR ASOCIATIVIDAD
() [] -> . ->
! ~ ++ -- - (tipo) * & sizeof <-
* / % ->
+ - ->
<< >> ->
< <= > >= ->
== != ->
& ->
^ ->
| ->
&& ->
|| ->
? : <-
= += -= etc <-
0 ->


ASOCIATIVIDAD
-> izquierda a derecha
<- derecha a izquierda
i=i+2
i+=2


Capítulo 3. CONTROL DE FLUJO

Proposiciones
Se terminan con ; (";" es terminador, no separador)
Nula: ;
Simple: x=0;
Compuesta: { proposiciones; }

if else
if (expresión)
proposición 1
else
proposición 2

Las siguientes proposiciones son equivalentes:
if (expresión)
if (expresión != 0)

El "else" se asocia a la condicional más interna:
if (n>0) if(a>b) z=a; else z=b;
Se entendería como:
if (n>0)
if(a>b)
z=a;
else
z=b;
Si se quiere que el "else" se asocie a la condicional externa, es necesario usar llaves, como se muestra a
continuación:
if (n>0) { if(a>b) z=a;} else z=b;
que se entiende como:
if (n>0) {
if(a>b)
z=a;
}
else
z=b;

else if
Permite escribir condicionales de casos EXCLUYENTES
if (expresión)
proposición
else if (expresión)
proposición
else
proposición

switch
Sintetiza una secuencia larga else if, incluyendo || (or).

Ej.



--------------------------------------------------------------------------------
main() /* cuenta dígitos, espacios en blanco y otros */
{


int c, i, nwhite, nother, ndigit[10];
nwhite=nother=0;
for (i=0; i<10; i++)
ndigit=0;
while ((c=getchar()) != EOF) {


switch(c) {


case '0':
case '1':
...
case '9':

ndigit[c-10]++;
break;


case ' ':
case '\n':
case '\t':


nwhite++;
break;


default:


nother++;
break;


}

}


printf("digits= ");
for (i=0; i<10; i++)
printf("%d",ndigit);
printf("\n white space = %d, ",
"other = %d\n",nwhite,nother);
return 0;
}



--------------------------------------------------------------------------------


while y for
while (expresión)
proposición

Las siguientes proposiciones "for" y "while" son equivalentes:
for (expr1; expr2; expr3)
proposicion

expr1;
while (expr2)
{
proposición
expr3;

}

Uso de la coma ","
La coma "," permite el cálculo secuencial de expresiones.

Por ejemplo:



--------------------------------------------------------------------------------
reverse(s) /* invierte cadena s */
char s[];
{


int c, i, j;
for (i=0; j=strlen(s)-1; i)

{

c=s;
s=s[j];
s[j]=c;

}

}



--------------------------------------------------------------------------------

do while
do
proposición
while (expresión);

break
La proposición "break" permite una salida forzada de:

do
while
for
switch
Puede similarse usando otra "condición", pero no resulta tan claro.

continue
Obliga a ejecutar la siguiente iteración del ciclo, en las proposiciones:

do
while
for

Por ejemplo



--------------------------------------------------------------------------------
/* procesa los valores positivos de un arreglo */
for (i=0; i {
if (a<0) /* salta los elementos negativos */
continue;
/* aquí procesa los elementos positivos */
}
--------------------------------------------------------------------------------


goto y etiquetas
Generalmente es usada en el manejo de errores. Se aconseja ser parcos en su uso.
Por ejemplo


--------------------------------------------------------------------------------

/* muestra el primer valor negativo de un */
/* arreglo multidimensional */
for (i=0; i for (j=0; j if (v[j]<0)
goto found;
/* no se encontró */
found: /* se encontró en la posición i,j */
..

--------------------------------------------------------------------------------

Capítulo 4. FUNCIONES Y LA ESTRUCTURA DEL PROGRAMA

En C no se pueden escribir funciones dentro de funciones.
Por ejemplo:

--------------------------------------------------------------------------------
/* Imprime las líneas que contengan cierto patrón */
#define MAXLINE 100

void index(char [], char []);
extern void getline(char [], int);

main()
{
char line[MAXLINE];

while(getline(line,MAXLINE)>0)
if (index(line,"the")>=0
printf("%s",line);
}

void index(char s[], char t[])
/* devuelve posición t en s; o -1 si no está */
{
int i,j,k;

for (i=0; s!='\0'; i++)
{
for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++,k++)
;
if (t[k]=='\0')
return (i);
}
}


Title: Re: programación C/C++
Post by: el_mejor_demolidor on September 19, 2005, 06:57:07 PM
escrebo más de una parte,porque pasava de el limite de caracteres!!

Compilación y encadenamiento
En UNIX:
$ cc main.c getline.c index.c
produce:
main.o getline.o index.o <- programas objeto
a.out <- programa ejecutable

Funciones que devuelven valores no enteros
Se tienen las siguientes 2 puntos:
- Por default el tipo de la función es "int" ("char" se convierte a "int").
- En caso de no ser "int", la función se debe declarar:
- en la función:
double atof(s) /* convierte la cadena s a double */
- en la llamada:
double sum,atof();
...
(... sum+=atof(line));

Reglas sobre el alcance de validez de una variable:
Variable externa (declaración)
Se dan a conocer las propiedades de una variable, por ejemplo tipo, tamaño, etc.

Variable externa (definición)
Causa una asignación de memoria. Solo se debe hacer una definición.

Por ejemplo, las siguientes líneas


int sp;
double val[MAXVAL];


cuando están fuera de cualquier función, definen las variables externas "sp" y "val", obligan a asignar
memoria y sirven de declaración para el
resto del archivo.

Sin embargo, las líneas


extern int sp;
double val[MAXVAL];


declaran para el resto del archivo que "sp" es un entero, y "val" es un arreglo double (cuyo tamaño se fija
en otro lugar), pero no se crean las
variables ni se les asigna memoria.


Variables estáticas
Las variables estáticas son accesibles solo dentro del archivo donde son definidas. Y pueden ser definidas
dentro o fuera de una función.

Ej. Si las 2 variables y las 2 funciones siguientes se compilan
en un archivo con:


static char buf[BUFSIZE]; /* buffer para "ungetch" */
static int bufp=0; /* sig. pos. libre en "buf" */
getch() {...}
ungetch() {...}


el resto de las funciones de los otros archivos no tendrá acceso ni a "buf" ni a "bufp". Por lo anterior, no
habrá conflictos si los mismos nombres
son usados en otros programas.

Una función estática es inaccesible fuera del archivo donde se declara (y define, por supuesto).


Variables registro.
Las variables registro sólo pueden ser las variables automáticas y los parámetros formales de la función.

Las variables registro son usadas para variables muy usadas. El compilar coloca las variables registro en
los registros de la CPU de la máquina,
siempre y cuando sea posible.

NO ES POSIBLE obtener la dirección de una variable estática.

Se declaran de la siguiente manera:
register int x;
register char c;

Y la declaración para parámetros formales de función, es:
f(register int c,n)
{
...
}

Estructura de bloques
Se tienen las siguientes características:
- No se pueden definir funciones dentro de funciones. Si embargo si se pueden declarar funciones dentro de
funciones. Esta declaración hace
referencia a funciones que se encuentran en otro parte.
- Las declaraciones o definiciones (incluyendo inicializaciones), se colocan dentro de las llaves que
introduce cualquier sentencia compuesta.
Por ejemplo:
if (n>0)
{
/* se declara una variable nueva "i" */
int i;
for (i=0; i ...
}

Inicialización
La inicialización tiene las siguientes consideraciones:
- Si no se inicializan explicitamente las variables, se tiene:
- Las variables externas y estáticas tendrán cero.
- Las variables automáticas y registro tendrán basura.

- Las variables simples, que no son arreglos ni estructuras, se inicializan así:
int x;
char squoute = '\'';
long day=60*24; /* minutos del día */

- Las variables externas estáticas se inicializan una vez en tiempo de compilación; las variables
automáticas y registro, cada vez que se entra a
la función.

- Las variables automáticas y registro se pueden inicializar con valores definidos previamente, incluso
llamadas a función. Por ejemplo:
{
int low=0;
int high=n-1; /* n definida anteriormente */
int mid;
..
}

- Los arreglos automáticos no pueden ser incializados.

- Los arreglos externos y estáticos se inicializan con valores separados por ',' y entre llaves. Por
ejemplo, el programa siguiente para contar
dígitos, espacios y otros:
/* cuenta dígitos, espacios y otros */
main()
{
int c,i,nwhite,nother;
int ndigit[10];

nwhite=nother=0;
for (i=0; i<10; i++)
ndigit=0;
...
}
puede ser escrito como:
/* cuenta dígitos, espacios y otros */
int nwhite=0;
int nother=0;
/* inicialización con 10 0's */
int digit[10]={0,0,0,0,0,0,0,0,0,0,0};
main()
{
int c,i;
...
}

- Se pueden inicializar arreglos de caracteres de 2 maneras:
- Como cadena de caracteres
char pattern[]="the";
- Como arreglo de caracteres
char pattern[]={'t','h','e','\0'};

Recursividad
- Las funciones en C pueden llamarse a si mismas, es decir pueden ser recursivas.
- Una función puede llamarse a si misma, directa o indirectamente. Por ejemplo:



--------------------------------------------------------------------------------
/* imprime n en decimal (recursivamente) */
void printd(int n)
{
int i;
if (n<0)
{
putchar('-');
n=-n;
}
if ((i=n/10) != 0)
printd(i);
putchar(n%10+'0');
}
--------------------------------------------------------------------------------



El preprocesador de C

Inclusión de archivos (include):
Una línea de la forma
#include "nombre"
indica al preprocesador de C, substituir la línea con el contenido del archivo "nombre", de trayectoria
absoluta.

Una línea de la forma
#include
indica al preprocesador de C, substituir la línea con el contenido del archivo "nombre", de la trayectoria
PREDEFENIDA para los archivos "include".

Los "include"s pueden ser anidados.

Los "include"s son recomendables para tener las mismas definiciones en varios programas fuentes.

Sustitución de Macros
Para sustituir SI por 1, usamos la línea siguiente.
#define SI 1
aquí, las cadenas "SI=" no serán sustituidas.

Para usar una sintaxis similar al PASCAL, usamos las líneas
#define then
#define begin {
#define end }
y podríamos escribir después
if (i>0) then
begin
a=1;
b=2
end

Podemos usar parámetros en la sustitución de macros. Por ejemplo:
#define max(A,B) ( (A)>(B) ? (A) : (B) )
y usarla como
x=max(p+q,r+s);
que sería sustituida por
x=((p+q)>(r+s) ? (p+q) : (r+s));

NOTAS:
- Es necesaria utilizar paréntesis en la definición de macros, para evitar resultados erróneos debido a la
prioridad de las operaciones
aritmÚticas.
- Con una MACRO se puede crear una sola función para varios tipos de argumentos.
- Las MACROS con parámetros son más eficientes que las llamadas a funciones, ya que son una expansión en
línea. Por ejemplo, las funciones
"getchar()" y "putchar()" están definidas como MACROS de las funciones "putc()" y "getc()", usando la salida
estándard (stdout) y entrada estándard
(stdin) respectivamente.


Capítulo 5. Apuntadores y arreglos.
Apuntadores y direcciones.
Los símbolos * y & pueden ser usados para el contenido y la dirección de una variable, respectivamente. Por
ejemplo,

si "x" es una variable de tipo "int"
y "y" es una variable de tipo "int"
y "px" es una variable de tipo "apuntador a int"
entonces, se podría hacer lo siguiente:

Asignar la dirección de "x" al apuntador "px"
px = &x;

Aumentar en 1, el valor apuntado por "px" (es decir, el valor de "x") y asignarlo a la variable "y".
y = *px+1;

Aumentar en 1, el valor del apuntador "px" (es decir, el valor de una variable desconocida) y asignarlo a la
variable "y".

Aumentar en 1 el valor apuntado por "px" (es decir, el valor de "x").
*px+=1;
o bien
(*px)++;
notar que en este último ejemplo es necesario usar parÚntesis, debido a que, aunque la prioridad de "*" y
"++" es igual, la asociatividad es de
DERECHA a IZQUIERDA. Así, sin los parÚntesis, la expresión "*px++;" se entendería como: "*(px++);".

Title: Re: programación C/C++
Post by: el_mejor_demolidor on September 19, 2005, 06:57:37 PM
APUNTADORES Y ARREGLOS

Se definimos el arreglo de 10 enteros de la siguiente manera:
int a[10];
podemos referenciar a[0] a[1] .. a[9].
Si además definimos el apuntador a entero "pa"
int *pa;
y le asignamos la dirección del primer elemento del arreglo "a",
pa=&pa[0]; o bien pa=a;
entonces, el contenido de "a" puede ser visto con
*(pa+i)

En apuntadores a arreglos de caracteres, las 2 siguientes declaraciones son equivalentes:
char s[];
char *s;

AritmÚtica de direcciones.
Son posibles las siguientes operaciones con apuntadores:
- Sumar y restar un entero a un apuntador.
- Restar y comparar 2 apuntadores.
- Comparar un apuntador con NULL.

Apuntadores a caracteres y a funciones.
En el siguiente ejemplo, la variable "mensaje" es SOLO UN APUNTADOR.
char *message="now is the time";
No se debe comfundir el envío de un APUNTADOR a un arreglo de caracteres con el envío del ARREGLO de
caracteres. Por ejemplo, en la siguiente
función se envían los apuntadores a 2 arreglos de caracteres (cuya memoria fue asignada en otra parte del
programa).

strcpy(s,t) /* copia t a s, con apuntadores */
{
while (*s++=*t++)
;
}

Arreglos Multidimensionales
En C, los arreglos de 2 dimensiones se implementan como arreglos unidimensionales. Donde cada elemento es, a
su vez, un arreglo unidimensional. Por
lo anterior, la sintaxis en C es
day_tab[j]; /* [renglón] [columna] */
en lugar de:
day_tab[i,j]; /* INCORRECTO */

Los arreglos de 2 dimensiones pueden ser inicializados como sigue:
static int day_tab[2][13] =
{
{0,31,28,..,31},
{0,31,29,..,31},
};


Arreglo de apuntadores. Apuntadores a apuntadores.
Inicialización de arreglos de apuntadores:
static char *name[]=
{
"mes ilegal",
"enero",
...
"diciembre",
};


Diferencia entre apuntadores y arreglos multidimensionales.
No se debe confundir las declaraciones:
int a[10][20]; /* matriz de 10*20=200 enteros */

int *b[10]; /* vector de 10 apuntadores a enteros */
/* o 10 apuntadores a arreglos a enteros */

Si consideramos que en los 2 arreglos anteriores, usamos
[renglón] [columna]

Entonces tenemos 2 diferencias básicas:
1. En el arreglo "a" el número de columnas (elementos) x renglón es 20 para todos los renglones. En el
arreglo "b" podemos tener un número
diferente de columnas x renglón para cada renglón. Por ejemplo 2 elementos en el renglón 0; 5 en el renglón
1; e incluso una matriz de 4x4 en el
renglón 3, etc.
2. La memoria ocupada por los 2 arreglos es diferente. Inclusive en el caso de que los apuntadores del
arreglo "b" apuntaran a un arreglo de 20
elementos por renglón, la memoria ocupada por los 2 arreglos sería diferente.
Para el arreglo "a", 200 enteros.
Para el arreglo "b", 200 enteros + 10 apuntadores.

Argumentos de la línea de comandos.
Al correr el programa ejecutable producido por un programa fuente escrito en C, podemos agregar argumentos
en la línea de comandos. Estos
argumentos pueden ser usados para producir efectos diferentes al correr el mismo programa. Así, podríamos
usar opciones como las usadas en los
sistemas operativos:
C:> copy
C:> copy a:\arch1 b:
C:> copy a:\arch1 b:\arch2

El procesamiento de los argumentos de la línea de comandos se puede ejemplificar con el siguiente programa
en C, que simplemente escribe los
argumentos en la salida estándard.




--------------------------------------------------------------------------------
/* escribe los argumentos en la salida estándard */
main(int argc, char *argv[])
{
while(--argc>0)
printf("%s%c",*++argv,(argc>1)?' ':'\n');
}

--------------------------------------------------------------------------------

"argc" y "argv" son palabras predefinidas. "argc" indica el número de argumentos (incluyendo el nombre del
programa ejecutable). "argv" es un
arreglo de apuntadores a arreglos de caracteres. "argv" es un apuntador al arreglo de caracteres del
argumento i.

Por ejemplo, si "echo.exe" es un programa ejecutable producido por un programa escrito en C, entonces al ser
corrido con:
echo hello world
los valores que tomarían "argc" y "argv" en caso de haber sido usados son:
argc=3 *argv[0]=echo *argv[1]=hello *argv[2]=world


Apuntadores a funciones
En la definición:
/* compara 2 cadenas */
int strcmp();
En la declaración:
/* apuntador a función que devuelve un entero */
int (* comp)();

/* función que devuelve apuntador a entero */
int *comp();



Capítulo 6. ESTRUCTURAS



Por ejemplo, si queremos crear el tipo "date" y crear 2 variables de ese tipo, "birthdate" y "hiredate".
Podemos usar:
struct date
{
int day;
int month;
int year;
};
date birthdate, hiredate;

o bien, también podemos escribir:
struct date
{
int day;
int month;
int year;
} birthdate, hiredate;

Si solo queremos crear las variables, y no llamar a su tipo con algún nombre, podemos simplemente teclear:
struct
{
int day;
int month;
int year;
} birthdate, hiredate;

Una estructura puede contener a su vez estructuras, como en:
struct person
{
char name[NAMESIZE];
char address[ADRSIZE];
long zipcode;
double salary;
struct date birthdate;
struct date hiredate;
}emp;
En el caso de haber declarado la variable "emp" de la forma anterior, podemos hacer referencia al mes de su
fecha de nacimiento con:
emp.birthdate.month

También podemos inicializar estructuras estáticas y externas de la siguiente manera:
struct date d={4,7,1776}

Si declaramos apuntadores a estructuras, como en
struct date *pd;
podemos hacer referencias con la notación:
pd->year
o bien
(*pd).year

NOTAS:
- punto(.) -> () [] tienen la máxima precedencia
Por lo tanto,
++p->x incrementa x
- La asociatividad de punto(.) y -> es de izq. a der.
Por lo tanto,
p->q->memb
se entiende como (p->q)->memb
emp.birthdate.month
se entiende como (emp.birthdate).month

Arreglos de estructuras
En lugar de usar arreglos paralelos en C, como en el ejemplo siguiente para contar palabras reservadas de C,
char *keyword[NKEYS];
int keycount[NKEYS];

se pueden usar estructuras, de la siguiente manera:
struct key
{
char *keyword;
int keycount;
} keytab[NKEYS];
pero tendremos que asignar valores despuÚs a "keytab".

También podemos usar declaración explicita como en:
struct key
{
char *keyword;
int keycount;
} keytab[]=
{
"break",0,
"case",0,
...
"while",0
};
#define NKEYS (sizeof(keytab)/sizeof(struct key))
donde se define NKEYS en base a los tamaños de la estructura y la declaración explícita, para no tener que
calcular su valor y recalcularlo cada
vez que el contenido de "keytab" cambie.

Apuntadores a estructuras
Se pueden declarar apuntadores a estructuras, como por ejemplo, si usamos la estructura "key" anteriormente
definida:
struct key *binary(),*pk;
y podemos referenciar a los campos de la estructura con:
pk->keyword
pk->keycount

Estructuras autoreferenciadas
Las estructuras pueden contener apuntadores a si mismas como se muestra en el siguiente ejemplo:
struct tnode /* el nodo */
{
char *word; /* apuntador a los caracteres */
int count; /* número de ocurrencias */
struct tnode *left; /* hijo izquierdo */
struct tnode *right; /* hijo derecho */
};

Se puede convertir un apuntador a caracter en un apuntador de estructura mediante el uso de un 'cast'
(conversión forzada).
char *p;
... (struct tnode *) p ...
La anterior conversión es usada principalmente en el uso de memoria dinámica.


Uniones
Las uniones son usadas cuando se necesita que una variable tome valores de tipos diferentes. En el ejemplo
siguiente:
union u_tag
{
int ival;
float fval;
char *pval;
} uval;
la variable "uval" de tipo "u_tag" puede tomar valores
"int" si se usa "uval.ival"
"float" si se usa "uval.fval"
"char *" si se usa "uval.pval"

Es necesario el uso consistente de uniones. Es decir, el tipo utilizado debe ser el tipo más recientemente
almacenado.


Las uniones pueden ser anidadas en una estructura, como se muestra:
struct
{
char *name;
int flags;
int utype;
union
{
int ival;
float fval;
char *pval;
} uval;
} symtab[NSYM];

y se hace referencia de la siguiente manera:
symtab.uval.ival para ival
symtab.uval.pval para el primer caracter de pval

typedef
El "typedef" permite declarar sinónimos de tipos. Por ejemplo
typedef int LENGTH;
declara el nombre de LENGTH como sinónimo de int.

Este "nuevo tipo" podría ser usado en
LENGTH len, maxlen;
LENGTH *lengths[]; /* arreglo de apuntadores a tipo LENGTH=int */

Algunas observaciones del uso de "typedef"
- Sintácticamente "typedef" se parece a las clases de almacenamiento "extern", "static", etc.
- No crea un nuevo tipo, sino añade un nuevo nombre.
- Es parecido a "#define" pero con mayor alcance. Por ejemplo, el siguiente sinónimo es para un apuntador a
una función que devuelve un int.
typedef int (*PFI) ();
..
PFI strcmp, numcmp, swap;


Capítulo 7. ENTRADA Y SALIDA


Acceso a la biblioteca estándard
La línea siguiente se coloca al principio de un programa fuente. Define ciertas macros y variables empleadas
por la biblioteca estándard de E/S.
#include
Se usa < >, en vez de "", para que el archivo sea buscado en el directorio de información estándard, por
ejemplo:
/usr/include ---> en UNIX
\TURBOC2.0\INCLUDE ---> en MS-DOS

Entrada y salida estándard: putchar(), getchar()
El uso de la entrada y salida estándard permite hacer redireccionamiento de y hacia archivos.
prog < arch_ent
prog > arch_sal
o bien procesamiento entubado, como en:
prog | otr_prog
otr_prog | prog

Por ejemplo, el siguiente programa copia la entrada estándard (teclado) a la salida estándard (monitor).



--------------------------------------------------------------------------------
#include
main()
{
int c;
while ((c=getchar())!=EOF)
putchar(isupper(c) ? tolower(c) : c);
}
y podría correrse, en el casO de llamarse "lower", de la siguiente manera:
C:> type file1 | lower > salida


Salida con formato, printf()
La sintaxis es la siguiente:
printf(control,arg1,arg2,...,argn)
donde:
control::="{char}%[-][long_max]convers.[char_o_decim]{char}"
char ::=cualquier caracter
- justificación a la izquierda
long_max::=longitud máxima. Si no cabe el valor, se viola
convers::=d decimal
o octal
x hexadecimal
u unsigned
c caracter
s cadena(string)
e float o double => [-]m.nnnnnnE[+-]xx
f float o double => [-]mmm.nnnnnn
g más corto que %e o %f. Los ceros no significativos no se imprimen
char_o_dec número de caracteres de la cadena o número de decimales

Por ejemplo, si "s" es un apuntador a "hello, world", se tiene:
0 1 2
1234567890123456789012
printf(":%10s:",s) => :hello world:
printf(":%-10s:",s) => :hello world:
printf(":%20s:",s) => : hello world:
printf(":%-20s:",s) => :hello world :


Entrada con formato, scanf()
La sintaxis es la siguiente:
scanf(control,arg1,arg2,...,argn)
donde:
# control::="{char}%convers[long_max]convers"
char::=cualquier caracter
convers::= d decimal
o octal
x hexadecimal
h entero corto (short)
c caracter
s cadena
f,e punto flotante. Puede usar E+ o E-
l long (double)

Por ejemplo, si declaramos:
int i;
float x;
char name[50];
entonces, la llamada de la función, líneas leídas y valores asignados, se muestran a continuació:
scanf("%d %f %s",&i,&x,name);
25 54.32E-1 Torres
=> i=25 x=5.432 name="Torres\0"
scanf("%2d %f %*d %25",&i,&x,name);
56789 0123 45182
=> i=56 x=789.0 name="45\0"


Conversión de formato en memoria, sprintf(), sscanf().
sprintf() y sscanf() hacen la misma función que printf() y sscanf(), pero en lugar de enviar el resultado a
la salida estándar o leerlo de la
entrada estándar, usan variables de tipo de arreglo de caracteres.

Por ejemplo, si n=123, la siguiente llamada a sprintf() almacena "temp123\0" en el arreglo de caracteres
name.
sprintf(name,"temp%d",n);

Y si name contiene "temp123", el valor 123 se asignará a n al ejecutarse la siguiente llamada
sscanf(name,"temp%d",n);


Acceso a archivos (funciones de stdio.h)
En la librería  está definido el tipo FILE. Este tipo permite guardar información de posición y descripción
del buffer asociado a un archivo.

El tipo FILE se usa de la siguiente forma:
FILE *fopen(), *fp;
donde "fp" puede ser usado como apuntador del archivo que se abre:
fp=fopen(nombre,modo);
donde:
nombre es el nombre del archivo que se va a abrir
modo puede ser: lectura("r"), escritura("w"), y añadido("a").
NOTA: si se produce un error, fopen regresa NULL.

Para escribir y leer información de un archivo, usamos: putc() y getc(), de la siguiente manera:
c=getc(fp); /* lee un caracter del archivo apuntado fp */
putc(c,fp); /* escribe un caracter al arch. apunt. fp */

Existen en la librería  las definiciones para 3 apuntadores estándard a archivos:
stdin archivo de la entrada estándard
stdout archivo de la salida estándard
stderr archivo de la salida del error estándard

En base a los apuntadores estándard anteriores, se pueden definir las funciones putchar() y getchar().
#define getchar() getc(stdin)
#define putchar(c) putc(c,stdout)

También podemos usar entrada y salida formateada a archivo, con las funciones:
fscanf(fp,formato,lista de variables);
fprintf(fp,formato,lista de variables);
con la misma sintaxis que scanf(),printf().

NOTA: Cuando se detecta un error de entrada/salida en archivos, es conveniente escribir el mensaje de error
en stderr.

Entrada y salida de líneas
Para almacenar en el arreglo de caracteres line, una línea de un máximo de MAXLINES caracteres leída del
archivo apuntado por fp, usamos:
fgets(line,MAXLINE,fp)
Para escribir en el archivo apuntado por fp el arreglo de caracteres line, usamos
fputs(line,fp);

Operaciones con cadenas de caracteres, string.h
En el directorio include de la versión de C que se estÚ manejando existen encabezados de otras librerías,
entre las que se cuentan string.h. En
este encabezado están las declaraciones para las funciones de manejo de cadenas de caracteres que se listan
a continuación. En adelante, s y t son
de tipo apuntador a caracter, y c y n son enteros.
strcat(s,t); concatena s al final de t
strncat(s,t,n); concat. n caracts. de t al final de s.
strcmp(s,t); regresa negativo, cero, o positivo para: s t
strncmp(s,t,n); i gual que strcmp pero solo con n caract.
strcpy(s,t); copia t en s
strncpy(s,t,n); copia a lo mas n caract. de s en t
strlen(s); regresa la longitud de s
strchr(s,c); regresa un apuntador al primer c que estÚ en s, o NULL si no está presente.
strrchr(s,c); regresa un apuntador al último c que estÚ en s, o NULL si no está presente.


Prueba y conversión de cadenas de caracteres, ctype.h
Varias de las funciones declaradas en  realizan pruebas y conversiones de caracteres. En lo que se muestra a
continuación, c es un int que se puede
representar como un unsigned char o EOF. Las funciones regresan int
isalpha(c); != 0 si c es alfabÚtica, 0 otro caso.
isupper(c); mayúscula
islower(c); minúscula
isdigit(c); dígito
isalnum(c); isalpha(c) || isdigit(c)
isspace(c); blanco, tabulador, nueva línea, retorno, avance de línea, tabulador vertical
toupper(c); regresa c convertida a mayúscula
tolower(c); regresa c convertida a minúscula
ungetc(c,fp) Esta función se usa para devolver el caracter c al archivo apuntado por fp.

Funcion system()
La función system() permite hacer una llamada al sistema operativo. La sintáxis es la siguiente:
system("date");
system("dir");

Memoria Dinámica
Al declarar (o definir) una variable en C, normalmente se establece una memoria limitada. Por ejemplo:
int i;
int a[10];
int *c;
Sin embargo si nosotros queremos que ciertos datos se almacenen en memoria no limitada (salvo la limitación
del "heap" del sistema), podemos usar
memoria dinámica.

El siguiente ejemplo muestra como almacenar una cadena arbitrariamente larga de caracteres.


--------------------------------------------------------------------------------
/* programa para almacenar cadena de longitud ilimitada */
#include
#include
struct scar
{
char car; /* caracter */
struct caract *psig; /* apuntador al siguiente */
} pini, pfin;

main()
{
int c;
struct caract pc;

/* lectura y almacenamiento */
pini=pfin=NULL
if (c=getchar()!=EOF)
do
c=getchar();
for (pini=pfin=NULL; (c=getchar())!=EOF; )
pfin=(struct scar *) malloc(sizeof(struct scar))
if (pfin=NULL)
puts("No hay memoria",stderr);
else
pini->car=c, pini->psig=NULL)
while (c!=EOF);
}


el unico problema és:és un poco avanzado!!
Title: Re: programación C/C++
Post by: el_mejor_demolidor on September 23, 2005, 08:48:53 PM
curso pratico (http://espanol.geocities.com/ssomeonexx/cursoprt.zip%5B/url) <---tyene el basico para empezar!
Title: Recomendacion
Post by: Zcarpa on September 27, 2005, 02:53:30 PM
Solo una recomendacion para todos los usuarios y aficionados a C++...... Cuando esten trabajando con  punteros traten de declararlos antes de todas sus variables, por que el declararlo en cualquier parte provoca que los punteros almacenen basura