Está en la página 1de 151

ManualdeC

HctorTejedaVillela

ndiceGeneral 1.CompilacindeunprogramaenC/C++ 1.1Creacin,compilacinyejecucindeunprograma 1.1.1Creacindelprograma 1.1.2Compilacin 1.1.3Ejecucindelprograma 1.2ElmodelodecompilacindeC 1.3Elpreprocesador 1.4CompiladordeC 1.5Ensamblador 1.6Ligador 1.7Algunasopcionestilesdelcompilador 1.8Usodelasbibliotecas 1.9Ejemplos 1.9.1Creacindeunabibliotecaesttica 1.9.2Creacindeunabibliotecacompartida 1.10FuncionesdelabibliotecadeUNIX 1.10.1Encontrandoinformacinacercadelasbibliotecas. 1.11Ejercicios 2.PrincipiosdeC 2.1OrgenesdelC 2.2CaractersticasdeC 2.3EstructuradeunprogramaenC 2.4Variables 2.4.1Definicindevariablesglobales 2.4.2Lecturayescrituradevariables 2.5Constantes 2.6OperadoresAritmticos 2.7OperadoresdeComparacin 2.8Operadoreslgicos 2.9Ordendeprecedencia 2.10Ejercicios 3.EstructurasCondicionales 3.1Lasentencia if 3.2Eloperador ? 3.3Lasentencia switch 3.4Ejercicios

4.Iteracin 4.1Lasentencia for 4.2Lasentencia while 4.3Lasentencia dowhile 4.4Usode break y continue 4.5Ejercicios 5.Arreglosycadenas 5.1Arreglosunidimensionalesymultidimensionales 5.2Cadenas 5.3Ejercicios 6.Funciones 6.1Funciones void 6.2Funcionesyarreglos 6.3Prototiposdefunciones 6.4Ejercicios 7.Mstiposdedatos 7.1Estructuras 7.1.1Definicindenuevostiposdedatos 7.2Uniones 7.3Conversindetipos(casts) 7.4Enumeraciones 7.5Variablesestticas 7.6Ejercicios 8.Apuntadores 8.1Definicindeunapuntador 8.2ApuntadoresyFunciones 8.3Apuntadoresyarreglos 8.4Arreglosdeapuntadores 8.5Arreglosmultidimensionalesyapuntadores 8.6Inicializacinestticadearreglosdeapuntadores 8.7Apuntadoresyestructuras 8.8Fallascomunesconapuntadores 8.9Ejercicios 9.AsignacindinmicadememoriayEstructurasdinmicas 9.1Usode malloc,sizeof y free 9.2 calloc y realloc 9.3Listasligadas 9.4Programaderevisin 9.5Ejercicios 10.Tpicosavanzadosconapuntadores 10.1Apuntadoresaapuntadores 10.2Entradaenlalneadecomandos

10.3Apuntadoresafunciones 10.4Ejercicios

11.Operadoresdebajonivelycamposdebit 11.1Operadoressobrebits 11.2Camposdebit 11.2.1Portabilidad 11.3Ejercicios 12.ElpreprocesadordeC 12.1Directivasdelpreprocesador 12.1.1 #define 12.1.2 #undef 12.1.3 #include 12.1.4 #if Inclusi ncondicional 12.2Controldelpreprocesadordelcompilador 12.3Otrasdirectivasdelpreprocesador 12.4Ejercicios 13.C,UNIXylasbibliotecasestndar 13.1VentajasdelusarUNIXconC 13.2Usodefuncionesdebibliotecasyllamadasdelsistema 14.Biblioteca <stdlib.h> 14.1Funcionesaritmticas 14.2Nmerosaleatorios 14.3Conversindecadenas 14.4Bsquedayordenamiento 14.5Ejercicios 15.Biblioteca <math.h> 15.1Funcionesmatemticas 15.2Constantesmatemticas 16.Entradaysalida(E/S) stdio.h 16.1Reportandoerrores 16.1.1 perror() 16.1.2 errno 16.1.3 exit 16.2Flujos 16.2.1Flujospredefinidos 16.3E/SBasica 16.4E/Sformateada 16.4.1 printf 16.4.2 scanf 16.5Archivos 16.5.1Lecturayescrituradearchivos 16.6 sprintf y sscanf 16.6.1Peticindelestadodelflujo

16.7E/Sdebajonivelosinalmacenamientointermedio 16.8Ejercicios

17.Manejodecadenas <string.h> 17.1Funcionesbsicasparaelmanejodecadenas 17.1.1Bsquedaencadenas 17.2Pruebayconversindecaracteres <ctype.h> 17.3Operacionesconlamemoria <memory.h> 17.4Ejercicios 18.AccesodeArchivosyllamadasalsistemadedirectorios 18.1Funcionesparaelmanejodedirectorios <unistd.h> 18.1.1Busquedayordenamientodedirectorios: sys/types.h , sys/dir.h 18.2Rutinasdemanipulacindearchivos:unistd.h,sys/types.h,sys/stat.h 18.2.1Permisosdeaccesosaarchivos 18.2.2Estadodeunarchivo 18.2.3Manipulacindearchivos:stdio.h,unistd.h 18.2.4Creacindearchivostemporales: <stdio.h> 18.3Ejercicios 19.Funcionesparaeltiempo 19.1Funcionesbsicasparaeltiempo 19.2Ejemplosdeaplicacionesdefuncionesdeltiempo. 19.2.1Ejemplo1:Tiempo(ensegundos)parahaceralgnclculo. 19.2.2Ejemplo2:Inicializarlasemilladeunnmeroaleatorio. 19.3Ejercicios 20.Controldeprocesos: <stdlib.h> , <unistd.h> 20.1EjecutandocomandosdeUNIXdesdeC 20.2 execl() 20.3 fork() 20.4 wait() 20.5 exit() 20.6Ejercicios 21.CompilacindeProgramasconArchivosMltiples 21.1ArchivosCabezera 21.2VariablesyFuncionesExternas 21.2.1Alcancedelasvariablesexternas 21.3VentajasdeUsarVariosArchivos 21.4Comodividirunprogramaenvariosarchivos 21.5OrganizacindelosDatosencadaArchivo 21.6LautileraMake 21.6.1ProgramandoMake 21.7CreacindeunArchivoMake(Makefile) 21.8UsodemacrosconMake 21.9Ejecucinde Make

22.Comunicacinentreprocesos(IPCInterprocessCommunication),PIPES 22.1EntubandoenunprogramadeC <stdio.h> 22.1.1 popen() Tuber aformateada 22.1.2 pipe() Tuber adebajonivel 23.Sockets 23.1Creacinynombradodesockets 23.2Conectandosocketsdeflujo 23.2.1Transferenciadedatosenunflujoycerrado Sobreestedocumento...

ltimamodificacin:20050812 HctorTejedaV htejeda@fismat.umich.mx

Subsecciones

1.1Creacin,compilacinyejecucindeunprograma 1.1.1Creacindelprograma 1.1.2Compilacin 1.1.3Ejecucindelprograma 1.2Elmodelodecompilaci ndeC 1.3Elpreprocesador 1.4CompiladordeC 1.5Ensamblador 1.6Ligador 1.7Algunasopcionestilesdelcompilador 1.8Usodelasbibliotecas 1.9Ejemplos 1.9.1Creacindeunabibliotecaesttica 1.9.2Creacindeunabibliotecacompartida 1.10FuncionesdelabibliotecadeUNIX 1.10.1Encontrandoinformacinacercadelasbibliotecas. 1.11Ejercicios

1.CompilacindeunprogramaenC/C++
EnestacaptulosedanlasprocesosbsicosqueserequierenparacompilarunprogramadeC.Se describetambinelmodelodecompilacindeCytambincomoCsoportabibliotecasadicionales.

1.1Creacin,compilacinyejecucindeun programa
1.1.1Creacindelprograma
Sepuedecrearunarchivoquecontengaelprogramacompleto,comoenlosejemplosquesetienen msadelante.Sepuedeusarcualquiereditordetextosordinarioconelqueseestefamiliarizado.Un editordisponibleenlamayoradelossistemasUNIXesvi,yenLinuxsepuedeusarpico. Porconvencinelnombredelarchivodebeterminarcon``.c''porejemplo:miprograma.c progprueba.c.ElcontenidodelarchivodeberobedecerlasintaxisdeC.

1.1.2Compilacin
ExistenmuchoscompiladoresdeC.ElcceselcompiladorestndardeSun.ElcompiladorGNUde Cesgcc,elcualesbastantepopularyestadisponibleenvariasplataformas. ExistentambincompiladoresequivalentesdeC++loscualesusualmentesonnombradoscomoCC. Porejemplo,SunproveeCCyGNUGCC.ElcompiladordeGNUestambindenotadocomog++. ExistenotroscompiladoresmenoscomunesdeCyC++.Engeneraltodosloscompiladores mencionadosoperanesencialmentedelamismaformaycompartenmuchasopcionescomunesen lalneadeopciones.Msadelanteselistanysedanejemplosdeopcionescomunesdelos compiladores.Sinembargo,lamejorreferenciadecadacompiladoresatravsdelaspginasen lnea,delmanualdelsistema.Porejemplo:mangcc. Paracompilarelprogramausaremoselcomandogcc.Elcomandodeberserseguidoporel nombredelprogramaenCquesequierecompilar.Undeterminadonmerodeopcionesdel compiladorpuedenserindicadastambin.Porelmomentonoharemosusodeestasopciones todava,seirncomentandoalgunasmsesenciales. Porlotanto,elcomandobsicodecompilacines:
gccprograma.c

dondeprograma.ceselnombredelarchivo. Sihayerroresobviosenelprograma(talescomopalabrasmalescritas,caracteresnotecleadosu omisionesdepuntoycoma),elcompiladorsedetendrylosreportar. Podrahaberdesdeluegoerroreslgicosqueelcompiladornopodrdetectar.Enelcasoqueesta fueralasituacinseleestarindicandoalacomputadoraquehagalasoperacionesincorrectas. Cuandoelcompiladorhaterminadoconxito,laversincompilada,oelejecutable,esdejadoenun archivollamadoa.out,osilaopcinoesusadaconelcompilador,elnombredespusdeoesel nombredelprogramacompilado. Serecomiendayesmsconvenienteusarlaopcinoconelnombredelarchivoejecutablecomose muestraacontinuacin:
gccoprogramaprograma.c

elcualponeelprogramacompiladoenelarchivodelprogramasealado,enstecasoenprograma, envezdelarchivoa.out.

1.1.3Ejecucindelprograma
Elsiguienteestadoescorrerelprogramaejecutable.ParacorrerunejecutableenUNIX, simplementeseescribeelnombredelarchivoquelocontiene,enestecasoprograma(oa.out). Conloanterior,seejecutaelprograma,mostrandoalgnresultadoenlapantalla.Ensteestado,

podrahabererroresentiempodeejecucin(runtimeerrors),talescomodivisinporcero,obien, podranhacerseevidentesalverqueelprogramanoproducelasalidacorrecta. Siloanteriorsucede,entoncessedeberegresaraeditarelarchivodelprograma,recompilarlo,y ejecutarlonuevamente.

1.2ElmodelodecompilacindeC
Enlafigura1.1semuestranlasdistintastapasquecubreelcompiladorparaobtenerelcdigo ejecutable.

Figura1.1:ModelodecompilacindeC.

1.3Elpreprocesador
Estapartedelprocesodecompilacinsercubiertaconmsdetalleenelcaptulo12referenteal preprocesador.Sinembargo,sedaalgunainformacinbsicaparaalgunosprogramasdeC. Elpreprocesadoraceptaelcdigofuentecomoentradayesresponsablede:

quitarloscomentarios interpretarlasdirectivasdelpreprocesadorlascualesiniciancon#.

Porejemplo:

#includeincluyeelcontenidodelarchivonombrado.Estossonusualmentellamados archivosdecabecera(header).Porejemplo: #include<math.h>Archivodelabibliotecaestndardematemticas. #include<stdio.h>ArchivodelabibliotecaestndardeEntrada/Salida.

#definedefineunnombresimblicooconstante.Sustitucindemacros. #defineTAM_MAX_ARREGLO100

1.4CompiladordeC
ElcompiladordeCtraduceelcdigofuenteencdigodeensamblador.Elcdigofuenteesrecibido delpreprocesador.

1.5Ensamblador
Elensambladorcreaelcdigofuenteiolosarchivosobjeto.EnlossistemasconUNIXsepodrn verlosarchivosconelsufijo.o.

1.6Ligador
Sialgnarchivofuentehacereferenciaafuncionesdeunabibliotecaodefuncionesqueestn definidasenotrosarchivosfuentes,elligadorcombinaestasfunciones(conmain())paracrearun archivoejecutable.Lasreferenciasavariablesexternasenestatapasonresueltas.

1.7Algunasopciones tilesdelcompilador
Descritoelmodelobsicodecompilacin,sedarnalgunasopcionestilesyalgunasveces esenciales.Denuevacuenta,serecomiendarevisarlaspginasdemanparamayorinformaciny opcionesadicionales. E Secompiladorsedetieneenlatapadepreprocesamientoyelresultadosemuestraenla salidaestndar. gccEarch1.c c Suprimeelprocesodeligadoyproduceunarchivo.oparacadaarchivofuentelistado. Despuslosarchivosobjetopuedenserligadosporelcomandogcc,porejemplo: gccarch1.oarch2.o...oejecutable lbiblioteca Ligaconlasbibliotecasobjeto.Estaopcindeberseguirlosargumentosdelos

archivosfuente.Lasbibliotecasobjetosonguardadasypuedenestarestandarizadas,un terceroousuariolascrea.Probablementelabibliotecamscomnmenteusadaesla bibliotecamatemtica(math.h).Estabibliotecadeberligarseexplcitamentesise deseausarlasfuncionesmatemticas(yporsupuestonoolvidarelarchivocabecera #include<math.h>,enelprogramaquellamaalasfunciones),porejemplo: gcccalc.cocalclm Muchasotrasbibliotecassonligadasdeestaforma. Ldirectorio Agregadirectoriosalalistadedirectoriosquecontienenlasrutinasdelabibliotecade objetos.Elligadorsiemprebuscalasbibliotecasestndaresydelsistemaen/liby /usr/lib.Sisequierenligarbibliotecaspersonalesoinstaladasporusted,setendr queespecificardondeestanguardadoslosarchivos,porejemplo: gccprog.cL/home/minombr/mislibsmilib.a Itrayectoria Agregaunatrayectoriaorutaalalistadedirectoriosenloscualessebuscarnlos archivoscabecera#includeconnombresrelativos(esdecir,losquenoempiezancon diagonal/). Elprocesadorpordefault,primerobuscalosarchivos#includeeneldirectorioque contieneelarchivofuente,ydespusenlosdirectoriosnombradosconlaopcinIsi hubiera,yfinalmente,en/usr/include.Porlotanto,sisequiereincluirarchivosde cabeceraguardadosen/home/minombr/miscabecerassetendrquehacer: gccprog.cI/home/minombr/miscabeceras Nota:Lascabecerasdelasbibliotecasdelsistemasonguardadosenunlugarespecial (/usr/include)ynosonafectadasporlaopcinI.Losarchivoscabeceradel sistemaydelusuariosonincludosenunamaneraunpocodiferente. g Opcinparallamarlasopcionesdedepuracin(debug).Instruyealcompiladorpara producirinformacinadicionalenlatabladesmbolosqueesusadoporunavariedadde utilerasdedepuracin.Porejemplo,siseempleaeldepuradordeGNU,elprograma debercompilarsedelasiguienteformaparagenerarextensionesdeGDB: gccggdboprogprog.c D Definesmboloscomoidentificadores(Didentificador)ocomovalores (Dsmbolo=valor)enunaformasimilaraladirectivadelpreprocesador#define).

v Muestraenlasalidaestandardeerroresloscomandosejecutadosenlastapasde compilacin.

1.8Usodelasbibliotecas
Cesunlenguajeextremadamentepequeo.Muchasdelasfuncionesquetienenotroslenguajesno estnenC,porejemplo,nohayfuncionesparaE/S,manejodecadenasofuncionesmatemticas. LafuncionalidaddeCseobtieneatravsdeunricoconjuntodebibliotecasdefunciones. Comoresultado,muchasimplementacionesdeCincluyenbibliotecasestndardefuncionespara variasfinalidades.ParamuchospropsitosbsicosestaspodranserconsideradascomopartedeC. Peropuedenvariardemquinaamquina. Unprogramadorpuedetambindesarrollarsuspropiasfuncionesdebibliotecaeinclusobibliotecas especialesdeterceros,porejemplo,NAGoPHIGS. Todaslasbibliotecas(exceptoE/Sestndar)requierenserexplcitamenteligadasconlaopcinly, posiblementeconL,comosesealopreviamente.

1.9Ejemplos
1.9.1Creacindeunabibliotecaesttica
Sisetieneunconjuntoderutinasqueseusenenformafrecuente,sepodradesearagruparlasenun conjuntodearchivosfuente,compilarcadaarchivofuenteenunarchivoobjeto,yentoncescrearuna bibliotecaconlosarchivosobjeto.Conloanteriorsepuedeahorrartiempoalcompilarenaquellos programasdondeseanusadas. Supongamosquesetieneunconjuntodearchivosquecontenganrutinasquesonusadas frecuentemente,porejemplounarchivocubo.c:
floatcubo(floatx) { return(x*x*x); }

yotroarchivofactorial.c
intfactorial(intn) { inti,res=1; for(i=1;i<=n;i++) res*=i; return(res);

Paralosarchivosdenuestrasfuncionestambinsedebetenerunarchivodecabezera,paraque puedanserusadas,suponiendoquesetieneelsiguientearchivolibmm.hconelsiguiente contenido:


externfloatcubo(float); externintfactorial(int);

Elcdigoqueuselabibliotecaqueseestacreandopodraser:
/*Programaprueba.c*/ #include"libmm.h" #defineVALOR4 main() { printf("Elcubode%des%f\n",VALOR,cubo(VALOR)); printf("\tysufactoriales%d\n",factorial(VALOR)); }

Paracrearlabibliotecasedebencompilarlosarchivosfuente,quelopodemoshacerdelasiguiente forma:
$gccccubo.cfactorial.c

Locualnosdejarlosarchivoscubo.oyfactorial.o.Despussedebecrearlabibliotecaconlos archivosfuentes,suponiendoquenuestrabibliotecasellamelibmm.a,tendrsquehacerloconel comandoaras:


$arrlibmm.acubo.ofactorial.o

Cuandoseactualizaunabiblioteca,senecesitaborrarelarchivoanterior(libmm.a).Elltimo pasoescrearunndiceparalabiblioteca,loquepermitequeelligadorpuedaencontrarlasrutinas. Loanterior,lohacemosconelcomandoranlib,porloqueteclearemosahora:


$ranliblibmm.a

Losltimosdospasospudieronsercombinadosenunoslo,entonceshubieramospodidoteclear:
$arrslibmm.acubo.ofactorial.o

Ahoraqueyatenemoslabiblioteca,esconvenientequecoloquemosnuestrabibliotecayelarchivo cabezeraenalgnlugarapropiado.Supongamosquedejamoslabibliotecaen~/libyelfichero cabezeraen~/include,debemoshacerlosiguiente:


$mkdir../include $mkdir../lib $mvlibmm.h../include $mvlibmm.a../lib

Sillegarsamodificarlabiblioteca,tendrasquerepetirlaltimainstruccin. Sedebeahoracompilarelarchivoconlabiblioteca,delasiguienteforma:

gccI../includeL../libopruebaprueba.clmm

1.9.2Creacindeunabibliotecacompartida
Lasventajasquepresentanlasbibliotecascompartidas,eslareduccinenelconsumodememoria, sisonusadaspormsdeunproceso,ademsdelareduccindeltamaodelcdigoejecutable. Tambinsehaceeldesarrollomsfcil,yaquecuandosehacealgncambioenlabiblioteca,nose necesitarecompilaryreenlazarlaaplicacincadavez.Serequiereloanteriorslosisemodificoel nmerodeargumentosconlosquesellamaunafuncinosecambioeltamaodealguna estructura. Elcdigodelabibliotecacompartidanecesitaserindependientedelaposicin,parahacerposible queseausadoelcdigoporvariosprogramas.Paracrearlabibliotecahacerlodelasiguienteforma:
$gcccfPICcubo.cfactorial.c

Paragenerarlabibliotecadinmicahacerlosiguiente:
$gccsharedolibmm.socubo.ofactorial.o

Noexisteunpasoparalaindexacincomoocurreenlasbibliotecasestticas. Despushabrquemoverlabibliotecadinmicaasudirectoriocorrespondiente(../lib)y procederacompilarparaquenuestrocdigouselabiblioteca.


$gccI../includeL../libopruebaprueba.clmm

Nospreguntamosquesucedesihayunabibliotecacompartida(libmm.so)yunaesttica (libmm.a)disponibles.Enestecaso,elligadorsiempretomalacompartida.Sisedeseahaceruso delaesttica,setendrquenombrarexplcitamenteenlalneadecomandos:


$gccI../includeL../libopruebaprueba.clibmm.a

Cuandoseusanbibliotecascompartidasuncomandotilesldd,elcualnosinformaque bibliotecascompartidasunprogramaejecutableusa,acontinuacinunejemplo:
$lddprueba libstuff.so=>libstuff.so(0x40018000) libc.so.6=>/lib/i686/libc.so.6(0x4002f000) /lib/ldlinux.so.2=>/lib/ldlinux.so.2(0x40000000)

Comoseveencadalneaapareceelnombredelabiblioteca,elcaminocompletoalabibliotecaque esusada,ydondeenelespaciodedireccionesvirtualeslabibliotecaestamapeada. Silddmuestracomosalidanotfoundparaalgunabiblioteca,sevanatenerproblemasyel programanopodraserejecutado.Unaformadearreglarloesbuscarlabibliotecaycolocarlaenel lugarcorrectoparaqueelprogramaloaderlaencuentre,quesiemprebuscapordefaultenliby /usr/lib.Sisetienenbibliotecasenotrodirectorio,crearunavariabledeambiente LD_LIBRARY_PATHyponerlosdirectoriosseparadospor;.

1.10FuncionesdelabibliotecadeUNIX
ElsistemaUNIXdaungrannmerodefuncionesdeC.Algunasimplementanoperacionesdeuso frecuente,mientrasotrasestnmuyespecializadasenrelacinasuaplicacin. Noreinventelarueda.Serecomiendarevisarsiunafuncinenalgunabibliotecaexiste,envezde hacerlatareadeescribirsupropiaversin.Conloanteriorsereduceeltiempodedesarrollodeun programa.Yaquelasfuncionesdelabibliotecahansidoprobadas,porloqueestarncorregidas,a diferenciadecualquieraqueunprogramadorpuedaescribir.Loanteriorreducireltiempode depuracindelprograma.

1.10.1Encontrandoinformacinacercadelasbibliotecas.
ElmanualdeUNIXtieneunaentradaparatodaslasfuncionesdisponibles.Ladocumentacinde funcionesestaguardadaenlaseccin3delmanual,yhaymuchasotrastilesquehacenllamadasal sistemaenlaseccin2.Siyasabeelnombredelafuncinquesequiererevisar,puedeleerla pginatecleando: man3sqrt Sinosabeelnombredelafuncin,unalistacompletaestaincluidaenlapginaintroductoriadela seccin3delmanual.Paraleerlo,teclee: man3intro Hayaproximadamente700funciones.Elnmerotiendeaincrementarseconcadaactualizacinal sistema. Encualquierpginadelmanual,laseccindeSYNOPSISincluyeinformacindelusodela funcin.Porejemplo: #include<time.h> char*ctime(consttime_t*timep); Loquesignificaquesedebetener #include<time.h> enelarchivodelprogramaquehaceelllamadoactime.Yquelafuncinctimetomaun apuntadordeltipotime_tcomounargumento,yregresaunacadenachar*. EnlaseccinDESCRIPTIONsedaunapequeadescripcindeloquehacelafuncin.

1.11Ejercicios
1. Escribe,compilaycorreelsiguienteprograma.Modificaelprogramaparaqueincluyastu nombreylaformacomohicistesloanterior.Parainiciaruncomentariousa/*ypara terminarlo*/:
main() { inti; printf("\tNumero\t\tCubo\n\n"); for(i=0;i<=20;++i) printf("\t%d\t\t\t%d\n",i,i*i*i); }

2. Elsiguienteprogramausalabibliotecamatemtica.Teclalo,compilaloyejecutalo.Incluye concomentariosdentrodelprogramatunombreylaformacomohicistesloanterior.
#include<math.h> main() { inti; printf("\tAngulo\t\tSeno\n\n"); for(i=0;i<=360;i+=15) printf("\t%d\t\t\t%f\n",i,sin((double)i*M_PI/180.0)); }

3. Buscaenlosdirectorios/liby/usr/liblasbibliotecasqueestndisponibles.Manda3 nombresdeestticasy3decompartidas.

Useelcomandomanparaobtenerdetallesdelasfuncionesdelabiblioteca. Seleccionaalgunabibliotecayveloscdigosobjetosquecontiene,puedesteclear: artvbiblioteca

4. Veen/usr/includequearchivosdecabeceraestndisponibles. Usaloscomandosmoreocatparaverlosarchivosdetexto. Exploralosarchivoscabeceraparaverelcontenido,observandolasdirectivasde preprocesamientoinclude,define,lasdefinicionesdelostiposylosprototiposdelas funciones.Envia10casosdondesehayanusadolasdirectivasanteriores,indicando dequearchivodecabezeralasobtuvistes. 5. SupongamosquesetieneunprogramaenCelcualtienelafuncinprincipalenmain.cy quesetienenotrasfuncionesenlosarchivosinput.cyoutput.c: Dequformahabraquecompilaryligaresteprograma? Cmosedebernmodificarloscomandosanterioresparaligarunabiblioteca llamadaproceso1guardadaeneldirectorioestndardelasbibliotecasdel sistema? Cmomodificarasloscomandosanterioresparaligarunabibliotecallamada proceso2guardadaentudirectoriocasa? Algunosarchivoscabeceranecesitanserledosyencontradosenelsubdirectorio

headerdesudirectoriocasaytambinendirectoriodetrabajoactual.Cmose modificaranloscomandosdecompilacinparahacerlosealado?

Subsecciones 2.1OrgenesdelC 2.2CaractersticasdeC 2.3EstructuradeunprogramaenC 2.4Variables 2.4.1Definicindevariablesglobales 2.4.2Lecturayescrituradevariables


2.5Constantes 2.6OperadoresAritmticos 2.7OperadoresdeComparacin 2.8Operadoreslgicos 2.9Ordendeprecedencia 2.10Ejercicios

2.PrincipiosdeC
EnestecaptuloseofreceunabrevehistoriadeldesarrollodellenguajeCyseconsiderantambin suscaractersticas. EnelrestodelcaptulosevenlosaspectosbsicosdelosprogramasdeC,talescomosuestructura, ladeclaracindevariables,tiposdedatosyoperadores.

2.1OrgenesdelC
ElprocesodedesarrollodellenguajeCseoriginaconlacreacindeunlenguajellamadoBCPL, quefuedesarrolladoporMartinRichards.ElBCPLtuvoinfluenciaenunlenguajellamadoB,el cualseusen1970yfueinventadoporKenThompsonyquepermitieldesarrollodeCen1971,el cualloinventeimplementDennisRitchie.Para1973elsistemaoperativoUNIXestabacasi totalmenteescritoenC. DurantemuchosaoselestndarparaCfuelaversin5delsistemaoperativoUNIX,documentada en``TheCProgrammingLanguage''escritoporBrianW.KernighanandDennisM.Ritchiein1978 comnmentereferidocomoK&R. Posteriormentesehicieronvariasimplementacioneslascualesmostrabanlassiguientestendencias:

Nuevascaractersticas Diferenciasdemquinas Diferenciasdeproductos Erroresenloscompiladores Malasimplementaciones

Estooriginqueenelveranode1983seestablecierauncomitpararesolverestasdiscrepancias,el cualempezatrabajarenunestndarANSIC,lacualfuecompletadaen1988.

2.2CaractersticasdeC
Algunasdelascaractersticasmsimportantesquedefinenellenguajeyquehanpermitidoquesea tanpopular,comolenguajedeprogramacinson:

Tamaopequeo. Usoextensivodellamadasafunciones. Comandosbreves(pocotecleo). Lenguajeestructurado. Programacindebajonivel(nivelbit) Implementacindeapuntadoresusoextensivodeapuntadoresparalamemoria,arreglos, estructurasyfunciones

Lasdiversasrazonesporlacualsehaconvertidoenunlenguajedeusoprofesionalson:

Elusodeconstructoresdealtonivel. Elpodermanejaractividadesdebajonivel. Elgenerarprogramaseficientes. Laposibilidaddepodersercompiladoenunavariedaddecomputadoras,conpocoscambios (portabilidad).

Unpuntoencontraesquetieneunadeteccinpobredeerrores,locualenocasioneses problemticoparalosprincipiantes.

2.3EstructuradeunprogramaenC
UnprogramadeCtienebsicamentelasiguienteforma:

Comandosdelpreprocesador. Definicionesdetipos. Prototiposdefuncionesdeclaraeltipodefuncinylasvariablespasadasalamisma. Variables Funciones

Paraunprogramasedebetenerunafuncinmain(). Unafuncintienelaforma:
tiponombre_de_la_funcion(parmetros) { variableslocales sentenciasdeC

Siladefinicindeltipoesomitida,Casumequelafuncinregresauntipoentero.Nota:Lo anteriorpuedeserunafuentedeproblemasenunprograma. Acontinuacinsemuestraunprimerprograma:


/*Programaejemplo*/ main() { printf("MegustaC\n"); exit(0); }

NOTAS:

Crequiereunpuntoycomaalfinaldecadasentencia. printfesunafuncinestndardeC,lacualesllamadaenlafuncinmain(). \nsignificasaltodelnea.Salidaformateada. exit()estambinunafuncinestndarquehacequeelprogramatermine.Enelsentido estrictonoesnecesarioyaqueeslaltimalneademain()ydecualquierformaterminar elprograma.

Encasodequesehubierallamadoalafuncinprintfdelasiguienteforma:
printf(".\n.1\n..2\n...3\n");

Lasalidatendralasiguienteforma:
.1 ..2 ...3

2.4Variables
Ctienelossiguientestiposdedatossimples: Tabla2.1:TiposdeC Tipo char unsignedchar shortint unsignedshortint Tama o(bytes) Lmiteinferior Lmitesuperior 1 1 2 2

(long)int float double

4 4 8

Lostiposdedatosbsicostienevariosmodificadoresquelespreceden.Seusaunmodificadorpara alterarelsignificadodeuntipobaseparaqueencajeconlasdiversasnecesidadesosituaciones.Los modificadoresson:signed,unsigned,longyshort. EnlossistemasUNIXtodoslostiposintsonlongint,amenosqueseespecifique explcitamenteshortint. Nota:nohayuntipobooleanoenCsedeberusarchar,intoanmejorunsignedchar. signed,unsigned,longyshortpuedenserusadosconlostiposchareint.Aunquees permitidoelusodesignedenenteros,esredundanteporqueladeclaracindeenteropordefecto asumeunnmeroconsigno. ParadeclararunavariableenC,sedebeseguirelsiguienteformato: tipolista_variables; tipoesuntipovlidodeCylista_variablespuedeconsistirenunoomsindentificadores separadosporunacoma.Unidentificadordebecomenzarconunaletraounguinbajo. Ejemplo:
inti,j,k; floatx,y,z; charch;

2.4.1Definicindevariablesglobales
Unavaribleglobalsedeclarafueradetodaslasfunciones,incluyendoalafuncinmain().Una variableglobalpuedeserutilizadaencualquierpartedelprograma. Porejemplo:
shortnumero,suma; intnumerogr,sumagr; charletra; main() { ... }

Estambinposiblepreinicializarvariablesglobalesusandoeloperadordeasignacin=,por ejemplo:
floatsuma=0.0; intsumagr=0; charletra='A'; main() { ... }

Queeslomismoque:
floatsuma; intsumagr; charletra; main() { suma=0.0; sumagr=0; letra='A'; ... }

DentrodeCtambinsepermitelaasignacinmltipleusandoeloperador=,porejemplo:
a=b=c=d=3;

...queeslomismo,peromseficienteque:
a=3; b=3; c=3; d=3;

Laasignacinmltiplesepuedellevaracabo,sitodoslostiposdelasvariablessoniguales. SepuedenredefinirlostiposdeCusandotypedef.Comounejemplodeunsimpleusose consideracomosecreandosnuevostiposrealyletra.Estosnuevostipospuedenserusadosdeigual formacomolostipospredefinidosdeC.


typedeffloatreal; typedefcharletra; /*Declaraciondevariablesusandoelnuevotipo*/ realsuma=0.0; letrasig_letra;

2.4.2Lecturayescrituradevariables
EllenguajeCusasalidaformateada.Lafuncinprintftieneuncaracterespecialparaformatear (%)uncaracterenseguidadefineunciertotipodeformatoparaunavariable.

%ccaracteres %scadenadearacteres %denteros %fflotantes Porejemplo:


printf("%c%d%f",ch,i,x);

Lasentenciadeformatoseencierraentre"",yenseguidalasvariables.Asegurarsequeelorden deformateoylostiposdedatosdelasvariablescoincidan. scanf()eslafuncinparaentrarvaloresavariables.Suformatoessimilaraprintf.Por ejemplo:


scanf("%c%d%f%s",&ch,&i,&x,cad);

Observarqueseantepone&alosnombresdelasvaribles,exceptoalacadenadecaracteres.Enel captulo8quetratasobreapuntadoresserevisarmsafondoelusodeesteoperador.

2.5Constantes
ANSICpermitedeclararconstantes.Cuandosedeclaraunaconstanteesunpocoparecidoa declararunavariable,exceptoqueelvalornopuedesercambiado. Lapalabraclaveconstseusaparadeclararunaconstante,comosemuestraacontinuacin:
consta=1; inta=2;

Notas:

Sepuedeusarconstantesodespusdeltipo. Esusualinicializarunaconstanteconunvalor,yaquenopuedesercambiadadealgunaotra forma.

Ladirectivadelpreprocesador#defineesunmtodomsflexibleparadefinirconstantesenun programa. Frecuentementeseveladeclaracinconstenlosparmetrosdelafuncin.Loanterior simplementeindicaquelafuncinnocambiaraelvalordelparmetro.Porejemplo,lasiguiente funcinusaesteconcepto: char*strcpy(char*dest,constchar*orig); ElsegundoargumentoorigesunacadenadeCquenoseralterada,cuandoseuselafuncinde labibliotecaparacopiarcadenas.

2.6OperadoresAritmticos
Lomismoqueenotroslenguajesdeprogramacin,enCsetienenlosoperadoresaritmticosms usuales(+suma,resta,*multiplicacin,/divisiny%mdulo). Eloperadordeasignacines=,porejemplo:i=4;ch='y'; Incremento++ydecrementounario.Loscualessonmseficientesquelasrespectivas asignaciones.Porejemplo:x++esmsrpidoquex=x+1. Losoperadores++ypuedenserprefijosopostfijos.Cuandosonprefijos,elvalorescalculado antesdequelaexpresinseaevaluada,ycuandoespostfijoelvalorescalculadodespusquela expresinesevaluada. Enelsiguienteejemplo,++zesprefijoyespostfijo:
intx,y,z; main() { x=((++z)(y))%100; }

Queesequivalentea:
intx,y,z; main() { z++; x=(zy)%100; y; }

Eloperador%(mdulooresiduo)solamentetrabajaconenteros,aunqueexisteunafuncinpara flotantes(15.1fmod())delabibliotecamatemtica. Eloperadordivisin/esparadivisinenterayflotantes.Porlotantohayquetenercuidado.El resultadodex=3/2;esuno,ansixesdeclaradocomofloat.Lareglaes:siambos argumentosenunadivisinsonenteros,entoceselresultadoesentero.Sisedeseaobtenerla divisinconlafraccin,entoncesescribirlocomo:x=3.0/2;ox=3/2.0yan mejorx=3.0/2.0. Porotraparte,existeunaformamscortaparaexpresarclculosenC.Porejemplo,sisetienen expresionescomo:i=i+3;ox=x*(y+2);,puedenserreescritascomo: Locualesequivalente,peromenoseficienteque:

Porloquepodemosreescribirlasexpresionesanteriorescomo:i+=3;yx*=y+2; respectivamente.

2.7OperadoresdeComparacin
Eloperadorparaprobarlaigualdades==,porloquesedebertenercuidadodenoescribir accidentalmenteslo=,yaque: if(i=j)... EsunasentencialegaldeC(sintcticamentehablandoaunqueelcompiladoravisacuandose emplea),lacualcopiaelvalorde``j''en``i'',locualserinterpretadocomoVERDADERO,sij esdiferentedecero. Diferentees!=,otrosoperadoresson:<menorque,>mayorque,<=menorqueoigualay>= (mayorqueoiguala).

2.8Operadoreslgicos
Losoperadoreslgicossonusualmenteusadosconsentenciascondicionalesorelacionales,los operadoresbscioslgicosson: &&Ylgico,||Olgicoy!negacin.

2.9Ordendeprecedencia
Esnecesariosercuidadososconelsignificadodeexpresionestalescomoa+b*c, dependiendodeloquesedeseehacer (a+b)*c o a+(b*c) Todoslosoperadorestienenunaprioridad,losoperadoresdemayorprioridadsonevaluadosantes quelosquetienenmenorprioridad.Losoperadoresquetienenlamismaprioridadsonevaluadosde izquierdaaderecha,porloque: abc esevaluadocomo (ab)c

Prioridad Operador(es) Msalta ()[]> !~++(tipo)*&sizeof */% + <<>> <<=>>= ==!= & ^ | && || ? =+==*=/= Msbaja , Deacuerdoaloanterior,lasiguienteexpresin: a<10&&2*b<c Esinterpretadacomo: (a<10)&&((2*b)<c) y
a= b= 10/5 +2;

como
a= (b= (10/5) +2);

2.10Ejercicios
EscribirprogramasenCparahacerlassiguientestareas:

1. Leerlaentradadedosnmerosymostrareldobleproductodelprimeromenoslamitaddel segundo. 2. Leayescribasunombre,apellidopaterno,apellidomaternoymatriculaenunformato adecuado. 3. Escribirunprogramaparaleerun``flotante''querepresentaunnmerodegradosCelsius,e imprimecomoun``flotante''latemperaturaequivalenteengradosFahrenheit.Lasalida puedeserdelasiguienteforma:100.0gradosCelsiusson212.0grados Fahrenheit. 4. Escribirunprogramaparaimprimirvariasveceselejercicio2.Puedeusarvarias instruccionesprintf,conuncaracterdenuevalneaencadauna,ounainstruccinconvarios caracteresnuevalneaenlacadenadeformateo. 5. Escribirunprogramaqueleaelradiodeuncrculocomounnmeroflotanteymuestreel reayelpermetrodelcrculo. 6. Dadosciertoscentmetroscomoentradadetipoflotante,imprimirsuequivalenciaapies (enteros)ypulgadas(flotante,1decimal),dandolaspulgadasconunaprecisindeunlugar decimalSuponer2.54centmetrosporpulgada,y12pulgadasporpie. Silaentradaes333.3,elformatodelasalidadeberser: 333.3centmetrosson10pies11.2pulgadas.

Subsecciones

3.1Lasentencia if 3.2Eloperador ? 3.3Lasentencia switch 3.4Ejercicios

3.EstructurasCondicionales
EnestecaptuloserevisanlosdistintosmtodosconlosqueCcontrolaelflujolgicodeun programa. Comoserevisenelcaptuloanterior,losoperadoresrelacionesbinariosqueseusanson: ==,!=,<,<=,>y>= ademslosoperadoreslgicosbinarios: ||,&& yeloperadorlgicounariodenegacin!,queslotomaunargumento. Losoperadoresanteriorsonusadosconlassiguientesestructurasquesemuestran.

3.1Lasentenciaif
Lastresformascomosepuedeemplearlasentenciaifson: if(condicion) sentencia; ...o if(condicion) sentencia1; else sentencia2; ...o

if(condicion1) sentencia1; elseif(condicion2) sentencia2; ... else sentencian; Elflujolgicodeestaestructuraesdearribahaciaabajo.Laprimerasentenciaseejecutaryse saldrdelaestructuraifsilaprimeracondicinesverdadera.Silaprimeracondicinfuefalsa,y existeotracondicin,seevala,ysilacondicinesverdadera,entoncesseejecutalasentencia asociada.Siexistenmscondicionesdentrodelaestructuraif,sevanevaluandostas,siemprey cuandolascondicionesqueleprecedanseanfalsas. Lasentenciaqueestaasociadaalapalabrareservadaelse,seejecutasitodaslascondicionesdela estructuraiffueronfalsas. Porejemplo:
main() { intx,y,w; ........ if(x>0) { z=w; ....... } else { z=y; ....... } }

3.2Eloperador?
Eloperadorternariocondicional?esmseficientequelasentenciaif.Eloperador?tieneel siguienteformato: expresion1?expresion2:expresion3; Queesequivalentealasiguienteexpresin: if(expresion1)thenexpresion2elseexpresion3;

Porejemplo,paraasignarelmximodeaybalavariablez,usando?,tendramos: z=(a>b)?a:b; queeslomismoque:


if(a>b) z=a; else z=b;

Elusodeloperador?parareemplazarlassentenciasif...elsenoserestringesloa asignaciones,comoenelejemploanterior.Sepuedenejecutarunaomsllamadasdefuncin usandoeloperador?ponindolasenlasexpresionesqueformanlosoperandos,comoenelejemplo siguiente:


f1(intn) { printf("%d",n); } f2() { printf("introducido\n"); } main() { intt; printf(":"); scanf("%d",&t); /*imprimemensajeapropiado*/ t?f1(t)+f2():printf("Sediuncero\n"); }

3.3Lasentenciaswitch
Aunqueconlaestructuraif...elseifsepuedenrealizarcomprobacionesmltiples,en ocasionesnoesmuyelegante,yaqueelcdigopuedeserdifcildeseguirypuedeconfundirincluso alautortranscurridountiempo.Porloanterior,Ctieneincorporadaunasentenciadebifurcacin mltiplellamadaswitch.Conestasentencia,lacomputadoracompruebaunavariable sucesivamentefrenteaunalistadeconstantesenterasodecaracter.Despusdeencontraruna coincidencia,lacomputadoraejecutalasentenciaobloquedesentenciasqueseasocianconla constante.Laformageneraldelasentenciaswitches: switch(variable){ caseconstante1: secuenciadesentencias break;

caseconstante2: secuenciadesentencias break; caseconstante3: secuenciadesentencias break; ... default: secuenciadesentencias } dondelacomputadoraejecutalasentenciadefaultsinocoincideningunaconstanteconla variable,estaltimaesopcional.Cuandoseencuentraunacoincidencia,lacomputadoraejecutalas sentenciasasociadasconelcasehastaencontrarlasentenciabreakconloquesaledela estructuraswitch. Laslimitacionesquetienelasentenciaswitch...caserespectoalaestructuraifson:

Slosetieneposibilidadderevisarunasolavariable. Conswitchslosepuedecomprobarporigualdad,mientrasqueconifpuedesercon cualquieroperadorrelacional. Nosepuedeprobarmsdeunaconstanteporcase.

Laformacomosepuedesimularelltimopunto,esnoteniendosentenciasasociadosauncase, esdecir,teniendounasentencianuladondesloseponeelcaso,conloquesepermitequeelflujo delprogramacaigaalomitirlassentencias,comosemuestraacontinuacin:


switch(letra) { case'a': case'e': case'i': case'o': case'u': numvocales++; break; case'': numesp++; break; default: numotras++; break; }

3.4Ejercicios
1. Escribirunprogramaqueleadoscaracteres,eimprimasuvalorcuandosepuedainterpretar comounnmerohexadecimal.Aceptarletrasmaysculasyminsculasparalosvaloresdel 10al15. 2. Leerunvalorentero.Suponerqueelnmeroesundadelasemana.Suponerque0 correspondeaDomingoyassucesivamente.Imprimirelnombredelda. 3. Dadoscomoentrada3enterosrepresentandolafechacomoda,mes,ao,imprimirlafecha deldaanterior.Porejemploparaunaentradacomo:131992Lasalidaser:Fechaanterior a131992es29021992 4. Escribirunprogramaelcualleadosvaloresenteros.Sielprimeroesmenorqueelsegundo, queimprimaelmensaje``Arriba''.Sielsegundoesmenorqueelprimero,queimprimael mensaje``Abajo''.Silosnmerossoniguales,queimprimaelmensaje``igual''.Sihayun errorenlalecturadelosdatos,queimprimaunmensajeconteniendolapalabra``Error''y hagaexit(0);

Subsecciones

4.1Lasentencia for 4.2Lasentencia while 4.3Lasentencia dowhile 4.4Usode break y continue 4.5Ejercicios

4.Iteracin
EnestecaptuloserevisanlosmecanismosdeCpararepetiruncojuntodeinstruccioneshastaque secumpleciertacondicin.

4.1Lasentenciafor
Lasentenciafortieneelsiguienteformato: for(expresion1;expresion2;expresion3) sentencia; o{bloquedesentencias} Endondeexpresion1seusapararealizarlainicializacindevariables,usandounaovarias sentencias,siseusanvariassentenciasdeberusarseeloperador,parasepararlas.Porlogeneral, estableceelvalordelavariabledecontroldelciclo.expresion2seusaparalacondicinde terminacindelcicloyexpresion3eselmodificadoralavariabledecontroldelciclocadavez quelacomputadoralorepite,perotambinpuedesermsqueunincremento. Porejemplo:
intX; main() { for(X=3;X>0;X) { printf("X=%d\n",X); } }

generalasiguientesalidaapantalla...
X=3 X=2 X=1

TodoslassiguientessentenciasforsonvlidasenC.Lasaplicacionesprcticasdetalessentencias

nosonimportantesaqu,yaquetansloseintentailustraralguanascaractersticasquepuedenser deutilidad:
for(x=0;((x>3)&&(x<9));x++) for(x=0,y=4;((x>3)&&(x<9));x++,y+=2) for(x=0,y=4,z=4000;z;z/=10)

Enelsegundoejemplosemuestralaformacomomltiplesexpresionespuedenaparecer,siemprey cuandoestnseparadasporunacoma, Eneltercerejemplo,elciclocontinuariterandohastaquezseconviertaen .

4.2Lasentenciawhile
LasentenciawhileesotrocicloobucledisponibleenC.Suformatoes: while(expresion)sentencia; dondesentenciapuedeserunasentenciavaca,unasentencianicaounbloquedesentenciasquese repetirn.Cuandoelflujodelprogramallegaaestainstruccin,primeroserevisasilacondicines verdadparaejecutarla(s)sentencia(s),ydespuselciclowhileserepetirmientraslacondicin seaverdadera.Cuandollegaaserfalsa,elcontroldelprogramapasaalalneaquesiguealciclo. Enelsiguienteejemplosemuetraunarutinadeentradadesdeelteclado,lacualseciclamientrasno sepulseA:
main() { charcarac; carac='\0'; while(carac!='A')carac=getchar(); }

Antesdeentraralcicloseinicializalavariablecaracanulo.Despuspasaalasentenciawhile dondesecompruebasicaracnoesiguala'A',comoseaverdadentoncesseejecutalasentencia delbucle(carac=getchar();).Lafuncingetchar()leeelsiguientecarcterdelflujo estndar(teclado)ylodevuelve,queennuestroejemploeselcaracterquehayasidotecleado.Una vezquesehapulsadounatecla,seasignaacaracysecompruebalacondicinnuevamente. DespusdepulsarA,lacondicinllegaaserfalsaporquecaracesigualaA,conloqueelciclo termina. Deloanterior,setienequetantoelciclofor,comoelciclowhilecompruebanlacondicinenlo altodelciclo,porloqueelcdigodentrodelciclonoseejecutasiempre. Acontinuacinmostramosotroejemplo:
main() { intx=3;

while(x>0) { printf("x=%d\n",x); x; } }

quegeneralasiguientesalidaenpantalla:
x=3 x=2 x=1

Comoseobserva,dentrodelciclotenemosmsdeunasentencia,porloqueserequiereusarlallave abiertaylallavecerrada{...}paraqueelgrupodesentenciasseantratadascomounaunidad. Comoelciclowhilepuedaaceptartambinexpresiones,ynosolamentecondicioneslosiguiente esvlido:


while(x); while(x=x+1); while(x+=5);

Siseusanestetipodeexpresiones,solamentecuandoelresultadodex,x=x+1ox+=5sea cero,lacondicinfallarysepodrsalirdelciclo. Deacuerdoaloanterior,podemosrealizarunaoperacincompletadentrodelaexpresin.Por ejemplo:


main() { charcarac; carac='\0'; while((carac=getchar())!='A') putchar(carac); }

Enesteejemploseusanlasfuncionesdelabibliotecaestndargetchar()leeuncaracterdel tecladoyputchar()escribeuncaracterdadoenpantalla.Elciclowhileprocederaleerdel tecladoylomostrarhastaqueelcaracterAsealedo.

4.3Lasentenciadowhile
Alcontrariodelosciclosforywhilequecompruebanlacondicinenloaltodelbucle,elbucle do...whilelaexaminaenlapartebajadelmismo.Estacaractersticaprovocaqueunciclo do...whilesiempreseejecutealmenosunavez.Laformageneraldelcicloes: do{ sentencia;

}while(condicin); Aunquenosonnecesariaslasllavescuandosloestpresenteunasentencia,seusannormalmente porlegibilidadyparaevitarconfusin(respectoallector,ynodelcompilador)conlasentencia while. Enelsiguienteprogramaseusaunciclodo...whileparaleernmerosdesdeeltecladohasta queunodeellosesmenorqueoiguala100:


main() { intnum; do { scanf("%d",&num); }while(num>100); }

Otrousocomndelaestructurado...whileesunarutinadeseleccinenunmen,yaque siempreserequierequeseejecutealmenosunavez.
main() { intopc; printf("1.Derivadas\n"); printf("2.Limites\n"); printf("3.Integrales\n"); do { printf("Teclearunaopcion:"); scanf("%d",&opc); switch(opc) { case1: printf("\tOpcion1seleccionada\n\n"); break; case2: printf("\tOpcion2seleccionada\n\n"); break; case3: printf("\tOpcion3seleccionada\n\n"); break; default: printf("\tOpcionnodisponible\n\n"); break; } }while(opc!=1&&opc!=2&&opc!=3); }

Semuestraunejemplodondesereescribeusandodo...whileunodelosejemplosya mostrados.
main() { intx=3; do

{ printf("x=%d\n",x); } while(x>0); }

4.4Usodebreakycontinue
Comosecomentounodelosusosdelasentenciabreakesterminaruncaseenlasentencia switch.Otrousoesforzarlaterminacininmediatedeunciclo,saltandolapruebacondicional delciclo. Cuandoseencuentralasentenciabreakenunbucle,lacomputadoraterminainmediatamenteel cicloyelcontroldelprogramapasaalasiguientesenteciadelciclo.Porejemplo:
main() { intt; for(t=0;t<100;t++) { printf("%d",t); if(t==10)break; } }

Esteprogramamuestraenpantallalosnmerosdel0al10,cuandoalcanzaelvalor10secumplela condicindelasentenciaif,seejecutalasentenciabreakysaledelciclo. Lasentenciacontinuefuncionademanerasimilaralasentenciabreak.Sinembargo,envezde forzarlasalida,continuefuerzalasiguienteiteracin,porloquesaltaelcdigoquefaltapara llegaraprobarlacondicin.Porejemplo,elsiguienteprogramavisualizarslolosnmerospares:


main() { intx; for(x=0;x<100;x++) { if(x%2) continue; printf("%d",x); } }

Finalmenteseconsideraelsiguienteejemplodondeseleenvaloresenterosyseprocesandeacuerdo alassiguientescondiciones.Sielvalorquesealedoesnegativo,sedeseaimprimirunmensajede erroryseabandonaelciclo.Sielvaloresmayorque100,seignoraysecontinualeyendo,ysiel valorescero,sedeseaterminarelciclo.


main() { intvalor; while(scanf("%d",&valor)==1&&valor!=0) { if(valor<0)

{ printf("Valornovalido\n"); break; /*Salirdelciclo*/ } if(valor>100) { printf("Valornovalido\n"); continue; /*Pasaralprincipiodelciclonuevamente*/ } printf("Segarantizaqueelvalorleidoestaentre1y100"); } }

4.5Ejercicios
1. Escribirunprogramaquelea5nmerosyencuentreelpromedio,elmximoyelmnimode esosvalores. 2. Escribirunprogramaqueleanmeroshastaqueseencuentreelcero.Elsegundonmerose sumaralprimero,luegoelterceroserestar,elcuartosesumar,yassedeberseguir alternadohastaqueselleguealcero.Cuandosellegueaestacondiciondeberimprimirel resultado,eltotaldeoperandosdelaoperacin(sinincluirelcero),ylasumadelos operandosqueserestaron. 3. Escribirunprogramaqueleaunvalorenteroqueserlabaseparaunsistemanumrico (binario,octalodecimal),despusqueleaunenteropositivoenesabaseyqueimprimasu valorenbase10.Sedebevalidarqueelnmeropertenezcaaesabase.Labasesermenor queoiguala10.Elprogramapodratenerlasiguientesalida:
EntradaSalida BaseNumero ======================= 1012341234 87763 2111115

4. Escribirunprogramaqueleaunnmeroenbase10yloconviertaabase2,base8ybase hexadecimal. 5. Leertresvaloresrepresentandolosiguiente: Elcapital(nmeroenterodepesos) Unatasadeinteresenporciento(flotante) yunnmerodeaos(entero). Calcularlosvaloresdelasumadelcapitalyelinterescompuestoparaunperododadode aos.Paracadaaoelinteresescalculadocomo:interes=capital* tasa_interes/100; elcualsesumaalcapital capital+=interes;

Imprimirlosvaloresdemonedaconunaprecisindedosdecimales.Imprimirlosvalores delinterscompuestoparacadaaoalfinaldelperodo.Lasalidapuedesercomola siguiente:


Capitalinicial35000.00contasadel12.50en10aos AoInteresSuma ++ 14375.0039375.00 24921.8844296.88 35537.1149833.98 46229.2556063.23 57007.9063071.14 67883.8970955.03 78869.3879824.41 89978.0589802.45 911225.31101027.76 1012628.47113656.23

6. Leerunvalorpositivo,yhacerlasiguientesecuencia:sielnmeroespar,dividirloentre2; siesnon,multiplicarlopor3ysumarle1.Repetirloanteriorhastaqueelvalorsea1, imprimiendocadavalor,tambinsedeberimprimircuantasoperacionesdeestasson hechas. Unasalidapodraserlasiguiente:


Elvaloriniciales9 Elsiguientevalores28 Elsiguientevalores14 Elsiguientevalores7 Elsiguientevalores22 Elsiguientevalores11 Elsiguientevalores34 Elsiguientevalores17 Elsiguientevalores52 Elsiguientevalores26 Elsiguientevalores13 Elsiguientevalores40 Elsiguientevalores20 Elsiguientevalores10 Elsiguientevalores5 Elsiguientevalores16 Elsiguientevalores8 Elsiguientevalores4 Elsiguientevalores2 Valorfina11,numerodepasos19.

Sielvaloringresadoesmenorque1,imprimirunmensajequecontengalapalabra Error yhaga exit(0)

Subsecciones

5.1Arreglosunidimensionalesymultidimensionales 5.2Cadenas 5.3Ejercicios

5.Arreglosycadenas
Enelsiguientecaptulosepresentanlosarreglosylascadenas.Lascadenasseconsiderancomoun arreglodetipochar.

5.1Arreglosunidimensionalesy multidimensionales
Losarreglossonunacoleccindevariablesdelmismotipoquesereferencianutilizandounnombre comn.Unarregloconstadeposicionesdememoriacontigua.Ladireccinmsbajacorrespondeal primerelementoylamsaltaalltimo.Unarreglopuedetenerunaovariasdimensiones.Para accederaunelementoenparticulardeunarregloseusaunndice. Elformatoparadeclararunarreglounidimensionales: tiponombre_arr[tama o] Porejemplo,paradeclararunarreglodeenterosllamadolistanumcondiezelementossehacedela siguienteforma:
intlistanum[10];

EnC,todoslosarreglosusancerocomondiceparaelprimerelemento.Portanto,elejemplo anteriordeclaraunarreglodeenteroscondiezelementosdesdelistanum[0]hastalistanum[9]. Laformacomopuedenseraccesadosloselementosdeunarreglo,esdelasiguienteforma:


listanum[2]=15;/*Asigna15al3erelementodelarreglolistanum*/ num=listanum[2];/*Asignaelcontenidodel3erelementoalavariablenum*/

EllenguajeCnorealizacomprobacindecontornosenlosarreglos.Enelcasodequesobrepaseel finalduranteunaoperacindeasignacin,entoncesseasignarnvaloresaotravariableoauntrozo delcdigo,estoes,sisedimensionaunarreglodetamaoN,sepuedereferenciarelarreglopor encimadeNsinprovocarningnmensajedeerrorentiempodecompilacinoejecucin,incluso

aunqueprobablementeseprovoqueelfallodelprograma.Comoprogramadorseesresponsablede asegurarquetodoslosarreglosseanlosuficientementegrandesparaguardarloquepondrenellos elprograma. Cpermitearreglosconmsdeunadimensin,elformatogenerales: tiponombre_arr[tam1][tam2]...[tamN]; Porejemplounarreglodeenterosbidimensionalesseescribircomo:


inttabladenums[50][50];

Observarqueparadeclararcadadimensinllevasuspropiosparntesiscuadrados. Paraaccederloselementosseprocededeformasimilaralejemplodelarreglounidimensional,esto es,


tabladenums[2][3]=15;/*Asigna15alelementodela3filayla4columna*/ num=tabladenums[25][16];

Acontinuacinsemuestraunejemploqueasignaalprimerelementodeunarreglobidimensional cero,alsiguiente1,yassucesivamente.
main() { intt,i,num[3][4]; for(t=0;t<3;++t) for(i=0;i<4;++i) num[t][i]=(t*4)+i*1; for(t=0;t<3;++t) { for(i=0;i<4;++i) printf("num[%d][%d]=%d",t,i,num[t][i]); printf("\n"); } }

EnCsepermitelainicializacindearreglos,debiendoseguirelsiguienteformato: tiponombre_arr[tam1][tam2]...[tamN]={listavalores}; Porejemplo:


inti[10]={1,2,3,4,5,6,7,8,9,10}; intnum[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

5.2Cadenas
Adiferenciadeotroslenguajesdeprogramacinqueempleanuntipodenominadocadenastring paramanipularunconjuntodesimbolos,enC,sedebesimularmedianteunarreglodecaracteres,

endondelaterminacindelacadenasedebeindicarconnulo.Unnuloseespecificacomo'\0'. Porloanterior,cuandosedeclareunarreglodecaracteressedebeconsideraruncarcteradicionala lacadenamslargaquesevayaaguardar.Porejemplo,sisequieredeclararunarreglocadena queguardeunacadenadediezcaracteres,seharcomo:


charcadena[11];

SepuedenhacertambininicializacionesdearreglosdecaracteresendondeautomticamenteC asignaelcaracternuloalfinaldelacadena,delasiguienteforma: charnombre_arr[tam]="cadena"; Porejemplo,elsiguientefragmentoinicializacadenacon``hola'':


charcadena[5]="hola";

Elcdigoanterioresequivalentea:
charcadena[5]={'h','o','l','a','\0'};

Paraasignarlaentradaestndaraunacadenasepuedeusarlafuncinscanfconlaopcin%s (observarquenoserequiereusareloperador&),deigualformaparamostrarloenlasalidaestndar. Porejemplo:


main() { charnombre[15],apellidos[30]; printf("Introducetunombre:"); scanf("%s",nombre); printf("Introducetusapellidos:"); scanf("%s",apellidos); printf("Ustedes%s%s\n",nombre,apellidos); }

EllenguajeCnomanejacadenasdecaracteres,comosehaceconenterosoflotantes,porloquelo siguientenoesvlido:
main() { charnombre[40],apellidos[40],completo[80]; nombre="JosMara";/*Ilegal*/ apellidos="MorelosyPavn";/*Ilegal*/ completo="Gral."+nombre+appellidos;/*Ilegal*/ }

5.3Ejercicios
1. Escribirunprogramaqueleaunarreglodecualquiertipo(entero,flotante,char),sepodra pediralusuarioqueindiqueeltipodearreglo,ytambinescribirunprogramaquereviseel arregloparaencontrarunvalorenparticular.

2. Leeruntexto,uncaracteralavezdesdelaentradaestndar(queeselteclado),eimprimir cadalneaenformainvertida.Leerhastaqueseencuentreunfinaldedatos(teclar CONTROLDparagenerarlo). Elprogramapodraprobarsetecleandoprogrev|progrevparaversiunacopia exactadelaentradaoriginalesrecreada. Paraleercaractereshastaelfinaldedatos,sepuedeusarunciclocomoelsiguiente


charch; while(ch=getchar(),ch>=0)/*ch<0indicafindedatos*/

o
charch; while(scanf("%c",&ch)==1)/*seleeuncaracter*/

3. Escribirunprogramaparaleeruntextohastaelfindedatos,ymostrarunaestadsticadelas longitudesdelaspalabras,estoes,elnmerototaldepalabrasdelongitud1quehayan ocurrido,eltotaldelongitud2yassucesivamente. Defineunapalabracomounasecuenciadecaracteresalfabticos.Sedebernpermitir palabrashastadeunalongitudde25letras. Unasalidatpicapodrasercomoesta:


longitud1:16ocurrencias longitud2:20ocurrencias longitud3:5ocurrencias longitud4:2ocurrencias longitud5:0ocurrencias ........

Subsecciones

6.1Funciones void 6.2Funcionesyarreglos 6.3Prototiposdefunciones 6.4Ejercicios

6.Funciones
Unafuncinesunconjuntodedeclaraciones,definiciones,expresionesysentenciasquerealizan unatareaespecfica. ElformatogeneraldeunafuncinenCes especificador_de_tiponombre_de_funcin(lista_de_parmetros) { variableslocales cdigodelafuncin } Elespecificador_de_tipoindicaeltipodelvalorquelafuncindevolvermedianteelusode return.Elvalorpuedeserdecualquiertipovlido.Sinoseespecficaunvalor,entoncesla computadoraasumepordefectoquelafuncindevolverunresultadoentero.Nosetienensiempre queincluirparmetrosenunafuncin.lalistadeparmetrospuedeestarvaca. Lasfuncionesterminanyregresanautomticamentealprocedimientoquelasllamcuandose encuentralaltimallave},obien,sepuedeforzarelregresoantesusandolasentenciareturn. Ademasdelusosealadolafuncinreturnseusaparadevolverunvalor. Seexaminaacontinuacinunejemploqueencuentraelpromediodedosenteros:
floatencontprom(intnum1,intnum2) { floatpromedio; promedio=(num1+num2)/2.0; return(promedio); } main() { inta=7,b=10; floatresultado;

resultado=encontprom(a,b); printf("Promedio=%f\n",resultado); }

6.1Funcionesvoid
Lasfuncionesvoiddanunaformadeemular,loqueenotroslenguajesseconocencomo procedimientos(porejemplo,enPASCAL).Seusancuandonorequiereregresarunvalor.Se muestraunejemploqueimprimeloscuadradosdeciertosnmeros.
voidcuadrados() { intcontador; for(contador=1;contador<10;contador++) printf("%d\n",contador*contador); } main() { cuadrados(); }

Enlafuncincuadradosnoestadefinidoningnparmetro,yporotrapartetampocoseempleala sentenciareturnpararegresardelafuncin.

6.2Funcionesyarreglos
Cuandoseusanunarreglocomounargumentoalafuncin,sepasasloladireccindelarregloy nolacopiadelarregloentero.Parafinesprcticospodemosconsiderarelnombredelarreglosin ningnndicecomoladireccindelarreglo. Considerarelsiguienteejemploendondesepasaunarregloalafuncinimp_rev,observarque noesnecesarioespecificarladimensindelarreglocuandoesunparmetrodelafuncin.
voidimp_rev(chars[]) { intt; for(t=strlen(s)1;t>=0;t) printf("%c",s[t]); } main() { charnombre[]="Facultad"; imp_rev(nombre); }

Observarqueenlafuncinimp_revseusalafuncinstrlenparacalcularlalongituddela cadenasinincluirelterminadornulo.Porotraparte,lafuncinimp_revnousalasentencia returnniparaterminardeusarlafuncin,nipararegresaralgnvalor.

Semuestraotroejemplo,
floatenconprom(inttam,floatlista[]) { inti; floatsuma=0.0; for(i=0;i<tam;i++) suma+=lista[i]; return(suma/tam); } main() { floatnumeros[]={2.3,8.0,15.0,20.2,44.01,3.0,2.9}; printf("Elpromediodelalistaes%f\n",enconprom(7,numeros)); }

Paraelcasodequesetengaquepasarunarregloconmsdeunadimensin,noseindicalaprimera dimensinpero,elrestodelasdimensionesdebensealarse.Semuestraacontinuacinunejemplo:
voidimprtabla(inttamx,inttamy,floattabla[][5]) { intx,y; for(x=0;x<tamx;x++) { for(y=0;y<tamy;y++) printf("t[%d][%d]=%f",x,y,tabla[x][y]); printf("\n"); } }

6.3Prototiposdefunciones
AntesdeusarunafuncinCdebetenerconocimientoacercadeltipodedatoqueregresaryeltipo delosparmetrosquelafuncinespera. ElestndarANSIdeCintrodujunanueva(mejor)formadehacerloanteriorrespectoalas versionespreviasdeC. Laimportanciadeusarprototiposdefuncioneseslasiguiente:

Sehaceelcdigomsestructuradoyporlotanto,msfcildeleer. SepermitealcompiladordeCrevisarlasintaxisdelasfuncionesllamadas.

Loanterioreshecho,dependiendodelalcancedelafuncin.Bsicamentesiunafuncinhasido definidaantesdequeseausada(ollamada),entoncessepuedeusarlafuncinsinproblemas. Sinoesas,entonceslafuncinsedebedeclarar.Ladeclaracinsimplementemanejaeltipode datoquelafuncinregresayeltipodepar^o'ametrosusadosporlafuncin. Esunaprcticausualyconvenienteescribirelprototipodetodaslasfuncionesalprincipiodel programa,sinembargoestonoesestrictamentenecesario.

Paradeclararunprototipodeunafuncinseindicareltipodedatoqueregresarlafuncin,el nombredelafuncinyentreparntesislalistadeltipodelosparmetrosdeacuerdoalordenque aparecenenladefinicindelafuncin.Porejemplo:


intlongcad(char[]);

Loanteriordeclaraunafuncinllamadalongcadqueregresaunvalorenteroyaceptaunacadena comoparmetro.

6.4Ejercicios
1. Escribirunafuncin``reemplaza'',lacualtomaunacadenacomoparmetro,lereemplaza todoslosespaciosdelacadenaporunguinbajo,ydevuelveelnmerodeespacios reemplazados.Porejemplo:
charcadena[]="Elgatonegro"; n=reemplaza(cadena);

deberdevolver:
cadenaconvertida"El_gato_negro" n=2

2. Escribirunprogramaqueleaunalneadetextoenunbuffer(unacadenadecaracteres) usandolafuncingetsycalculelalongituddelalnea(NOusarlafuncinstrlen). 3. Modificarelprogramaanteriorparaqueleaunarchivodetexto.Elarchivodeber redireccionarsealprograma,debiendomostrarelcontenidodelmismo.Encasodequese leaunalneaconlongitud0deberterminarelprograma.

Subsecciones

7.1Estructuras 7.1.1Definicindenuevostiposdedatos 7.2Uniones 7.3Conversindetipos(casts) 7.4Enumeraciones 7.5Variablesestticas 7.6Ejercicios

7.Mstiposdedatos
EnestecaptuloserevisalaformacomopuedensercreadosyusadosenCtiposdedatosms complejosyestructuras.

7.1Estructuras
EnCunaestructuraesunacoleccindevariablesquesereferencianbajoelmismonombre.Una estructuraproporcionaunmedioconvenienteparamantenerjuntainformacinqueserelaciona. Unadefinicindeestructuraformaunaplantillaquesepuedeusarparacrearvariablesde estructura.Lasvariablesqueformanlaestructurasonllamadoselementosestructurados. Generalmente,todosloselementosenlaestructuraestnrelacionadoslgicamenteunosconotros. Porejemplo,sepuederepresentarunalistadenombresdecorreoenunaestructura.Mediantela palabraclavestructseleindicaalcompiladorquedefinaunaplantilladeestructura.
structdirec { charnombre[30]; charcalle[40]; charciudad[20]; charestado[3]; unsignedintcodigo; };

Coneltrozodecdigoanteriornohasidodeclaradaningunavariable,tansloseha definidoelformato.Paradeclararunavariable,seharcomosigue:
structdirecinfo_direc;

Sepuedendeclararunaomsvariablescuandosedefineunaestructuraentre)y;.Porejemplo:
structdirec { charnombre[30];

charcalle[40]; charciudad[20]; charestado[3]; unsignedintcodigo; }info_direc,binfo,cinfo;

observarquedirecesunaetiquetaparalaestructuraquesirvecomounaformabreve parafuturasdeclaraciones.Comoenesteltimadeclaracinseindicanlasvariablescon estaestructura,sepuedeomitirelnombredelaestructuratipo. Lasestructuraspuedensertambinpreinicializadasenladeclaracin:


structdirecinfo_direc={"VicenteFernandez","Fantasia 2000","Dorado","MMX",12345};

Parareferenciaroaccesarunmiembro(ocampo)deunaestructura,Cproporcionaeloperador punto.,porejemplo,paraasignarainfo_direcotrocdigo,lohacemoscomo:
info_direc.codigo=54321;

7.1.1Definicindenuevostiposdedatos
Sesealopreviamente(seccin2.4.1)quetypedefsepuedeusarparadefinirnuevosnombresde datosexplictamente,usandoalgunosdelostiposdedatosdeC,dondesuformatoes: typedef<tipo><nombre>; Sepuedeusartypedefparacrearnombresparatiposmscomplejos,comounaestructura,por ejemplo:
typedefstructdirec { charnombre[30]; charcalle[40]; charciudad[20]; charestado[3]; unsignedintcodigo; }sdirec; sdirecinfo_direc={"VicenteFernandez","Fantasia2000","Dorado","MMX",12345};

enestecasodirecsirvecomounaetiquetaalaestructurayesopcional,yaquehasido definidounnuevotipodedato,porloquelaetiquetanotienemuchouso,endonde sdireceselnuevotipodedatoseinfo_direcesunavariabledeltiposdirec,la cualesunaestructura. ConCtambinsepuedentenerarreglosdeestructuras:


typedefstructdirec { charnombre[30]; charcalle[40]; charciudad[20]; charestado[3]; unsignedintcodigo;

}info_direc; info_direcartistas[1000];

porloanterior,artistastiene1000elementosdeltipoinfo_direc.Loanterior podraseraccesadodelasiguienteforma:
artistas[50].codigo=22222;

7.2Uniones
Unaunionesunavariablelacualpodraguardar(enmomentosdiferentes)objetosdediferentes tamaosytipos.Cemplealasentenciaunionparacrearunionesporejemplo:
unionnumero { shortshortnumero; longlongnumero; doublefloatnumero; }unumero;

conloanteriorsedefineunauninllamadanumeroyunainstanciadeestallamada unumero.numeroeslaetiquetadelauninytieneelmismocomportamientoquela etiquetaenlaestructura. Losmiembrospuedenseraccesadosdelasiguienteforma:


printf("%ld\n",unumero.longnumero);

conlallamadaalafuncinsemuestraelvalordelongnumero. CuandoelcompiladordeCestareservandomemoriaparalasuniones,siemprecrearunavariable losuficientementegrandeparaquequepaeltipodevariablemslargodelaunin. Conlafinalidaddequeelprogramapuedallevarelregistrodeltipodelavariableuninusadaen unmomentodado,escomntenerunaestructura(conunauninanidada)yunavariablequeindica eltipodeunin. Semuestraunejemplodeloanterior:


typedefstruct { intmaxpasajeros; }jet; typedefstruct { intcapac_elev; }helicoptero; typedefstruct { intmaxcarga; }avioncarga;

typedefunion { jetjetu; helicopterohelicopterou; avioncargaavioncargau; }transporteaereo; typedefstruct { inttipo; intvelocidad; transporteaereodescripcion; }un_transporteaereo

enelejemplosedefineunauninbasedetransporteareoelcualpuedeserunjet,un helicpteroounaviondecarga. Enlaestructuraun_transporeaereohayunmiembroparaeltipo,queindicacualesla estructuramanejadaensemomento.

7.3Conversindetipos(casts)
Cesunodelospocoslenguajesquepermitenlaconversindetipos,estoes,forzarunavariablede untipoaserdeotrotipo.Loanteriorsepresentacuandovariablesdeuntiposemezclanconlasde otrotipo.Parallevaracaboloanteriorseusaeloperadordeconversin(cast)().Porejemplo:
intnumeroentero; floatnumeroflotante=9.87; numeroentero=(int)numeroflotante;

conlocualseasigna9alavariablenumeroenteroylafraccinesdesechada. Elsiguientecdigo:
intnumeroentero=10; floatnumeroflotante; numeroflotante=(float)numeroentero;

asigna10.0anumeroflotante.ComoseobservaCconvierteelvalordellado derechodelaasignacinaltipodelladoizquierdo. Laconversindetipospuedesertambinusadaconcualquiertiposimplededatosincluyendo char,porlotanto:


intnumeroentero; charletra='A'; numeroentero=(int)letra;

asigna65(queeselcdigoASCIIde'A')anumeroentero.

Algunasconversionesdetipossonhechasautomticamenteestoesprincipalmenteporla caractersticadecompatibilidaddetipos. Unabuenareglaeslasiguiente:Encasodeduda,conversindetipos. Otrousoesasegurarsequeladivisindenmerossecomportacomoserequiere,yaquesisetienen dosenteroslaformadeforzarelresultadoaunnmeroflotantees:


numeroflotante=(float)numerent/(float)denoment;

conloqueseaseguraqueladivisindevolverunnmeroflotante.

7.4Enumeraciones
Unaenumeracinesunconjuntodeconstantesenterasconnombreyespecificatodoslosvalores legalesquepuedetenerunavariabledeltipoenum. Laformacomosedefineunaenumeracinesdeformaparecidaacomosehaceconlasestructuras, usandolapalabraclaveenumparaelcomienzodeuntipodeenumeracin.Suformatoes: enumnombre_enum{lista_de_enumeracin}lista_de_variables; Esopcionalnombre_enumylista_de_variables.Laprimeraseusaparadeclararlasvariablesde sutipo.Elsiguientefragmentodefineunaenumeracinllamadadiscoquedeclara almacenamientoparaserdeesetipo.
enumalmacenamiento{diskette,dd,cd,dvd,cinta}; enumalmacenamientodisco;

Conlasiguientedefinicinydeclaracinsonvlidaslassiguientessentencias:
disco=cd; if(disco==diskette) printf("Esde1440Kb\n");

Seinicializaelprimersmbolodeenumeracinacero,elvalordelsegundosmboloa1yas sucesivamente,amenosqueseinicialicedeotramanera.Portanto,
printf("%d%d\n",dd,cinta)

muestra14enlapantalla. Sepuedeespecificarelvalordeunoomssmbolosusandouninicializador.Parahacerlo,ponerun signoigualyunvalorenterodespusdelsmbolo. Porejemplo,losiguienteasignaelvalor250acd


enumdisco{diskette,duro,cd=250,dvd,cinta};

Porlotantolosvaloresdelossmbolossonlossiguientes: diskette 0 duro 1 cd 250 dvd 251 cinta 252

7.5Variablesestticas
Csoportacuatroespecificadoresdeclasedealmacenamiento.Son auto extern static register Estosespecifcadoresledicenalcompiladorcomoalmacenarlavariablequesigue.Elespecificador dealmacenamientoprecedealadeclaracindevariablequetieneelformatogeneral: especif_almacespecif_tipolista_variables; Seusaelespecificadorautoparadeclararvariableslocales.Sinembargo,raramenteseusaporque lasvariableslocalessonautopordefecto. Lasvariablesstaticsonvariablespermanentesensupropiafuncinoarchivo.Sediferenciandelas variablesglobalesporquesondesconocidasfueradesusfuncionesoarchivo,peromantienensus valoresentrellamadas.Estacaractersticalashacetilescuandoseescribenfuncionesgeneralesy bibliotecasdefunciones. Variablesstaticlocales.Unavariableestticalocalesunavariablelocalqueretienensuvalorentre llamadasdefuncin,yaqueClescreaunalmacenamientopermanente.Siloanteriornosepudiera hacer,entoncessetendranqueusarvariablesglobalesqueabriralapuertaaposiblesefectos laterales.Unejemplodeunafuncinquerequeriratalesvariablesesungeneradordeseriesde nmerosqueproduceunnmeronuevobasadoenelltimo. Acontinuacinsemuestraunejemploendondeseanalizaelcomportamientodeunavariableauto yunavariablestatic
voidstat();/*Prototipodelafuncion*/ main() { inti; for(i=0;i<5;++i) stat(); }

voidstat() { autointa_var=0; staticints_var=0; printf("auto=%d,static=%d\n",a_var,s_var); ++a_var; ++s_var; }

Lasalidadelcdigoanteriores:
auto=0,static=0 auto=0,static=1 auto=0,static=2 auto=0,static=3 auto=0,static=4

Comosepuedeobservarlavariablea_varescreadacadavezquesellamaalafuncin.La variables_varescreadaenlaprimerallamadaydespusrecuerdasuvalor,esdecir,nose destruyecuandoterminalafuncin.

7.6Ejercicios
1. Escribirunprogramaqueuseeltipoenumerateparamostrarelnombredeunmes,su predecesorysusucesor.Elmesseingresardesdeeltecladodandounnmeroentre1y12. 2. Escribirunprogramaquecontengaunafuncinquepuedarecibirdosestructurasque contienenlascoordenadasenelplanodedospuntosdados,deloscualessedeseaconocersu puntomedio.

Subsecciones

8.1Definici ndeunapuntador 8.2ApuntadoresyFunciones 8.3Apuntadoresyarreglos 8.4Arreglosdeapuntadores 8.5Arreglosmultidimensionalesyapuntadores 8.6Inicializacinestticadearreglosdeapuntadores 8.7Apuntadoresyestructuras 8.8Fallascomunesconapuntadores 8.9Ejercicios

8.Apuntadores
LosapuntadoressonunapartefundamentaldeC.Siustednopuedeusarlosapuntadores apropiadamenteentoncesestaperdiendolapotenciaylaflexibilidadqueCofrecebsicamente.El secretoparaCestaenelusodeapuntadores. Cusalosapuntadoresenformaextensiva.Porqu?

Eslanicaformadeexpresaralgunosclculos. Segeneracdigocompactoyeficiente. Esunaherramientamuypoderosa.

Cusaapuntadoresexplcitamentecon:

Eslanicaformadeexpresaralgunosclculos. Segeneracdigocompactoyeficiente. Esunaherramientamuypoderosa.

Cusaapuntadoresexplcitamentecon:

Arreglos, Estructurasy Funciones

8.1Definicindeunapuntador
Unapuntadoresunavariablequecontieneladireccinenmemoriadeotravariable.Sepueden tenerapuntadoresacualquiertipodevariable.

Eloperadorunarioomondico&devuelveladireccindememoriadeunavariable. Eloperadordeindireccinodereferencia*devuelveel``contenidodeunobjetoapuntadoporun apuntador''. Paradeclararunapuntadorparaunavariableenterahacer:


int*apuntador;

Sedebeasociaracadaapuntadoruntipoparticular.Porejemplo,nosepuedeasignarladireccin deunshortintaunlongint. Paratenerunamejoridea,considerarelsiguientecdigo:


main() { intx=1,y=2; int*ap; ap=&x; y=*ap; x=ap; *ap=3; }

Cuandosecompileelcdigosemostrarelsiguientemensaje: warning:assignmentmakesintegerfrompointerwithoutacast. Conelobjetivodeentenderelcomportamientodelcdigosupongamosquelavariablexestaenla localidaddelamemoria100,yen200yapen1000.Nota:unapuntadoresunavariable,porlo tanto,susvaloresnecesitanserguardadosenalgnlado.


intx=1,y=2; int*ap; ap=&x;

100 x1

200 y2

1000 ap 100

Lasvariablesxeysondeclaradaseinicializadascon1y2respectivamente,apesdeclaradocomo unapuntadoraenteroyseleasignaladireccindex(&x).Porloqueapsecargaconelvalor100.
y=*ap;

100 x1

200 y1

1000 ap 100

Despusyobtieneelcontenidodeap.Enelejemploapapuntaalalocalidaddememoria100la localidaddex.Porlotanto,yobtieneelvalordexelcuales1.

x=ap;

100 x 100

200 y1

1000 ap 100

ComosehavistoCnoesmuyestrictoenlaasignacindevaloresdediferentetipo(apuntadora entero).Asqueesperfectamentelegal(aunqueelcompiladorgeneraunavisodecuidado)asignael valoractualdeapalavariablex.Elvalordeapenesemomentoes100.


*ap=3;

100 x3

200 y1

1000 ap 100

Finalmenteseasignaunvaloralcontenidodeunapuntador(*ap). Importante:Cuandounapuntadoresdeclaradoapuntaaalgnlado.Sedebeinicializarel apuntadorantesdeusarlo.Porloque:


main() { int*ap; *ap=100; }

puedegenerarunerrorentiempodeejecucinopresentaruncomportamientoerrtico. Elusocorrectoser:
main() { int*ap; intx; ap=&x; *ap=100; }

Conlosapuntadoressepuederealizartambinaritmticaentera,porejemplo:
main() { float*flp,*flq; *flp=*flp+10; ++*flp; (*flp)++; flq=flp; }

NOTA:Unapuntadoracualquiertipodevariablesesunadireccinenmemorialacualesuna direccinentera,perounapuntadorNOesunentero.

Laraznporlacualseasociaunapuntadorauntipodedato,esporquesedebeconocerencuantos bytesestaguardadoeldato.Detalforma,quecuandoseincrementaunapuntador,seincrementael apuntadorporun``bloque''dememoria,endondeelbloqueestaenfuncindeltamaodeldato. Porlotantoparaunapuntadoraunchar,seagregaunbytealadireccinyparaunapuntadora enterooaflotanteseagregan4bytes.Deestaformasiaunapuntadoraflotanteselesuman2,el apuntadorentoncessemuevedosposicionesfloatqueequivalena8bytes.

8.2ApuntadoresyFunciones
CuandoCpasaargumentosafunciones,lospasaporvalor,esdecir,sielparmetroesmodificado dentrodelafuncin,unavezqueterminalafuncinelvalorpasadodelavariablepermanece inalterado. Haymuchoscasosquesequierealterarelargumentopasadoalafuncinyrecibirelnuevovalor unavezquelafuncinhaterminado.Parahacerloanteriorsedebeusarunallamadaporreferencia, enCsepuedesimularpasandounpunteroalargumento.Conestoseprovocaquelacomputadora paseladireccindelargumentoalafuncin. Paraentendermejorloanteriorconsideremoslafuncinswap()queintercambiaelvalordedos argumentosenteros:
voidswap(int*px,int*py); main() { intx,y; x=10; y=20; printf("x=%d\ty=%d\n",x,y); swap(&x,&y); printf("x=%d\ty=%d\n",x,y); } voidswap(int*px,int*py) { inttemp; temp=*px;/*guardaelvalordeladireccionx*/ *px=*py;/*poneyenx*/ *py=temp;/*ponexeny*/ }

8.3Apuntadoresyarreglos
Existeunarelacinestrechaentrelospunterosylosarreglos.EnC,unnombredeunarregloesun ndicealadireccindecomienzodelarreglo.Enesencia,elnombredeunarregloesunpunteroal arreglo.Considerarlosiguiente:
inta[10],x; int*ap;

ap=&a[0];/*apapuntaaladirecciondea[0]*/ x=*ap;/*Axseleasignaelcontenidodeap(a[0]enestecaso)*/ *(ap+1)=100;/*Seasignaalsegundoelementode'a'elvalor100usando ap*/

Comosepuedeobservarenelejemplolasentenciaa[t]esidnticaaap+t.Sedebetenercuidadoya queCnohaceunarevisindeloslmitesdelarreglo,porloquesepuedeirfcilmentemsalladel arregloenmemoriaysobreescribirotrascosas. Csinembargoesmuchomsstilensurelacinentrearreglosyapuntadores.Porejemplosepuede teclearsolamente: ap=a;envezdeap=&a[0];ytambin*(a+i)envezdea[i],estoes, &a[i]esequivalentecona+i. Ycomoseveenelejemplo,eldireccionamientodeapuntadoressepuedeexpresarcomo: a[i]queesequivalentea*(ap+i) Sinembargolosapuntadoresylosarreglossondiferentes:

Unapuntadoresunavariable.Sepuedehacerap=ayap++. UnarregloNOESunavariable.Hacera=apya++ESILEGAL.

Esteparteesmuyimportante,asegresehaberlaentendido. Conlocomentadosepuedeentendercomolosarreglossonpasadosalasfunciones.Cuandoun arregloespasadoaunafuncinloqueenrealidadseleestapasandoeslalocalidaddesuelemento inicialenmemoria. Porlotanto: strlen(s)esequivalenteastrlen(&s[0]) Estaeslaraznporlacualsedeclaralafuncincomo: intstrlen(chars[]);yunadeclaracinequivalenteesintstrlen(char *s); yaquechars[]esigualquechar*s. Lafuncinstrlen()esunafuncindelabibliotecaestndar queregresalalongituddeunacadena. Semuestraenseguidalaversindeestafuncinquepodraescribirse:
intstrlen(char*s) { char*p=s; while(*p!='\0') p++;

returnps; }

Semuestraenseguidaunafuncinparacopiarunacadenaenotra.Aligualqueenelejercicio anteriorexisteenlabibliotecaestndarunafuncinquehacelomismo.
voidstrcpy(char*s,char*t) { while((*s++=*t++)!='\0'); }

Enlosdosltimosejemplosseempleanapuntadoresyasignacinporvalor.Nota:Seempleaeluso delcaracternuloconlasentenciawhileparaencontrarelfindelacadena.

8.4Arreglosdeapuntadores
EnCsepuedentenerarreglosdeapuntadoresyaquelosapuntadoressonvariables. Acontinuacinsemuestraunejemplodesuuso:ordenarlaslneasdeuntextodediferente longitud. Losarreglosdeapuntadoressonunarepresentacindedatosquemanejandeunaformaeficientey convenientelneasdetextodelongitudvariable. Cmosepuedehacerloanterior? 1. Guardartodaslaslneasenunarreglodetipochargrande.Observandoque\nmarcael findecadalnea.Verfigura8.1. 2. Guardarlosapuntadoresenunarreglodiferentedondecadaapuntadorapuntaalprimer caracterdecadalnea. 3. Comparardoslneasusandolafuncindelabibliotecaestndarstrcmp(). 4. Sidoslneasestndesacomodadasintercambiar(swap)losapuntadores(noeltexto).

Figura8.1:Arreglosdeapuntadores(Ejemplodeordenamientodecadenas).

Conloanteriorseelimina:

elmanejocomplicadodelalmacenamiento. altasobrecargaporelmovimientodelneas.

8.5Arreglosmultidimensionalesyapuntadores
UnarreglomultidimensionalpuedeservistoenvariasformasenC,porejemplo: Unarreglodedosdimensionesesunarreglodeunadimensin,dondecadaunodeloselementoses ensmismounarreglo. Porlotanto,lanotacin
a[n][m]

nosindicaqueloselementosdelarregloestnguardadosrenglnporrengln. Cuandosepasaunaarreglobidimensionalaunafuncinsedebeespecificarelnmerodecolumnas elnmeroderenglonesesirrelevante. Larazndeloanterior,esnuevamentelosapuntadores.Crequiereconocercuantassonlas columnasparaquepuedabrincarderenglnenrenglnenlamemoria. Considerandoqueunafuncindebarecibirinta[5][35],sepuededeclararelargumentodela funcincomo:


f(inta[][35]){.....}

oan
f(int(*a)[35]){.....}

Enelltimoejemploserequierenlosparnteis(*a)yaque[]tieneunaprecedenciamsalta que*. Porlotanto: int(*a)[35];declaraunapuntadoraunarreglode35enteros,yporejemplosi hacemoslasiguientereferenciaa+2,nosestaremosrefiriendoaladireccindelprimer elementoqueseencuentraneneltercerrenglndelamatrizsupuesta,mientrasque int*a[35];declaraunarreglode35apuntadoresaenteros. Ahoraveamosladiferencia(sutil)entreapuntadoresyarreglos.Elmanejodecadenasesuna aplicacincomndeesto. Considera:

char*nomb[10]; charanomb[10][20];

Endondeesvlidohacernomb[3][4]yanomb[3][4]enC. Sinembargo: anombesunarregloverdaderode200elementosdedosdimensionestipochar. Elaccesodeloselementosanombenmemoriasehacebajolasiguientefrmula20*renglon +columna+direccin_base Encambionombtiene10apuntadoresaelementos.

NOTA:sicadaapuntadorennombindicaunarreglode20elementosentoncesysolamente entonces200charsestarndisponibles(10elementos). Conelprimertipodedeclaracinsetienelaventajadequecadaapuntadorpuedeapuntaraarreglos dediferentelongitud. Considerar:


char*nomb[]={"Nomes","Ene","Feb","Mar",....}; charanomb[][15]={"Nomes","Ene","Feb","Mar",...};

Locualgrficamentesemuestraenlafigura8.2.Sepuedeindicarquesehaceunmanejoms eficientedelespaciohaciendousodeunarreglodeapuntadoresyusandounarreglobidimensional.

Figura8.2:Arreglode2dimensionesVS.arreglodeapuntadores.

8.6Inicializacinestticadearreglosde apuntadores
Lainicializacindearreglosdeapuntadoresesunaaplicacinidealparaunarregloestticointerno, porejemplo:
func_cualquiera() { staticchar*nomb[]={"Nomes","Ene","Feb","Mar",....}; }

Recordandoqueconelespecificadordealmacenamientodeclasestaticsereservaenforma permanentememoriaelarreglo,mientraselcdigoseestaejecutando.

8.7Apuntadoresyestructuras
Losapuntadoresaestructurassedefinenfcilmenteyenunaformadirecta.Considerarlosiguiente:
main() { structCOORD{floatx,y,z;}punto; structCOORD*ap_punto; punto.x=punto.y=punto.z=1; ap_punto=&punto;/*Seasignapuntoalapuntador*/ ap_punto>x++;/*Coneloperador>seaccesanlosmiembros*/ ap_punto>y+=2;/*delaestructuraapuntadosporap_punto*/ ap_punto>z=3; }

Otroejemplosonlaslistasligadas:
typedefstruct{ intvalor; structELEMENTO*sig; }ELEMENTO; ELEMENTOn1,n2; n1.sig=&n2;

Laasignacinquesehacecorrespondealafigura8.3

Figura8.3:Esquemadeunalistaligadacon2elementos. Nota:SolamentesepuededeclararsigcomounapuntadortipoELEMENTO.Nosepuedetenerun elementodeltipovariableyaqueestogeneraraunadefinicinrecursivalacualnoestapermitida. Sepermiteponerunareferenciaaunapuntadoryaqueloslosbytessedejandeladoparacualquier apuntador.

8.8Fallascomunesconapuntadores
Acontinuacinsemuestrandoserrorescomunesquesehacenconlosapuntadores.

Noasignarunapuntadoraunadireccindememoriaantesdeusarlo
int*x *x=100;

loadecuadoser,tenerprimeramenteunalocalidadfsicadememoria,digamosinty;
int*x,y; x=&y; *x=100;

Indireccinnovlida Supongamosquesetieneunafuncinllamadamalloc()lacualtratadeasignarmemoria dinmicamente(entiempodeejecucin),lacualregresaunapuntadoralbloquedememoria requeridasisepudoounapuntadoranuloenotrocaso. char*malloc()unafuncindelabibliotecaestndarqueseverms adelante. Supongamosquesetieneunapuntadorchar*p Considerar:


*p=(char*)malloc(100):/*pide100bytesdelamemoria*/ *p='y';

Existeunerrorenelcdigoanterior.Cules? El*enlaprimeralneayaquemallocregresaunapuntadory*pnoapuntaaninguna direccin. Elcdigocorrectodeberser:


p=(char*)malloc(100);

Ahorasimallocnopuederegresarunbloquedememoria,entoncespesnulo,yporlo tantonosepodrhacer:

*p='y';

UnbuenprogramaenCdeberevisarloanterior,porloqueelcdigoanteriorpuedeser reescritocomo:
p=(char*)malloc(100):/*pide100bytesdelamemoria*/ if(p==NULL) { printf("Error:fueradememoria\n"); exit(1); } *p='y';

8.9Ejercicios
1. Escribirelprogramaqueordenalaslneasdeuntextoledodesdelaentradaestndar,donde cadalneatienediferentelongitud,segnlodescritoenlaseccindearreglodeapuntadores. 2. Escribirunafuncinqueconviertaunacadenasaunnmerodepuntoflotanteusando apuntadores.Considerarqueelnmerotieneelsiguienteformato99999999.999999,es decir,nosedarennotacincientfica.Lafuncindebersuministrrseleunacadenay deberdevolverunnmero. 3. Escribirunprogramaqueencuentreelnmerodevecesqueunapalabradada(estoes,una cadenacorta)ocurreenunasentencia(unacadenalarga). Leerlosdatosdelaentradaestndar.Laprimeralneaesunasolapalabra,enlasegunda lneasetieneuntextogeneral.Leerambashastaencontraruncaracterdenuevalnea. Recordarquesedebeinsertaruncaracternuloantesdeprocesar. Lasalidatpicapodraser:
Lapalabraes"el" Lasentenciaes"elperro,elgatoyelcanario" Lapalabraocurrio3veces.

Subsecciones

9.1Usode malloc,sizeof y free calloc 9.2 y realloc 9.3Listasligadas 9.4Programaderevisin 9.5Ejercicios

9.Asignacindinmicadememoriay Estructurasdinmicas
LaasignacindinmicadememoriaesunacaractersticadeC.Lepermitealusuariocreartiposde datosyestructurasdecualquiertamaodeacuerdoalasnecesidadesquesetenganenelprograma. Serevisarndosdelasaplicacionesmscomunes:

Arreglosdinmicos Estructurasdinmicasdedatos.

9.1Usodemalloc,sizeofyfree
Lafuncinmallocesempleadacomnmenteparaintentar``tomar''unaporcincontiguade memoria.Estadefinidacomo:
void*malloc(size_tsize);

Loanteriorindicaqueregresarunapuntadordeltipovoid*,elcualeselinicioenmemoriade laporcinreservadadetamaosize.Sinopuedereservaresacantidaddememorialafuncin regresaunapuntadornulooNULL Dadoquevoid*esregresado,Casumequeelapuntadorpuedeserconvertidoacualquiertipo. Eltipodeargumentosize_testadefinidoenlacabecerastddef.hyesuntipoenterosin signo. Porlotanto:


char*cp; cp=(char*)malloc(100);

intentaobtener100bytesyasignarlosaladireccindeinicioacp.

Esusualusarlafuncinsizeof()paraindicarelnmerodebytes,porejemplo:
int*ip; ip=(int*)malloc(100*sizeof(int));

ElcompiladordeCrequierehacerunaconversindeltipo.Laformadelograrlacoercin(cast)es usando(char*)y(int*),quepermiteconvertirunapuntadorvoidaunapuntadortipo chareintrespectivamente.Hacerlaconversinaltipodeapuntadorcorrectoaseguraquela aritmticaconelapuntadorfuncionardeformacorrecta. Esunabuenaprcticausarsizeof()ansiseconoceeltamaoactualdeldatoqueserequiere, yaquedeestaformaelcdigosehaceindependientedeldispositivo(portabilidad). Lafuncinsizeof()puedeserusadaparaencontrareltamaodecualquiertipodedato,variable oestructura.Simplementesedebeproporcionarunodelosanteriorescomoargumentoalafuncin. Porlotanto:


inti; structCOORD{floatx,y,z}; structCOORD*pt; sizeof(int),sizeof(i),sizeof(structCOORD)y sizeof(PT)sontambiensentenciascorrectas.

Enelsiguienteejemplosereservamemoriaparalavariableip,endondeseemplealarelacinque existeentreapuntadoresyarreglos,paramanejarlamemoriareservadacomounarreglo.Por ejemplo,sepuedenhacercosascomo:


main() { int*ip,i; ip=(int*)malloc(100*sizeof(int)); ip[0]=1000; for(i=0;i<100;++i) scanf("%d",ip++); }

Cuandosehaterminadodeusarunaporcindememoriasiempresedeberliberarusandola funcinfree().Estafuncinpermitequelamemorialiberadaestedisponiblenuevementequizs paraotrallamadadelafuncinmalloc() Lafuncinfree()tomaunapuntadorcomounargumentoyliberalamemoriaalacualel apuntadorhacereferencia.

9.2callocyrealloc
Existendosfuncionesadicionalesparareservarmemoria,calloc()yrealloc().Los prototipossondadosacontinuacin:
void*calloc(size_tnmemb,size_tsize); void*realloc(void*ptr,size_tsize);

Cuandoseusalafuncinmalloc()lamemorianoesinicializada(acero)oborrada.Sisequiere inicializarlamemoriaentoncessepuedeusarlafuncincalloc.Lafuncincalloces computacionalmenteunpocomscarapero,ocasionalmente,msconvenientequemalloc.Se debeobservartambinladiferenciadesintaxisentrecallocymalloc,yaquecalloctomael nmerodeelementosdeseados(nmemb)yeltamaodelelemento(size),comodosargumentos individuales. Porlotantoparaasignara100elementosenterosqueestninicializadosacerosepuedehacer:


int*ip; ip=(int*)calloc(100,sizeof(int));

Lafuncinreallocintentacambiareltamaodeunbloquedememoriapreviamenteasignado. Elnuevotamaopuedesermsgrandeomspequeo.Sielbloquesehacemsgrande,entoncesel contenidoanteriorpermanecesincambiosylamemoriaesagregadaalfinaldelbloque.Siel tamaosehacemspequeoentonceselcontenidosobrantepermanecesincambios. Sieltamaodelbloqueoriginalnopuedeserredimensionado,entoncesreallocintentarasignar unnuevobloquedememoriaycopiarelcontenidoanterior.Porlotanto,lafuncindevolverun nuevoapuntador(odevalordiferentealanterior),estenuevovalorserelquedeberusarse.Sino puedeserreasignadanuevamemorialafuncinreallocdevuelveNULL. Siparaelejemploanterior,sequierereasignarlamemoriaa50enterosenvezde100apuntadospor ip,sehar;
ip=(int*)realloc(ip,50*sizeof(int));

9.3Listasligadas
Regresandoalejemplodelcaptuloanteriorsedefinilaestructura:
typedefstruct{ intvalor; structELEMENTO*sig; }ELEMENTO;

Lacualpuedecrecerenformadinmica.
ELEMENTO*liga;

liga=(ELEMENTO*)malloc(sizeof(ELEMENT));/*Asignamemoriaparaliga*/ free(liga);/*liberalamemoriaasignadaalapuntadorligausandofree()*/

9.4Programaderevisin
Lacolaesunacoleccindeordenadadeelementosdelaquesepuedenborrarelementosenun extremo(llamadoelfrentedelacola)oinsertarlosenelotro(llamadoelfinaldelacola. Semuestraacontinuacinelcdigocompletoparamanipularestaestructura:
/*cola.c*/ /*DemodeestructurasdinamicasenC*/ #include<stdio.h> #defineFALSO0 typedefstructnodo{ intdato; structnodo*liga; }elemento_lista; voidMenu(int*opcion); elemento_lista*AgregaDato(elemento_lista*apuntlista,intdato); elemento_lista*BorrarDato(elemento_lista*apuntlista); voidImprCola(elemento_lista*apuntlista); voidLimpCola(elemento_lista*apuntlista); main() { elemento_listalistmember,*apuntlista; intdato,opcion; apuntlista=NULL; do{ Menu(&opcion); switch(opcion){ case1: printf("Ingresaundatoqueseraagregado"); scanf("%d",&dato); apuntlista=AgregaDato(apuntlista,dato); break; case2: if(apuntlista==NULL) printf("Colavacia!\n"); else apuntlista=BorrarDato(apuntlista); break; case3: ImprCola(apuntlista); break; case4: break; default: printf("Opcionnovalidaintentarnuevamente\n"); break; } }while(opcion!=4);

LimpCola(apuntlista); }/*findemain*/ voidMenu(int*opcion) { charlocal; printf("\nEntre\t1paraagregarundato,\n\t2paraborrarundato,\n\t3para mostrarelcontenidodelacola\n\t4parasalir\n"); do{ local=getchar(); if((isdigit(local)==FALSO)&&(local!='\n')) { printf("\nSedebeingresarunentero.\n"); printf("Teclee1paraagregar,2paraborrar,3paraimprimir,4 parasalir\n"); } }while(isdigit((unsignedchar)local)==FALSO); *opcion=(int)local'0'; } elemento_lista*AgregaDato(elemento_lista*apuntlista,intdato) { elemento_lista*lp=apuntlista; if(apuntlista!=NULL){ while(apuntlista>liga!=NULL) apuntlista=apuntlista>liga; apuntlista>liga=(structnodo*)malloc(sizeof(elemento_lista)); apuntlista=apuntlista>liga; apuntlista>liga=NULL; apuntlista>dato=dato; returnlp; } else { apuntlista=(structnodo*)malloc(sizeof(elemento_lista)); apuntlista>liga=NULL; apuntlista>dato=dato; returnapuntlista; } } elemento_lista*BorrarDato(elemento_lista*apuntlista) { elemento_lista*tempp; printf("Elelementoborradoes%d\n",apuntlista>dato); tempp=apuntlista>liga; free(apuntlista); returntempp; } voidImprCola(elemento_lista*apuntlista) { if(apuntlista==NULL) printf("Lacolaestavacia!!\n"); else while(apuntlista!=NULL){ printf("%d\t",apuntlista>dato); apuntlista=apuntlista>liga; } printf("\n");

} voidLimpCola(elemento_lista*apuntlista) { while(apuntlista!=NULL){ apuntlista=BorrarDato(apuntlista); } }

9.5Ejercicios
1. Escribirunprogramaqueleaunnmero,queindicacuntosnmerosenterossern guardadosenunarreglo,crearelarregloparaalmacenareltamaoexactodelosdatosy entoncesleerlosenterosquesernguardadosenelarreglo. 2. Escribirunprogramaparaordenarunasecuenciadenmerosusandounrbolbinario.Un rbolbinarioesunaestructuratiporbolconsolamente2(posibles)ramasdecadanodo. Cadaramaentoncesrepresentaunadecisindefalsooverdadero.Paraordenarlosnmeros simplementeasignaralaramaizquierdalosnmerosmenoresrespectoalnmerodelnodo, yenlaramaderechaelresto(esdecir,losquesonmayoresoigualesa). Porlotanto,silalistadeentradaes:1415497183516420170145, sedebegenerarelrboldelafigura9.1.

Figura9.1:Arbolbinario. Paraobtenerunalistaordenadaenformaascendente,recorrerelrbolenpreorden(depth firstorder),esdecir,visitarlaraz,recorrerelsubrbolizquierdoenordenyrecorrerel subrbolderechoenorden.Porloquelasalidadeberser:


Losvaloresordenadosson: 0344557914141516171820

Mostrar10valoresporlnea.

Subsecciones

10.1Apuntadoresaapuntadores 10.2Entradaenlalneadecomandos 10.3Apuntadoresafunciones 10.4Ejercicios

10.Tpicosavanzadosconapuntadores
Sehanrevisadovariasaplicacionesytcnicasqueusanapuntadoresenloscaptulosanteriores.As mismosehanintroducidoalgunostemasavanzadosenelusodeapuntadores.Enestecaptulose profundizanalgunostpicosqueyahansidomencionadosbrevementeyotrosquecompletanla revisindeapuntadoresenC. Enestecaptulosedesarrollalosiguiente:

Seexaminanapuntadoresaapuntadoresconmsdetalle. Comoseusanlosapuntadoresenlalneadeentrada. Yserevisanlosapuntadoresafunciones.

10.1Apuntadoresaapuntadores
Unarreglodeapuntadoreseslomismoqueapuntadoresaapuntadores.Elconceptodearreglosde apuntadoresesdirectoyaqueelarreglomantienesusignificadoclaro.Sinembargo,sepueden confundirlosapuntadoresaapuntadores. Unapuntadoraunapuntadoresunaformadedireccionamientoindirectomltiple,ounacadenade apuntadores.Comoseveenlafigura10.1,enelcasodeunapuntadornormal,elvalordel apuntadoresladireccindelavariablequecontieneelvalordeseado.Enelcasodeunapuntadora unapuntador,elprimerapuntadorcontieneladireccindelsegundoapuntador,queapuntaala variablequecontieneelvalordeseado. Sepuedellevardireccionamientoindirectomltipleacualquierextensindeseada,perohaypocos casosdondemsdeunapuntadoraunapuntadorseanecesario,oinclusobuenodeusar.La direccinindirectaenexcesoesdifcildeseguirypropensaaerroresconceptuales. Sepuedetenerunapuntadoraotroapuntadordecualquiertipo.Considereelsiguientecdigo:
main() { charch;/*Uncaracter*/ char*pch;/*Unapuntadoracaracter*/ char**ppch;/*Unapuntadoraunapuntadoracaracter*/

ch='A'; pch=&ch; ppch=&pch; printf("%c\n",**ppch);/*muestraelvalordech*/ }

Loanteriorsepuedevisualizarcomosemuestraenlafigura10.1,endondeseobservaque**ppch serefierealadireccindememoriade*pch,lacualasuvezserefierealadireccindememoria delavariablech.Peroqusignificaloanteriorenlaprctica?

Figura10.1:Apuntadoraunapuntador,yapuntadoraunchar. Sedeberecordarquechar*serefiereaunacadenalacualterminaconunnulo.Porlotanto,un usocomnyconvenienteesdeclararunapuntadoraunapuntador,yelapuntadoraunacadena,ver figura10.2.

Figura10.2:Apuntadoraunapuntador,yapuntadoraunacadena. Tomandounpasomsallloanterior,sepuedentenervariascadenasapuntadasporelapuntador, verfigura10.3

Figura10.3:Apuntadoravariascadenas. Sepuedenhacerreferenciasacadenasindividualesmedianteppch[0],ppch[1],....Estoes idnticoahaberdeclaradochar*ppch[]. Unaaplicacincomndeloanterioresenlosargumentosdelalneadecomandosqueserevisarn acontinuacin.

10.2Entradaenlalneadecomandos
Cpermiteleerargumentosenlalneadecomandos,loscualespuedenserusadosenlosprogramas. Losargumentossondadosotecleadosdespusdelnombredelprogramaalmomentodeser ejecutadoelprograma. Loanteriorsehavistoalmomentodecompilar,porejemplo:
gccoprogprog.c

dondegcceselcompiladoryoprogprog.csonlosargumentos. Parapoderusarlosargumentosenelcdigosedebedefinircomosiguelafuncinmain.
main(intargc,char**argv)

o
main(intargc,char*argv[])

Conloquelafuncinprincipaltieneahorasuspropiosargumentos.Estossonsolamentelosnicos argumentosquelafuncinmainacepta. * * argceselnmerodeargumentosdadosincluyendoelnombredelprograma. argvesunarreglodecadenasquetieneacadaunodelosargumentosdelalneade comandosincluyendoelnombredelprogramaenelprimerelementodelarreglo. Semuestraacontinuacinunprogramadeejemplo:


main(intargc,char**argv) { /*Esteprogramamuestralosargumentosdelalineadecomandos*/ inti; printf("argc=%d\n\n",argc); for(i=0;i<argc;++i) printf("\t\targv[%d]:%s\n",i,argv[i]); }

Suponiendoquesecompilayseejecutaconlossiguientesargumentos:
argsf1"f2yf3"f45FIN

Lasalidaser:
argc=6 argv[0]:args argv[1]:f1 argv[2]:f2yf3 argv[3]:f4

argv[4]:5 argv[5]:FIN

Observarlosiguiente: argv[0]contieneelnombredelprograma. argccuentaelnmerodeargumentosincluyendoelnombredelprograma. Losespaciosenblancodelimitanelfindelosargumentos. Lascomillasdobles""sonignoradasysonusadasparaincluirespaciosdentrodeun argumento.

10.3Apuntadoresafunciones
LosapuntadoresafuncionessonquizunodelosusosmsconfusosdelosapuntadoresenC.Los apuntadoresafuncionesnosontancomunescomootrosusosquetienenlosapuntadores.Sin embargo,unusocomnescuandosepasanapuntadoresafuncionescomoparmetrosenlallamada aunafuncin. Loanterioresespecialmentetilcuandosedebenusardistintasfuncionesquizspararealizartareas similaresconlosdatos.Porejemplo,sepuedenpasarlosdatosylafuncinqueserusadapor algunafuncindecontrol.ComosevermsadelantelabibliotecaestndardeCdafuncionespara ordenamiento(qsort)ypararealizarbsqueda(bsearch),alascualesselespuedenpasarfunciones. Paradeclararunapuntadoraunafuncinsedebehacer:
int(*pf)();

Locualdeclaraunapuntadorpfaunafuncinqueregresauntipodedatoint.Todavanoseha indicadoaquefuncinapunta. Suponiendoquesetieneunafuncinintf(),entoncessimplementesedebeescribir:


pf=&f;

paraque

apuntealafuncin

Paraquetrabajeenformacompletaelcompiladoresconvenientequesetenganlosprototipos completosdelasfuncionesylosapuntadoresalasfunciones,porejemplo:
intf(int); int(*pf)(int)=&f;

Ahoraf()regresaunenteroytomaunenterocomoparmetro. Sepuedenhacercosascomo:

ans=f(5); ans=pf(5);

loscualessonequivalentes. Lafuncindelabibliotecaestndarqsortesmuytilyestadiseadaparaordenarunarreglo usandounvalorcomollavedecualquiertipoparaordenarenformaascendente. Elprototipodelafuncinqsortdelabibliotecastdlib.hes:


voidqsort(void*base,size_tnmiemb,size_ttam, int(*compar)(constvoid*,constvoid*));

Elargumentobaseapuntaalcomienzodelvectorqueserordenado,nmiembindicaeltamao delarreglo,tameseltamaoenbytesdecadaelementodelarregloyelargumentofinalcompar esunapuntadoraunafuncin. Lafuncinqsortllamaalafuncincomparlacualesdefinidaporelusuarioparacompararlos datoscuandoseordenen.Observarqueqsortconservasuindependenciarespectoaltipodedato aldejarlelaresponsabilidadalusuario.Lafuncincompardeberegresarundeterminadovalor enterodeacuerdoalresultadodecomparacin,quedebeser: menorquecero:sielprimervaloresmenorqueelsegundo. cero:sielprimervaloresigualqueelsegundo. mayorquecero:sielprimervaloresmayorqueelsegundo. Acontinuacinsemuestraunejemploqueordenaunarreglodecaracteres,observarqueenla funcincomp,sehaceuncastparaforzareltipovoid*altipochar*.
#include<stdlib.h> intcomp(constvoid*i,constvoid*j); main() { inti; charcad[]="facultaddecienciasfisicomatematicas"; printf("\n\nArreglooriginal:\n"); for(i=0;i<strlen(cad);i++) printf("%c",cad[i]); qsort(cad,strlen(cad),sizeof(char),comp); printf("\n\nArregloordenado:\n"); for(i=0;i<strlen(cad);i++) printf("%c",cad[i]); printf("\n"); } intcomp(constvoid*i,constvoid*j) { char*a,*b;

a=(char*)i;/*Paraforzarvoid*altipochar*,sehacecast*/ b=(char*)j;/*empleando(char*)*/ return*a*b; }

10.4Ejercicios
1. Escribirunprogramaquemuestrelasltimaslneasdeuntextodeentrada.Pordefectoo ``default''ndeberser7,peroelprogramadeberpermitirunargumentoopcionaltalque ultlinn muestralasltimasnlneas,dondenesunentero.Elprogramadeberhacerelmejoruso delespaciodealmacenamiento.(Eltextodeentradapodrserledodeunarchivodado desdelalneadecomandosoleyendounarchivodelaentradaestndar.) 2. Escribirunprogramaqueordeneunalistadeenterosenformaascendente.Sinembargo,si unaopcinrestapresenteenlalneadecomandoselprogramadeberordenarlalistaen formadescendente. 3. Escribirunprogramaquelealasiguienteestructurayordenelosdatosporlallaveusando qsort
typedefstruct{ charllave[10]; intalgo_mas; }Record;

Subsecciones

11.1Operadoressobrebits 11.2Camposdebit 11.2.1Portabilidad 11.3Ejercicios

11.Operadoresdebajonivelycamposdebit
Sehavistocomolosapuntadoresnosdancontrolsobrelasoperacionesdebajoniveldelamemoria. Muchosprogramas(porejemplo,aplicacionesdeltiposistemas)operanactualmenteabajonivel dondebitsindividualesdebensermanipulados. LacombinacindeapuntadoresyoperadoresanivelbithacendeCtilparamuchasaplicaciones debajonivelypuedencasireemplazaralcdigoensamblador.(Solamenteun10% aproximadamentedeUNIXestaencdigoensambladorelrestoesC.)

11.1Operadoressobrebits
LosoperadoressobrebitsdeCseresumenenlasiguientetabla: Operador & | ^ ~ << >> Accin Y O Oexclusiva(XOR) Complementoauno Negacin Desplazamientoalaizquierda Desplazamientoaladerecha

Nosedebeconfundireloperador&coneloperador&&:&eseloperadorYsobrebits,&&esel operadorlgicoY.Similarmentelosoperadores|y||. Eloperadorunario~slorequiereunargumentoaladerechadeloperador. Losoperadoresdedesplazamiento,>>y<<,mueventodoslosbitsenunaposicinhacialaderecha olaizquierdaundeterminadonmerodeposiciones.Elformatogeneraldelasentenciade desplazamientoaladerechaes:

variable>>num_pos_de_bit

yelformatogeneraldedesplazamientoalaizquierdaes
variable<<num_pos_de_bit

Comolosoperadoresdesplazanbitsenunsentido,lacomputadoratraecerosenelotroextremo.Se deberecordarqueundesplazamientonoesunarotacin:losbitsdesplazadosenunextremono vuelvenalotro.Sepierdenyloscerostradoslosreemplazan. Unaaplicacinquetienenlosoperadoresdedesplazamientodebitsespararealizarmultiplicaciones ydivisionesrpidasconenteros.Comoseveenlasiguientetabla,dondeundesplazamientoala izquierdaesmultiplicarpor2yunoaladerechadividirpor2. charx x=7; x<<1; x<<3; x<<2; x>>1; x>>2; Ejecucin 00000111 00001110 01110000 11000000 01100000 00011000 Valordex 7 14 112 192 96 24

Losdesplazamientossonmuchomsrpidosquelamultiplicacinactual(*)oladivisin(/)por dos.Porlotanto,sisequierenmultiplicacionesodivisionesrpidaspor2usedesplazamientos. Conlafinalidaddeilustraralgunospuntosdelosoperadoressobrebits,semuestralasiguiente funcincontbit,lacualcuentalosbitspuestosa1enunnmerode8bits(unsignedchar) pasadocomounargumentoalafuncin.


intcontbit(unsignedcharx) { intcount; for(count=0;x!=0;x>>=1) if(x&1) count++; returncount; }

EnestafuncinseilustranvariascaractersticasdeC:

Elciclofornoesusadoparasimplementecontar. x>>=1esequivalenteax=x>>1. Elcicloforiterativamentedesplazaaladerechaxhastaquexsehace0. x&01enmascaraelprimerbitdex,ysiestees1entoncesincrementacount.

11.2Camposdebit
Alcontrariodelamayoradeloslenguajesdeprogramacin,Ctieneunmtodopredefinidopara accederaunnicobitenunbyte.Estemtodopuedeserutilsimoporunaseriederazones: Sielalmacenamientoeslimitado,sepuedenalmacenarvariasvariablesbooleanasenunbyte; ciertasinterfacesdedispositivotransmiteninformacinquesecodificaenbitsdentrodeun byte; ciertasrutinasdeencriptacinnecesitanaccederalosbitsenunbyte. ElmtodoqueCusaparaaccederalosbitssebasaenlaestructura.Uncampodebitesuntipo especialdeestructuraquedefinelalongitudenbitsquetendrcadaelemento.Elformatogeneralde unadefinicindecampodebites: structnomb_estruct{ tiponombre_1:longitud; tiponombre_2:longitud; . . . tiponombre_n:longitud; } Sedebedeclararuncampodebitcomoint,unsignedosigned.Sedebedeclararloscamposdebits delongitud1comounsigned,yaqueunbitniconopuedetenersigno. Porejemplo,considerarestadefinicindeestructura:
structempaquetado{ unsignedintb1:1; unsignedintb2:1; unsignedintb3:1; unsignedintb4:1; unsignedinttipo:4; unsignedintent_raro:9; }paquete;

Laestructuraempaquetadocontiene6miembros:4banderasde1bit(b1,b2,b3yb4),unode4 bits(tipo)yotrode9bits(ent_raro). Cautomticamenteempacaloscamposdebitanteriorestancompactamentecomoseaposible, dondelalongitudmximadelcampoesmenorqueoigualalalongituddelapalabraenteradela computadora.Sinofueraelcaso,entoncesalgunoscompiladorespodranpermitirtraslapeen memoriaparaloscampos,mientrasotrospodranguardarelsiguientecampoenlasiguiente palabra.

Laformadeaccesarlosmiembrosesenlaformausual:
paquete.tipo=7;

Conestructuraanteriorsetieneque:

Solamentelosnbitsmsbajossonasignadosaunnmerodenbits.Porlotanto,elcampo tiponopuedetomarvaloresmayoresque15,yaqueesde4bitsdelargo. Loscamposdebitsonsiempreconvertidosauntipoenterocuandosehacealgnclculo conellos. Sepermitemezclarlostipos``normales''conloscamposdebit.

11.2.1Portabilidad
Loscamposdebitsonunaformaconvenientedeexpresarmuchasoperacionesdificiles.Sin embargo,loscamposdebitcarecendeportabilidadentreplataformas,poralgunadelassiguientes razones:

Losenterospodranserconosinsigno. Muchoscompiladoreslimitanelnmeromximodebitsenelcampodebitaltamaodeun integer,elcualpodraserde16bitsode32bits. Algunosmiembroscamposdebitsonguardadosdeizquierdaaderecha,otrossonguardados dederechaaizquierdaenmemoria. Siloscamposdebitssonmuylargos,elsiguientecampodebitpodraserguardado consecutivamenteenmemoria(traslapandoloslmitesentrelaslocalidadesdememoria)o enlasiguientepalabradememoria.

11.3Ejercicios
1. Escribirunafuncinquemuestreunnmerode8bits(unsignedchar)enformatobinario. 2. Escribirunafuncinponerbits(x,p,n,y)queregresex,connbitsqueempiezanen laposicinpyestanaladerechadeunavariableyunsignedchar,dejndolosenxenla posicinpyalaizquierdadejandolosotrosbitssincambio. Porejemplo,six=10101010(170decimal),y=10100111(167 decimal),n=3yp=6,entoncessenecesitatomar3bitsdedey(111)yponerlosen xenlaposicin10xxx010paraobtenerlarespuesta10111010. Larespuestadebermostrarseenformabinaria(verprimerejercicio),sinembargola entradapuedeserenformadecimal. Lasalidapodrasercomolasiguiente:
x=10101010(binario) y=10100111(binario) ponerbitsn=3,p=6dax=10111010(binario)

3. Escribirunafuncinqueinviertalosbitsdex(unsignedchar)yguardelarespuestaeny. Larespuestadebermostrarseenformabinaria(verprimerejercicio),sinembargola entradapuedeestarenformadecimal. Lasalidapodrasercomolasiguiente:


x=10101010(binario) xinvertida=01010101(binario)

4. Escribirunafuncinquerote(nodesplaze)aladerechanposicionesdebitsdexdeltipo unsignedchar.Larespuestadebermostrarseenformabinaria(verprimerejercicio)yla entradapuedeserenformadecimal. Lasalidapodrasercomolasiguiente:


x=10100111(binario) xrotadapor3=11110100(binario)

Subsecciones

12.1Directivasdelpreprocesador 12.1.1 #define 12.1.2 #undef 12.1.3 #include 12.1.4 #if Inclusi ncondicional 12.2Controldelpreprocesadordelcompilador 12.3Otrasdirectivasdelpreprocesador 12.4Ejercicios

12.ElpreprocesadordeC 12.1Directivasdelpreprocesador
Comosecomentoenelprimercaptuloelpreprocesamientoeselprimerpasoenlatapade compilacindeunprogramaestapropiedadesnicadelcompiladordeC. Elpreprocesadortienemsomenossupropiolenguajeelcualpuedeserunaherrramientamuy poderosaparaelprogramador.Todaslasdirectivasdepreprocesadorocomandosinicianconun#. Lasventajasquetieneusarelpreprocesadorson: losprogramassonmsfcilesdedesarrollar, sonmsfcilesdeleer, sonmsfcilesdemodificar yelcdigodeCesmstransportableentrediferentesarquitecturasdemquinas.

12.1.1#define
Elpreprocesadortambinpermiteconfigurarellenguaje.Porejemplo,paracambiaralassentencias debloquedecdigo{...}delimitadoresquehayainventadoelprogramadorcomoinicio ...finsepuedehacer:
#defineinicio{ #definefin}

Durantelacompilacintodaslasocurrenciasdeinicioyfinsernreemplazadasporsu correspondiente{o}delimitadorylassiguientestapasdecompilacindeCnoencontrarn ningunadiferencia. Ladirectiva#defineseusaparadefinirconstantesocualquiersustitucindemacro.Suformato eselsiguiente: #define<nombredemacro><nombredereemplazo> Porejemplo:


#defineFALSO0 #defineVERDADERO!FALSO

Ladirectiva#definetieneotrapoderosacaracterstica:elnombredemacropuedetener argumentos.Cadavezqueelcompiladorencuentraelnombredemacro,losargumentosreales encontradosenelprogramareemplazanlosargumentosasociadosconelnombredelamacro.Por ejemplo:


#defineMIN(a,b)(a<b)?a:b main() { intx=10,y=20; printf("ELminimoes%d\n",MIN(x,y)); }

Cuandosecompilaesteprograma,elcompiladorsustiuirlaexpresindefinidaporMIN(x,y), exceptoquexeysernusadoscomolosoperandos.Asdespusdequeelcompiladorhacela sustitucin,lasentenciaprintfsersta:


printf("Elminimoes%d\n",(x<y)?x:y);

ComosepuedeobservardondesecoloqueMIN,eltextoserreemplazadoporladefinicin apropiada.Porlotanto,sienelcdigosehubierapuestoalgocomo:
x=MIN(q+r,s+t);

despusdelpreprocesamiento,elcdigopodraversedelasiguienteforma:
x=(q+r<s+t)?q+r:s+t;

Otrosejemplosusando#definepuedenser:
#defineDeg_a_Rad(X)(X*M_PI/180.0) /*Conviertegradossexagesimalesaradianes,M_PIeselvalordepi*/ /*yestadefinidaenlabibliotecamath.h*/ #defineIZQ_DESP_8<<8

LaltimamacroIZQ_DESP_8essolamentevlidaentantoelreemplazodelcontextoesvlido, porejemplo:x=yIZQ_DESP_8. Elusodelasustitucindemacrosenellugardelasfuncionesrealestieneunbeneficioimportante:

incrementalavelocidaddelcdigoporquenosepenalizaconunallamadadefuncin.Sinembargo, sepagaesteincrementodevelocidadconunincrementoeneltamaodelprogramaporquese duplicaelcdigo.

12.1.2#undef
Seusa#undefparaquitarunadefinicindenombredemacroquesehayadefinidopreviamente. Elformatogenerales: #undef<nombredemacro> Elusoprincipalde#undefespermitirlocalizarlosnombresdemacrossloenlasseccionesde cdigoquelosnecesiten.

12.1.3#include
Ladirectivadelpreprocesador#includeinstruyealcompiladorparaincluirotroarchivofuenteque estadadoconestadirectivaydeestaformacompilarotroarchivofuente.Elarchivofuentequese leersedebeencerrarentrecomillasdoblesoparntesisdengulo.Porejemplo:
#include<archivo> #include"archivo"

Cuandoseindica<archivo>seledicealcompiladorquebusquedondeestanlosarchivos incluidoso``include''delsistema.UsualmentelossistemasconUNIXguardanlosarchivosenel directorio/usr/include. Siseusalaforma"archivo"esbuscadoeneldirectorioactual,esdecir,dondeelprogramaesta siendoejecutado. Losarchivosincluidosusualmentecontienenlosprototiposdelasfuncionesylasdeclaracionesde losarchivoscabecera(headerfiles)ynotienencdigodeC(algoritmos).

12.1.4#ifInclusincondicional
Ladirectiva#ifevaluaunaexpresinconstanteentera.Siempresedebeterminarcon#endif paradelimitirelfindeestasentencia. Sepuedenasmismoevaluarotrocdigoencasosecumplaotracondicin,obien,cuandonose cumpleningunausando#elifo#elserespectivamente. Porejemplo,
#defineMEX0 #defineEUA1 #defineFRAN2

#definePAIS_ACTIVOMEX #ifPAIS_ACTIVO==MEX charmoneda[]="pesos"; #elifPAIS_ACTIVO==EUA charmoneda[]="dolar"; #else charmoneda[]="franco"; #endif

Otromtododecompilacincondicionalusalasdirectivas#ifdef(sidefinido)y#ifndef(sino definido). Elformatogeneralde#ifdefes: #ifdef<nombredemacro> <secuenciadesentecias> #endif Sielnombredemacrohasidodefinidoenunasentencia#define,secompilarlasecuenciade senteciasentreel#ifdefy#endif. Elformatogeneralde#ifdefes: #ifndef<nombredemacro> <secuenciadesentecias> #endif Lasdirectivasanterioressontilespararevisarsilasmacrosestndefinidastalvezpormdulos diferentesoarchivosdecabecera. Porejemplo,paraponereltamaodeunenteroparaunprogramaportableentreTurboCdeDOSy unsistemaoperativoconUNIX,sabiendoqueTurboCusaenterosde16bitsyUNIXenterosde32 bits,entoncessisequierecompilarparaTurboCsepuededefinirunamacroTURBOC,lacualser usadadelasiguienteforma:
#ifdefTURBOC #defineINT_SIZE16 #else #defineINT_SIZE32 #endif

12.2Controldelpreprocesadordelcompilador
Sepuedeusarelcompiladorgccparacontrolarlosvaloresdadosodefinidosenlalneade comandos.Estopermitealgunaflexibilidadparaconfigurarvaloresademasdeteneralgunasotras funcionestiles.Paraloanterior,seusalaopcinDmacro[=defn],porejemplo:
gccDLONGLINEA=80prog.coprog

quehubiesetenidoelmismoresultadoque
#defineLONGLINEA80

encasodequehubieradentrodelprograma(prog.c)algn#defineo#undefpasarapor encimadelaentradadelalneadecomandos,yelcompiladorpodramandarun``warning''sobre estasituacin. Tambinsepuedeponerunsmbolosinvalor,porejemplo:


gccDDEBUGprog.coprog

Endondeelvalorquesetomaesde1paraestamacro. Lasaplicacionespuedenserdiversas,comoporejemplocuandosequierecomounabanderapara depuracinsepuedehaceralgocomolosiguiente:


#ifdefDEBUG printf("Depurando:Versindelprograma1.0\n"); #else printf("Versiondelprograma1.0(Estable)\n"); #endif

Comoloscomandosdelpreprocesadorpuedenestarencualquierpartedeunprograma,sepueden filtrarvariablesparamostrarsuvalor,cuandoseestadepurando,verelsiguienteejemplo:
x=y*3; #ifdefDEBUG printf("Depurando:variablesxeyigualesa\n",x,y); #endif

LaopcinEhacequelacompilacinsedetengadespusdelatapadepreprocesamiento,porlo anteriornoseestapropiamentecompilandoelprograma.Lasalidadelpreprocesamientoesenviada alaentradaestndar.GCCignoralosarchivosdeentradaquenorequieranpreprocesamiento.

12.3Otrasdirectivasdelpreprocesador
Ladirectiva#errorforzaalcompiladorapararlacompilacincuandolaencuentra.Seusa principalmenteparadepuracin.Porejemplo:
#ifdefOS_MSDOS #include<msdos.h> #elifdefOS_UNIX #include"default.h" #else #errorSistemaOperativoincorrecto #endif

Ladirectiva#linenmero``cadena''informaalpreprocesadorcualeselnmerosiguientedela lneadeentrada.Cadenaesopcionalynombralasiguientelneadeentrada.Estoesusado frecuentementecuandosontraducidosotroslenguajesaC.Porejemplo,losmensajesdeerror producidosporelcompiladordeCpuedenreferenciarelnombredelarchivoylalneadelafuente

originalenvezdelosarchivosintermediosdeC. Porejemplo,losiguienteespecificaqueelcontadordelneaempezarcon100.
#line100"test.c"/*inicializaelcontadordelineaynombredearchivo*/ main()/*linea100*/ { printf("%d\n",__LINE__);/*macropredefinida,linea102*/ printf("%s\n",__FILE__);/*macropredefinidaparaelnombre*/ }

12.4Ejercicios
1. Definirunamacromin(a,b)paradeterminarelenteromspequeo.Definirotramacro min3(a,b,c)entrminosdemin(a,b).Incorporarlasmacrosenunprograma demostrativoendondesepidaalusuariotresnmerosysemuestreelmspequeo. 2. Definirunnombredemacrodepreprocesadorparaseleccionar: losbitsmenossignificativosdeuntipodedatounsignedchar. elnsimobit(asumiendoqueelmenossignificativoes0)deuntipodedato unsignedchar.

Subsecciones

13.1VentajasdelusarUNIXconC 13.2Usodefuncionesdebibliotecasyllamadasdelsistema

13.C,UNIXylasbibliotecasestndar
ExisteunarelacinestrechaentreCyelsistemaoperativoqueejecutalosprogramasdeC.El sistemaoperativoUNIXestaescritoensumayorparteconC.EnestecaptulosevercomoCy UNIXinteractunjuntos. SeusaUNIXparamanejarelespaciodelarchivo,paraeditar,compilaroejecutarprogramas,entre otrascosas. SinembargoUNIXesmuchomstilqueloanterior.

13.1VentajasdelusarUNIXconC

PortabilidadUnixoalgunavariantedeUNIXestndisponiblesenmuchasmquinas.Los programasescritosconUNIXyCestndaresdebencorrerencualquiermquina prcticamentesinningnproblema. Multiusuario/MultitareaMuchosprogramaspuedencompartirlacapacidadde procesamientodelasmquinas. ManejodearchivosElsistemajerrquicodearchivosempleamuchasrutinasdemanejode archivos. ProgramacindelShellUNIXsuministraunintrpretedecomandospoderosoqueentiende masde200comandosyquepuedetambincorrerUNIXoprogramasdelusuario. EntubamientooPipePermitelaconexinentreprogramas,endondelasalidadeun programapuedeserlaentradadeotro.Loanteriorpuedehacercedesdelalneadecomandos odentrodeunprogramadeC. UtilerasdeUNIXHaycercade200utilerasquepermitenejecutarmuchasrutinassin escribirnuevosprogramas.Porejemplo:make,grepdiff,awk,etc. LlamadasalsistemaUNIXtieneaproximadamente60llamadasalsistema,quesonel corazndelsistemaoperativoodelkerneldeUNIX.Lasllamadasestnactualmenteescritas enC.TodasellaspuedenseraccesadasdesdeprogramasdeC.Ejemplosdeestassonel sistemabsicodeE/S,accesoalrelojdelsistema.Lafuncinopen()esunejemplodeuna llamadaalsistema. BibliotecadefuncionesQuesonadicionesalsistemaoperativo.

13.2Usodefuncionesdebibliotecasyllamadas delsistema
ParausarlasbibliotecasdefuncionesylasllamadasalsistemaenunprogramadeCsimplementese debellamarlafuncinapropiadadeC. EjemplosdelasfuncionesdelabibliotecaestndarquehansidovistassonlasfuncionesdeE/Sde altonivelfprintf(),malloc(),... Operadoresaritmticos,generadoresdenmerosaleatoriosrandom(),srandom(),lrand48(), drand48(),etc.yfuncionesparaconversindecadenasalostiposbsicosdeC(atoi(),atof(),etc.) sonmiembrosdelabibliotecaestndarstdlib.h. Todaslasfuncionesmatemticascomosin(),cos(),sqrt()sonfuncionesdelabiblioteca estndardematemticas(math.h). Paramuchasllamadasdelsistemayfuncionesdelasbibliotecassetienequeincluirelarchivo cabeceraapropiado,porejemplo:stdio.h,math.h. Parausarunafuncinsedebeasegurardehaberpuestoloscorrespondientes#includeenel archivodeC.Deestaformalafuncinpuedeserllamadacorrectamente. Esimportanteasegurarsequelosargumentostenganlostiposesperados,deotraformalafuncin probablementeproducirresultadosextraos. Algunasbibliotecasrequierenopcionesextrasantesdequeelcompiladorpuedasoportarsuuso.Por ejemplo,paracompilarunprogramaqueincluyafuncionesdelabibliotecamath.helcomando podraserdelasiguienteforma:
gccmatprog.comatprog.clm

Laopcinfinallmesunainstruccinparaligarlabibliotecamatemticaconelprograma.La pginademanparacadafuncinusualmenteinformasiserequierealgunabanderadecompilacin especial. Informacindecasitodaslasllamadasalsistemayfuncionesdebibliotecaestndisponiblesenlas pginasdelman.Seencuentrandisponiblesenlneacontansloteclearmanyelnombredela funcin.Porejemplo:


mandrand48

nosdarinformacinacercadestegeneradordenmerosaleatorios.

Subsecciones

14.1Funcionesaritm ticas 14.2Nmerosaleatorios 14.3Conversindecadenas 14.4Bsquedayordenamiento 14.5Ejercicios

14.Biblioteca<stdlib.h>
Parausartodaslasfuncionesdestabibliotecasedebetenerlasiguientedirectiva
#include<stdlib.h>

Lasfuncionesdelabibliotecapuedenseragrupadasentrescategorasbsicas:

Aritmticas; Nmerosaleatorios;y Conversindecadenas.

Elusodetodaslasfuncionesessencillo.Seconsiderandentrodelcaptuloenformabreve.

14.1Funcionesaritmticas
Haycuatrofuncionesenterasbsicas:
intabs(intj); longintlabs(longintj); div_tdiv(intnumer,intdenom); ldiv_tldiv(longintnumer,longintdenom);

Fundamentalmentehaydosfuncionesparaenterosyparacompatibilidadconenteroslargos.

abs()Lafuncinregresaelvalorabsolutodelargumentoenteroj. div()Calculaelvalornumerentredenomydevuelveelcocienteyelrestoenuna estructurallamadadiv_tquecontienedosmiembrosllamadosquotyrem.

Laestructuradiv_testadefinidaenstdlib.hcomosigue:
typedefstruct{ intquot;/*cociente*/ intrem;/*residuo*/ }div_t;

Laestructuraldiv_tesdefinidadeunaformasimilar.

Semuestraunejemplodondesehaceusodelafuncindiv_t:
#include<stdlib.h> main() { intnum=8,den=3; div_tres; res=div(num,den); printf("Respuesta:\n\tCociente=%d\n\tResiduo=%d\n", res.quot,res.rem); }

quegeneralasiguientesalida:
Respuesta: Cociente=2 Residuo=2

14.2N merosaleatorios
Losnmerosaleatoriossontilesenprogramasquenecesitansimulareventosaleatorios,tales comojuegos,simulacionesyexperimentos.Enlaprcticaningunafuncinproducedatosaleatorios verdaderoslasfuncionesproducennmerospseudoaleatorios.Losnmerosaleatoriosson calculadosapartirdeunafrmuladada(losdistintosgeneradoresusandiferentesfrmulas)ylas secuenciasdenmerosquesonproducidasserepiten.Unasemilla(seed)esusualmenteinicializada paraquelasecuenciaseagenerada.Porlotanto,silasemillaessiempreinicializadaconelmismo valortodoeltiempo,elmismoconjuntosersiemprecalculado. Unatcnicacomnparaintroducirmsaleatoriedadenelgeneradordenmerosaleatorioses usandoeltiempoylafechaparainicializarlasemilla,yaquestesiempreestarcambiando. Haymuchasfuncionesdenmeros(pseudo)aleatoriosenlabibliotecaestndar.Todasellasoperan conlamismaideabsicaperogeneransecuenciasdiferentesdenmeros(basadasenfunciones generadorasdiferentes)sobrerangosdiferentesdenmeros. Elconjuntomssimpledefuncioneses:
intrand(void); voidsrand(unsignedintsemilla);

rand()Lafuncindevuelveunenteropseudoaleatorioentre0y

(RAND_MAX).

srand()Establecesuargumentocomolasemilladeunanuevaseriedeenterospseudo aleatorios.

Unejemplosencillodelusodeltiempodelafechaesinicializandolasemillaatravsdeuna llamada:
srand((unsignedint)time(NULL));

Elsiguienteprogramatarjeta.cmuestraelusodeestasfuncionesparasimularunpaquetede tarjetasqueestasiendorevueltas.
/* **Seusannumerosaleatoriospararevolverlas"tarjetas"delabaraja. **Elsegundoargumentodelafuncionindicaelnumerodetarjetas. **Laprimeravezqueestafuncionesllamada,srandes **llamadaparainicializarelgeneradordenumerosaleatorios. */ #include<stdlib.h> #include<time.h> #defineVERDADERO1 #defineFALSO0 voidintercambiar(int*baraja,intn_cartas) { inti; staticintprimera_vez=VERDADERO; /* **Inicializarelgeneradordenumerosconlafechaactual **siaunnosehahecho. */ if(primera_vez){ primera_vez=FALSO; srand((unsignedint)time(NULL)); } /* **"intercambiar"empleandoparesdecartas. */ for(i=n_cartas1;i>0;i=1){ intalguno; inttemp; alguno=rand()%i; temp=baraja[alguno]; baraja[alguno]=baraja[i]; baraja[i]=temp; } }

14.3Conversindecadenas
Existenunascuantasfuncionesparaconvertircadenasaenteros,enteroslargosyvaloresflotantes. Estasson:

doubleatof(constchar*cadena)Convierteunacadenaaunvalorflotante. intatoi(constchar*cadena)Convierteunacadenaaunvalorentero. intatol(constchar*cadena)Convierteunacadenaaunvalorenterolargo. doublestrtod(constchar*cadena,char**finap)Convierteunacadenaaunvalorde puntoflotante. doublestrtol(constchar*cadena,char*finap,intbase)Convierteunacadenaaunentero largodeacuerdoaunabasedada,lacualdeberestarentre2y36inclusive. unsignedlongstrtoul(constchar*cadena,char*finap,intbase)Convierteunacadenaa unenterolargosinsigno.

Variasdelasfuncionessepuedenusarenformadirecta,porejemplo:
char*cad1="100"; char*cad2="55.444"; char*cad3="1234"; char*cad4="123cuatro"; char*cad5="invalido123"; char*cad6="123E23Hola"; char*cad7; inti; floatf: i=atoi(cad1);/*i=100*/ f=atof(cad2);/*f=55.44*/ i=atoi(cad3);/*i=1234*/ i=atoi(cad4);/*i=123*/ i=atoi(cad5);/*i=0*/ f=strtod(cad6,&cad7);/*f=1.230000E+25ycad7=hola*/

Nota:

Loscaracteresenblancosonsaltados. Caracteresilegalessonignorados. Silaconversinnopuedeserhechaseregresaceroyerrnoespuestaconelvalor ERANGE.

14.4B squedayordenamiento
Labibliotecastdlib.htienedosfuncionestilesparahacerbsquedayordenamientodedatos decualquiertipo.Lafuncinqsort()yafuevistapreviamenteenlaseccin10.3. Paracompletarlalistaseanotaelprototipo,peroparaverunejemplopasaralcaptuloindicado. Lafuncinqsortdelabibliotecaestndaresmuytil,yaqueestadiseadaparaordenarun arregloporunvalorllavedecualquiertipoenordenascendente,contaldequeloselementosdel arregloseandeuntipofijo. Elprototipodelafuncindeacuerdoastdlib.hes:
voidqsort(void*base,size_tnmiemb,size_ttam, int(*compar)(constvoid*,constvoid*));

Similarmente,hayunafuncinparabsquedabinaria,bsearch()lacualtieneelsiguiente prototipoenstdlib.hcomo:
void*bsearch(constvoid*key,constvoid*base,size_tnmemb, size_tsize,int(*compar)(constvoid*,constvoid*));

Acontinuacinsemuestraunejemploquehaceusodelafuncinbsearch():
#defineTAM10 #include<stdio.h> #include<stdlib.h>

typedefstruct{ intllave; charinformacion[30]; }Registro; intcompara_registro(voidconst*i,voidconst*j) { inta,b; a=((Registro*)i)>llave; b=((Registro*)j)>llave; returnab; } main() { Registrollave; Registro*resp; Registroarreglo[TAM]; intlong_arreglo=TAM; arreglo[0].llave=43;arreglo[1].llave=9;arreglo[2].llave=0; arreglo[3].llave=3;arreglo[4].llave=4;arreglo[5].llave=9; arreglo[6].llave=10;arreglo[7].llave=12;arreglo[8].llave=30; arreglo[9].llave=203; printf("Introduceelvalordelallavequesebuscaraenelarreglo:"); scanf("%d",&llave.llave);/*valordelindicequeserabuscado*/ resp=(Registro*)bsearch(&llave,arreglo,long_arreglo, sizeof(Registro), compara_registro); if(resp!=NULL) printf("Selocalizolallave%d\n",resp>llave); else printf("Noselocalizoningunelementoconlallave%d\n", llave.llave); }

Lafuncinbsearch()regresaunapuntadoralregistroquecoincideconlallavedada,obien,el valorNULLsinoencuentraelregistro. Observarqueeltipodelargumentodelallavedebeserdelmismotipoqueladelarreglodelos elementos(ennuestrocasoRegistro).

14.5Ejercicios
1. Escribirunprogramaquesimuleellanzamientodeundado. 2. Escribirunprogramaquesimuleelmelate,endondeseseleccionan6nmerosenterosenun rangode1al44 3. Escribirunprogramaqueleaunnmerodelalneadeentradaygenereunnmeroflotante aleatorioenelrangode0aelnmerodeentrada.

Subsecciones

15.1Funcionesmatem ticas 15.2Constantesmatemticas

15.Biblioteca<math.h>
Labibliotecadematemticasesrelativamentefcildeusar,aligualquelasvistaspreviamente.Se debeincluirladirectivadepreprocesamiento#include<math.h>,ademsderecordardeligar labibliotecadematemticasalcompilar:
gccprogmat.coprogmatlm

Unerrorcomneselolvidarincluirelarchivo<math.h>.

15.1Funcionesmatemticas
Semuestraacontinuacinunalistadefuncionesmatemticas.Sonfcilesdeusaryalgunasdeellas hansidoyausadaspreviamente.Noseproporcionaejemplodelasmismas.

doubleacos(doublex)Calculaelarcocosenodex. doubleasin(doublex)Calculaelarcosenodex. doubleatan(doublex)Devuelveelarcotangenteenradianes. doubleatan2(doubley,doublex)Calculaelarcotangentedelasdosvariables xey.Essimilaracalcularelarcotangentedey/x,exceptoenquelossignosdeambos argumentossonusadosparadeterminarelcuadrantedelresultado. doubleceil(doublex)Redondeaxhaciaarribaalenteromscercano. doublecos(doublex)devuelveelcosenodex,dondexestdadoenradianes. doublecosh(doublex)Devuelveelcosenohiperblicodex. doubleexp(doublex)Devuelveelvalordee(labasedeloslogaritmosnaturales) elevadoalapotenciax. doublefabs(doublex)Devuelveelvalorabsolutodelnmeroenpuntoflotantex. doublefloor(doublex)Redondeaxhaciaabajoalenteromscercano. doublefmod(doublex,doubley)Calculaelrestodeladivisindexentrey.El valordevueltoesxn*y,dondeneselcocientedex/y. doublefrexp(doublex,int*exp)Seempleaparadividirelnmeroxenuna fraccinnormalizadayunexponentequeseguardaenexp . longintlabs(longintj)Calculaelvalorabsolutodeunenterolargo. doubleldexp(doublex,intexp)Devuelveelresultadodemultiplicarel nmeroxpor2elevadoaexp(inversadefrexp). doublelog(doublex);Devuelveellogaritmoneperianodex. doublelog10(doublex)Devuelveellogaritmodecimaldex.

doublemodf(doublex,double*iptr)Divideelargumentoxenunaparte enterayunapartefraccional.Laparteenteraseguardaeniptr. doublepow(doublex,doubley)Devuelveelvalordexelevadoay. doublesin(doublex)Devuelveelsenodex. doublesinh(doublex)Regresaelsenohiperblicodex. doublesqrt(doublex)Devuelvelarazcuadradanonegativadex. doubletan(doublex)Devuelvelatangentedex. doubletanh(doublex)Devuelvelatangentehiperblicadex.

15.2Constantesmatemticas
Labibliotecadematemticasdefinevariasconstantes(porlogeneraldesechadas).Siemprees aconsejableusarestasdefiniciones.

M_ELabasedeloslogaritmosnaturalese. M_LOG2EEllogaritmodeedebase2. M_LOG10EEllogaritmodeedebase10. M_LN2Ellogartimonaturalde2. M_LN10Ellogaritmonaturalde10. M_PI M_PI_2 M_PI_4 M_1_PI M_2_PI

M_2_SQRTPI

M_SQRT2Larazcuadradapositivade2 M_SQRT1_2Larazcuadradapositivade1/2

Subsecciones

16.1Reportandoerrores 16.1.1 perror() 16.1.2 errno 16.1.3 exit 16.2Flujos 16.2.1Flujospredefinidos 16.2.1.1Redireccionamiento 16.3E/SBasica 16.4E/Sformateada 16.4.1 printf 16.4.2 scanf 16.5Archivos 16.5.1Lecturayescrituradearchivos sprintf 16.6 y sscanf 16.6.1Peticindelestadodelflujo 16.7E/Sdebajonivelosinalmacenamientointermedio 16.8Ejercicios

16.Entradaysalida(E/S)stdio.h
Enestecaptulosevernvariasformasdeentradaysalida(E/S).Sehanmencionadobrevemente algunasformasyahoraserevisarnconunpocomsdedetalle. LosprogramasquehaganusodelasfuncionesdelabibliotecadeE/Sdebenincluirlacabecera, estoes:
#include<stdio.h>

16.1Reportandoerrores
EnmuchasocasionesestilreportarloserroresenunprogramadeC.Lafuncindelabiblioteca estndarperroreslaindicadaparahacerlo.Esusadaconjuntamenteconlavariableerrnoy frecuentementecuandoseencuentraunerrorsedeseaterminarelprogramaantes.Ademsserevisa lafuncinexit()yerrno,queenunsentidoestrictonosonpartedelabibliotecastdio.h,para vercomotrabajanconperror.

16.1.1perror()
Elprototipodelafuncionperrores:
voidperror(constchar*s);

Lafuncinperror()produceunmensajequevaalasalidaestndardeerrores,describiendoel ltimoerrorencontradoduranteunallamadaalsistemaoaciertasfuncionesdebiblioteca.La cadenadecaracteressquesepasacomoargumento,semuestraprimero,luegounsignodedos puntosyunespacioenblanco;porltimo,elmensajeyunsaltodelnea.Paraserdemsutilidad, lacadenadecaracterespasadacomoargumentodeberaincluirelnombredelafuncinqueincurri enelerror.Elcdigodelerrorsetomadelavariableexternaerrno,quetomaunvalorcuando ocurreunerror,peronoespuestaaceroenunallamadanoerrnea.

16.1.2errno
Alavariableespecialdelsistemaerrnoalgunasllamadasalsistema(yalgunasfuncionesde biblioteca)ledanunvalorentero,paraindicarquehahabidounerror.Estavariableestadefinidaen lacabecera#include<errno.h>yparaserusadadentrodeunprogramadebeserdeclarada delasiguienteforma:
externinterrno;

Elvalorsloessignificativocuandolallamadadevolviunerror(usualmente1),algunasveces unafuncintambinpuededevolver1comovalorvlido,porloquesedebeponererrnoacero antesdelallamada,parapoderdetectarposibleserrores.

16.1.3exit
Lafuncinexittieneelsiguienteprototipodeacuerdoalacabecera#include<stdlib.h>:
voidexit(intstatus);

Lafuncinproducelaterminacnnormaldelprogramayladevolucindestatusalprocesopadreo alsistemaoperativo.Elvalordestatusesusadoparaindicarcomohaterminadoelprograma: o o saleconunvalorEXIT_SUCCESSenunaterminacin saleconunvalorEXIT_FAILUREenunaterminacin Porlotantocuandoseencuentreunerrorsellamaralafuncincomoexit(EXIT_FAILURE) paraterminarunprogramaconerrores.

16.2Flujos
Losflujossonunaformaflexibleyeficienteparaleeryescribirdatos. ExisteunaestructurainternadeC,FILE,lacualrepresentaatodaslosflujosyestadefinidaen stdio.h.Porlotantosimplementesenecesitareferirsealaestructurapararealizarentraday salidadedatos. Parausarlosflujosentoncessedebedeclararunavariableoapuntadordeestetipoenelprograma. Noserequiereconocermsdetallesacercadeladefinicin.Sedebeabrirunflujoantesderealizar cualquierE/S,despussepuedeaccesaryentoncessecierra. ElflujodeE/SusaunBUFFER,esdecir,unpedazofijodereatemporaldelamemoria(elbuffer) esledooescritoaunarchivo.Losiguientesemuestraenlafigura17.1.Observarqueelapuntador delarchivoactualmenteapuntaastebuffer.

Figura16.1:Modelodeentradasalidausandounbuffer. EstoconduceaunusoeficientedeE/Sperosedebetenercuidado:losdatosescritosaunbufferno aparecenenunarchivo(odispositivo)hastaqueelbufferesescrito(con\nsepuedehacer). Cualquiersalidaanormaldelcdigopuedecausarproblemas.

16.2.1Flujospredefinidos
EnUNIXsetienenpredefinidos3flujos(enstdio.h):stdin,stdoutystderr. TodasellasusantextocomomtododeE/S. Losflujosstdinystdoutpuedenserusadasconarchivos,programas,dispositivosdeE/Scomoel teclado,laconsola,etc.Elflujostderrsiemprevaalaconsolaolapantalla. Laconsolaeseldispositivopredefinidoparastdoutystderr.Eltecladoloesparastdin.

Losflujospredefinidossonautomticamenteabiertas.

16.2.1.1Redireccionamiento
LosiguientenoespartedeC,perodependedelsistemaoperativo.Sehaceredireccionamiento desdelalneadecomandoscon: >queredireccionastdoutaunarchivo. Porlotanto,sisetieneunprogramallamadosalida,queusualmentemuestraenpantallaalgo, entonces: salida>archivo_sal mandarlasalidaalarchivoarchivo_sal <redireccionastdindesdeunarchivoaunprograma. Porlotanto,siseesperaentradadesdeeltecladoparaunprogramallamadoentrada,sepuedeleer enformasimilarlaentradadesdeunarchivo. entrada<archivo_ent Con|entubamientoopipesecolocastdoutdeunprogramaenstdindeotro, prog1|prog2 Porejemplo,mandarlasalida(usualmenteaconsola)deunprogramadirectamentealaimpresora out|lpr

16.3E/SBasica
HayunpardefuncionesquedanlasfacilidadesbsicasdeE/S.Quizslasmscomunesson: getchar()yputchar().Estndefinidasysonusadascomosigue:

intgetchar(void)leeuncaracterdestdin intputchar(charch)escribeuncaracterastdoutyregresaelcaracterescrito.

main(){ intch; ch=getchar(); (void)putchar((char)ch);}

Otrasfuncionesrelacionadasson:
intgetc(FILE*flujo); intputc(charch,FILE*flujo);

16.4E/Sformateada
SehanvistoyaalgunosejemplosdecomoCusalaE/Sformateada.Enestaseccinserevisarncon msdetalle.

16.4.1printf
Elprototipodelafuncinestadefinidocomo:
intprintf(constchar*formato,listaarg...);

quemuestraenstdoutlalistadeargumentosdeacuerdoalformatoespecificado.Lafuncin devuelveelnmerodecaracteresimpresos. Lacadenadeformateotienedostiposdeobjetos:


caracteresordinariosestossoncopiadosalasalida. especificadoresdeconversinprecedidospor%ylistadosenlatabla16.1.

Tabla16.1:Caracteresdeformatprintf/scanf Especificador(%) c i,d o x,X u s f e,E g,G % Tipo char int int int int char* " " Resultado unslocaracter nmerobasediez nmerobaseocho nmerobasedieciseis notacinmins/mays enterosinsigno impresindecadena terminadapornulo NotacinCientfica 1.23e002 eflaquesea mscompacta caracter%

double/float formatom.ddd...

Entreel%yelcaracterdeformatosepuedeponer:

signomenosparajustificaralaizquierda. nmeroenteroparaelanchodelcampo. m.dendondemeselanchodelcampo,ydeslaprecisindedgitosdespusdelpunto decimaloelnmerodecaracteresdeunacadena.

Porlotanto:
printf("%2.3f\n",17.23478);

lasalidaenpantallaser:
17.235

y
printf("VAT=17.5%%\n");

generalasiguientesalida:
VAT=17.5%

16.4.2scanf
Lafuncinestadefinidacomosigue:
intscanf(constchar*formato,listaarg...);

Leedelaentradaestndar(stdin)ycolocalaentradaenladireccindelasvariablesindicadasen listaargs.Regresaelnmerodecaracteresledos. Lacadenadecontroldeformateoessimilaraladeprintf. Importante:serequiereladireccindelavariableounapuntadorconscanf. Porejemplo:


scanf("%d",&i);

Paraelcasodeunarregloocadenasloserequiereelnombredelmismoparapoderusarscanfya quecorrespondealiniciodeladireccindelacadena.
charcadena[80]; scanf("%s",cadena);

16.5Archivos
Losarchivossonlaformamscomndelosflujos.

Loprimeroquesedebehaceresabrirelarchivo.Lafuncinfopen()hacelosiguiente:
FILE*fopen(constchar*nomb,constchar*modo);

fopenregresaunapuntadoraunFILE.Enlacadenanombseponeelnombreylatrayectoriadel archivoquesedeseaaccesar.Lacadenamodocontrolaeltipodeacceso.Siunarchivonopuedeser accesadoporalgunaraznunapuntadorNULLesdevuelto. Losmodosson:


``r''lectura; ``w''escritura;y ``a''

Paraabrirunarchivosedebetenerunflujo(apuntadortipoarchivo)queapuntealaestructura FILE. Porlotanto,paraabrirunarchivodenominadomiarch.datparalecturaharemosalgocomolo siguiente;


FILE*flujo;/*Sedeclaraunflujo*/ flujo=fopen("miarch.dat","r");

esunabuenaprcticarevisarsiunarchivosepudoabrircorrectamente
if((flujo=fopen("miarch.dat","r"))==NULL) { printf("Nosepudoabrir%s\n","miarch.dat"); exit(1); } .....

16.5.1Lecturayescrituradearchivos
Lasfuncionesfprintfyfscanfsoncomnmenteempleadasparaaccesararchivos.
intfprintf(FILE*flujo,constchar*formato,args...); intfscanf(FILE*flujo,constchar*formato,args...);

Lasfuncionessonsimilaresaprintfyscanfexceptoquelosdatossonledosdesdeelflujo,el cualdeberserabiertoconfopen(). Elapuntadoralflujoesautomticamenteincrementadocontodaslasfuncionesdelecturay escritura.Porlotanto,nosedebepreocuparenhacerloanterior.


char*cadena[80]; FILE*flujo; if((flujo=fopen(...))!=NULL) fscanf(flujo,"%s",cadena);

Otrasfuncionesparaarchivosson:

intgetc(FILE*flujo)intfgetc(FILE*flujo) intputc(charch,FILE*s)intfputc(charch,FILE*s)

Estassonparecidasagetcharyputchar. getcestadefinidacomounamacrodelpreprocesadorenstdio.h.fgetcesunafuncindela bibliotecadeC.Conambasseconsigueelmismoresultado. Paraelvolcadodelosdatosdelosflujosadisco,obien,paradisasociarunflujoaunarchivo, haciendopreviamenteunvolcado,usar:


intfflush(FILE*flujo); intfclose(FILE*flujo);

Tambinsepuedeteneraccesoalosflujospredeterminadosconfprintf,etc.Porejemplo:
fprintf(stderr,"Nosepuedecalcular!!\n"); fscanf(stdin,"%s",string);

16.6sprintfysscanf
Sonparecidasafprintfyfscanfexceptoqueescriben/leenunacadena.
intsprintf(char*cadena,char*formato,args...) intsscanf(char*cadena,cahr*formato,args...)

Porejemplo:
floattanque_lleno=47.0;/*litros*/ floatkilometros=400; charkm_por_litro[80]; sprintf(km_por_litro,"Kilometrosporlitro=%2.3f",kilometros/tanque_lleno);

16.6.1Peticindelestadodelflujo
Existenunascuantasfuncionestilesparaconocerelestadodealgnflujoyquetienenlos prototipossiguientes:
intfeof(FILE*flujo); intferror(FILE*flujo); voidclearerr(FILE*flujo); intfileno(FILE*flujo);

feof()devuelveverdaderosielflujoindicadoestaenelfindelarchivo.Porlotantoparaleer unflujo,fp,lneaalneasepodrahaceralgocomo:
while(!feof(fp)) fscanf(fp,"%s",linea);

ferror()inspeccionaelindicadordeerrorparaelflujoindicado,regresandoverdaderosiun

errorhaocurrido. clearerr()limpialosindicadoresdefindeficheroyerrorparaelflujoindicado. fileno()examinaelargumentoflujoydevuelvesudescriptordefichero,comounentero.

16.7E/Sdebajonivelosinalmacenamiento intermedio
EstaformadeE/Sessinbuffercadarequerimientodelectura/escriturageneraunaccesoaldisco(o dispositivo)directamenteparatraer/ponerundeterminadonmerodebytes. Nohayfacilidadesdeformateoyaqueseestnmanipulandobytesdeinformacin. Loanteriorsignificaqueseestanusandoarchivosbinarios(ynodetexto). Envezdemanejarapuntadoresdearchivos,seempleaunmanejadordearchivodebajonivelo descriptordearchivo,elcualdaunenteronicoparaidentificarcadaarchivo. Paraabrirunarchivousar:
intopen(char*nomb,intflag);

queregresaundescriptordearchivo1sifalla. flagcontrolaelaccesoalarchivoytienelossiguientesmacrosdefinidasenfcntl.h:

O_APPENDelarchivoseabrirenmododesloaadir O_CREATsielarchivonoexiste,sercreado. O_EXCLabrirenformaexclusiva. O_RDONLYslolectura O_RDWRlecturayescritura O_WRONLYsloescritura

paraverotrasopcionesusarman. Lafuncin:
intcreat(char*nomb,intperms);

puedetambinserusadaparacrearunarchivo. Otrasfuncionesson:
intclose(intfd); intread(intfd,char*buffer,unsignedlongitud); intwrite(intfd,char*buffer,unsignedlongitud);

quepuedenserusadasparacerrarunarchivoyleer/escribirundeterminadonmerodebytesdela memoria/haciaunarchivoenlalocalidaddememoriaindicadaporbuffer.

Lafuncinsizeof()escomnmenteusadaparaindicarlalongitud. Lasfuncionesreadywriteregresanelnmerodebytesledos/escritoso1sifallan. Setieneacontinuacindosaplicacionesqueusanalgunasdelasfuncionesindicadas:


#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> main(intargc,char**argv) { floatbuffer[]={23.34,2.34,1112.33}; intdf; intbytes_esc; intnum_flot; /*Primeramentesecreaelarchivo*/ if((df=open(argv[1],O_CREAT,S_IRUSR|S_IWUSR))==1) {/*Error,archivonoabierto*/ perror("Archivodatos,apertura"); exit(1); } else printf("Descriptordearchivo%d\n",df); /*Despuesseabreparasolamenteescribir*/ if((df=open(argv[1],O_WRONLY))==1) {/*Error,archivonoabierto*/ perror("Archivodatos,apertura"); exit(1); } else printf("Descriptordearchivo%d\n",df); /*Enprimerlugarseescribeelnumerodeflotantesqueseranescritos */ num_flot=3; if((bytes_esc=write(df,&num_flot,sizeof(int)))==1) {/*Errorenlaescritura*/ perror("Archivodatos,escritura"); exit(1); } else printf("Escritos%dbytes\n",bytes_esc); /*Seescribeelarreglodeflotantes*/ if((bytes_esc=write(df,buffer,num_flot*sizeof(float)))==1) {/*Errorenlaescritura*/ perror("Archivodatos,escritura"); exit(1); } else printf("Escritos%dbytes\n",bytes_esc); close(df); }

Ejemplodelecturadelejemploanterior:

/*Esteprogramaleeunalistadeflotantesdeunarchivobinario.*/ /*Elprimerbytedelarchivoesunenteroindicandocuantos*/ /*flotanteshayenelarchivo.Losflotantesestandespuesdel*/ /*entero,elnombredelarchivosedaenlalineadecomandos.*/ #include<stdio.h> #include<fcntl.h> main(intargc,char**argv) { floatbuffer[1000]; intfd; intbytes_leidos; intnum_flot; if((fd=open(argv[1],O_RDONLY))==1) {/*Error,archivonoabierto*/ perror("Archivodatos"); exit(1); } if((bytes_leidos=read(fd,&num_flot,sizeof(int)))==1) {/*Errorenlalectura*/ exit(1); } if(num_flot>999){/*archmuygrande*/exit(1);} if((bytes_leidos=read(fd,buffer,num_flot*sizeof(float)))==1) {/*Errorenlalectura*/ exit(1); } }

16.8Ejercicios
1. Escribirunprogramaparacopiarunarchivoenotro.Los2nombresdelosarchivosson dadoscomolosprimerosargumentosdelprograma. Copiarbloquesde512bytescadavez.
Revisarqueelprograma: tengadosargumentosomostrar"Elprogramarequieredos argumentos"; elprimernombredearchivoseadelecturaomostrar"Nose puedeabrirarchivo...paralectura"; queelsegundonombredelarchivoseadeescrituraomostrar"No sepuedeabrirarchivo...paraescritura".

2. Escribirunprograma"ultimas"quemuestrelasltimasnlneasdeunarchivodetexto.ny elnombredelarchivodebernespecificarsedesdelalneadecomandos.Pordefecton deberser5.Elprogramadeberhacerelmejorusodelespaciodealmacenamiento. 3. Escribirunprogramaquecomparedosarchivosymuestrelaslneasquedifieran.Tip: buscarrutinasapropiadasparamanejodecadenasymanejodearchivos.Elprogramano debersermuygrande.

Subsecciones

17.1Funcionesbsicasparaelmanejodecadenas 17.1.1Bsquedaencadenas 17.2Pruebayconversi ndecaracteres <ctype.h> 17.3Operacionesconlamemoria <memory.h> 17.4Ejercicios

17.Manejodecadenas<string.h>
Recordandolapresentacindearregloshecha(captulo5)endondelascadenasestndefinidas comounarreglodecaracteresounapuntadoraunaporcindememoriaconteniendocaracteres ASCII.UnacadenaenCesunasecuenciadeceroomscaracteresseguidasporuncaracterNULLo \0:

Figura17.1:Representacindeunarreglo. EsimportantepreservarelcaracterdeterminacinNULL,yaqueconsteescomoCdefiney manejalaslongitudesdelascadenas.TodaslasfuncionesdelabibliotecaestndardeClorequieren paraunaoperacinsatisfactoria. Engeneral,apartedealgunasfuncionesrestringidasenlongitud(strncat(),strncmp()y strncpy()),almenosquesecreencadenasamano,nosedebernencontrarproblemas.Se debernusarlasfuncionesparamanejodecadenasynotratardemanipularlascadenasenforma manualdesmantelandoyensamblandocadenas.

17.1Funcionesbsicasparaelmanejode cadenas
Todaslasfuncionesparamanejodecadenastienensuprototipoen:
#include<string.h>

Lasfuncionesmscomunessondescritasacontinuacin:

char*strcpy(constchar*dest,constchar*orig)Copialacadenadecaracteresapuntada pororig(incluyendoelcarcterterminador'\0')alvectorapuntadopordest.Las

cadenasnodebensolaparse,yladedestino,debesersuficientementegrandecomopara alojarlacopia. intstrcmp(constchar*s1,constchar*s2)Comparalasdoscadenasdecaracteress1y s2.Devuelveunenteromenor,igualomayorquecerosiseencuentraques1es, respectivamente,menorque,iguala,omayorques2. char*strerror(interrnum)Devuelveunmensajedeerrorquecorrespondeaunnmerode error. intstrlen(constchar*s)Calculalalongituddelacadenadecaracteres. char*strncat(char*s1,constchar*s2,size_tn)Agregancaracteresdes2as1. intstrncmp(constchar*s1,char*s2,size_tn)Comparalosprimerosncaracteresdedos cadenas. char*strncpy(constchar*s1,constchar*s2,size_tn)Copialosprimerosncaracteresde s2as1. strcasecmp(constchar*s1,constchar*s2)versinqueignorasisonmaysculaso minsculasdestrcmp(). strncasecmp(constchar*s1,constchar*s2,size_tn)versininsensibleamaysculaso minsculasdestrncmp()quecomparalosprimerosncaracteresdes1.

Elusodemuchasfuncionesesdirecto,porejemplo:
char*s1="Hola"; char*s2; intlongitud; longitud=strlen("Hola");/*long=4*/ (void)strcpy(s2,s1);

Observarquetantostrcat()ystrcopy()regresanunacopiadesuprimerargumento,elcual eselarreglodestino.Observartambinqueordendelosargumentosesarreglodestinoseguidopor arreglofuentelocualavecesesunasituacinparahacerloincorrectamente. Lafuncinstrcmp()comparalexicogrficamentelasdoscadenasyregresa:


Menorquecerosis1eslxicamentemenorques2; Cerosis1ys2sonlxicamenteiguales; Mayorquecerosis1eslxicamentemayorques2;

Lasfuncionesdecopiadostrncat(),strncmp()ystrncpy()sonversionesms restringidasquesuscontrapartesmsgenerales.Realizanunatareasimilar,perosolamenteparalos primerosncaracteres.ObservarqueelcaracterdeterminacinNULLpodraservioladocuandose usaestasfunciones,porejemplo:


char*s1="Hola"; char*s2=2; intlongitud=2; (void)strncpy(s2,s1,longitud);/*s2="Ho"*/

dondes2notieneelterminadorNULL.

17.1.1B squedaencadenas
Labibliotecatambinproporcionavariasfuncionesdebsquedaencadenas.

char*strchr(constchar*s,intc)Devuelveunpunteroalaprimeraocurrenciadelcarcter cenlacadenadecaracteress. char*strrchr(constchar*s,intc)Encuentralaltimaocurrenciadelcaractercenla cadena. char*strstr(constchar*s1,constchar*s2)Localizalaprimeraocurrenciadelacadenas2 enlacadenas1. char*strpbrk(constchar*s1,constchar*s2)Regresaunapuntadoralaprimera ocurrenciaenlacadenas1decualquiercarcterdelacadenas2,ounapuntadornulosino hayuncaracterdes2queexistaens1. size_tstrspn(constchar*s1,constchar*s2)Calculalalongituddelsegmentoinicialdes1 queconstanicamentedecaracteresens2. size_tstrcspn(constchar*s1,constchar*s2)Regresaelnmerodecaracteresalprincipio des1quenocoincidencons2. char*strtok(char*s1,constchar*s2)Dividelacadenaapuntadaas1enunasecuenciade ``tokens'',cadaunodeellosestadelimitadoporunoomscaracteresdelacadenaapuntada pors2.

Lasfuncionesstrchr()ystrrchr()sonlasmssimplesdeusar,porejemplo:
char*s1="Hola"; char*resp; resp=strchr(s1,'l');

Despusdelaejecucin,respapuntaalalocalidads1+2. Lafuncinstrpbrk()esunafuncinmsgeneralquebuscalaprimeraocurrenciadecualquier grupodecaracteres,porejemplo:


char*s1="Hola"; char*resp; res=strpbrk(s1,"aeiou");

Enestecaso,respapuntaalalocalidads1+1,lalocalidaddelaprimerao. Lafuncinstrstr()regresaunapuntadoralacadenadebsquedaespecificadaounapuntador nulosilacadenanoesencontrada.Sis2apuntaaunacadenadelongitudcero(estoes,lacadena ""),lafuncinregress1.Porejemplo:


char*s1="Hola"; char*resp; resp=strstr(s1,"la");

lacualtendrresp=s1+2. Lafuncinstrtok()esunpocomscomplicadaencuantoaoperacin.Sielprimerargumento

noesNULLentonceslafuncinencuentralaposicindecualquieradeloscaracteresdelsegundo argumento.Sinembargo,laposicinesrecordadaycualquirllamadasubsecuenteastrtok() iniciarensaposicinsienestassubsecuentesllamadaselprimerargumentonoesNULL.Por ejemplo,sideseamosdividirlacadenas1usandocadaespacioeimprimircada``token''enuna nuevalneaharamoslosiguiente:


chars1[]="Holamuchachogrande"; char*t1; for(t1=strtok(s1,""); t1!=NULL; t1=strtok(NULL,"")) printf("%s\n",t1);

Seempleauncicloforenunaformanoregulardeconteo:

Enlainicializacinsellamaalafuncinstrtok()conlacadenas1. Seterminacuandot1esNULL. Seestaasignandotokensdes1at1hastalaterminacinllamandoastrtok()conel primerargumentoNULL.

17.2Pruebayconversindecaracteres <ctype.h>
Unabibliotecarelacionada#include<ctype.h>lacualcontienemuchasfuncionestilespara convertiryprobarcaracteresindividuales. Lasfuncionesmscomunespararevisarcaracterestienenlossiguientesprototipos:

intisalnum(intc)Verdadsicesalfanumrico. intisalpha(intc)Verdadsicesunaletra. intisascii(intc)VerdadsicesASCII. intiscntrl(intc)Verdadsicesuncaracterdecontrol. intisdigit(intc)Verdadsicesundgitodecimal. intisgraph(intc)Verdadsicesuncaracterimprimible,exceptuandoelespacioenblanco. intislower(intc)Verdadsicesunaletraminscula. intisprint(intc)Verdadsicesuncaracterimprimible,incluyendoelespacioenblanco. intispunct(intc)Verdadsicesunsignodepuntuacin. intisspace(intc)Verdadsicesunespacio intisupper(intc)Verdadsicesunaletramayscula. intisxdigit(intc)Verdadsicesundgitohexadecimal.

Lasfuncionesparaconversindecaracteresson:

inttoascii(intc)ConviertecaASCIIoununsignedcharde7bits,borrandolosbits altos. inttolower(intc)Conviertelaletracaminsculas,siesposible. inttoupper(intc)Conviertelaletracamaysculas,siesposible.

Elusodeestasfuncionesesdirectoyporlotanto,nosedanejemplos.

17.3Operacionesconlamemoria <memory.h>
Finalmenteseverunresumendealgunasfuncionesbsicasdememoria.Sinembargo,noson funcionesestrictamentedecadenas,perotienensuprototipoen#include<string.h>:

void*memchr(void*s,intc,size_tn)Buscauncaracterenunbuffer. intmemcmp(void*s1,void*s2,size_tn)Comparadosbuffers. void*memcpy(void*dest,void*fuente,size_tn)Copiaunbufferdentrodeotro. void*memmove(void*dest,void*fuente,size_tn)Mueveunnmerodebytesdeunbuffer aotro. void*memset(void*s,intc,size_tn)Ponetodoslosbytesdeunbufferauncaracterdado.

Elusodeestasfuncionesesdirectoyparecidoalasoperacionesdecomparacindecaracteres (exceptoquelalongitudexacta(n)detodaslasoperacionesdeberserindicadayaquenohayuna formapropiadeterminacin). Observarqueentodosloscasosbytesdememoriasoncopiados,porloquelafuncinsizeof() ayudaenestoscasos,porejemplo:


charfuente[TAM],dest[TAM]; intifuente[TAM],idest[TAM]; memcpy(dest,fuente,TAM);/*Copiachars(bytes)OK*/ memcpy(idest,ifuente,TAM*sizeof(int));/*Copiaarreglodeenteros*/

Lafuncinmemmove()secomportadelamismaformaquememcpy()exceptoquelas localidadesdelafuenteyeldestinopodrantraslaparse. Lafuncinmemcmp()essimilarastrcmp()exceptoqueunsignedbytessoncomparadosyse devuelvecerosis1esmenorques2,etc.

17.4Ejercicios
1. Escribirunafuncinsimilarastrlenquepuedamanejarcadenassinterminador.Tip:se necesitarconocerypasarlalongituddelacadena. 2. Escribirunafuncinqueregreseverdad,siunacadenadeentradaesunpalndromo.Un palndromoesunapalabraqueseleeigualdeizquierdaaderecha,odederechaaizquierda. Porejemplo,ANA. 3. Sugerirunaposibleimplementacindelafuncinstrtok(): 1. usandootrasfuncionesdemanejodecadenas. 2. desdelosprincipiosdeapuntadores. Cmoselograelalmacenamientodeunacadenaseparada? 4. Escribirunafuncinqueconviertatodosloscaracteresdeunacadenaamaysculas.

5. Escribirunprogramaqueinviertaelcontenidodelamemoriaenbytes.Esdecir,sisetienen nbytes,elbytedememorianseinvierteconelbyte0,elbyten1seintercambiaconelbyte 1,etc.

Subsecciones

18.1Funcionesparaelmanejodedirectorios <unistd.h> 18.1.1Busquedayordenamientodedirectorios: sys/types.h , sys/dir.h 18.2Rutinasdemanipulacindearchivos:unistd.h,sys/types.h,sys/stat.h 18.2.1Permisosdeaccesosaarchivos 18.2.1.1errno 18.2.2Estadodeunarchivo 18.2.3Manipulacindearchivos:stdio.h,unistd.h 18.2.4Creacindearchivostemporales: <stdio.h> 18.3Ejercicios

18.AccesodeArchivosyllamadasalsistema dedirectorios
Existenmuchasutilerasquepermitenmanipulardirectoriosyarchivos.Loscomandoscd,ls,rm, cp,mkdir,etc.sonejemplosquehansidorevisadosyaenelsistemaoperativo. SerevisarenestecaptulocomohacerlasmismastareasdentrodeunprogramaenC.

18.1Funcionesparaelmanejodedirectorios <unistd.h>
Pararealizarloserequierellamarlasfuncionesapropiadaspararecorrerlajerarquadedirectorioso preguntarsobreloscontenidosdelosdirectorios.

intchdir(char*path)cambiaaldirectorioindicadoenlacadenapath. char*getcwd(char*path,size_ttam)Obtienelatrayectoriacompleta,esdecir,desdela razdeldirectorioactual.pathesunapuntadoraunacadenadondelatrayectoriaser regresada.LafuncindevuelveunapuntadoralacadenaoNULLsiunerrorocurre.

SetieneacontinuacinlaemulacindelcomandocddeUnixconC:
#include<stdio.h> #include<unistd.h> #defineTAM80 main(intargc,char**argv)

{ charcadena[TAM]; if(argc<2) { printf("Uso:%s<directorio>\n",argv[0]); exit(1); } if(chdir(argv[1])!=0) { printf("Erroren%s.\n",argv[0]); exit(1); } getcwd(cadena,TAM); printf("Eldirectorioactuales%s\n",cadena); }

18.1.1Busquedayordenamientodedirectorios: sys/types.h,sys/dir.h
Dosfuncionestiles(enplataformasBSDyaplicacionesnomultithread)estndisponibles: intscandir(constchar*dir,structdirent**listanomb, int(*select)(conststructdirent*), int(*compar)(conststructdirent**,conststructdirent**) Estafuncinrastreaeldirectoriodir,llamandoselect()encadaentradadedirectorio.Las entradasparalasqueselect()devuelveunvalordistintodecerosealmacenanencadenasquese asignandelamemoriaconmalloc(),ordenadasusandoqsort()conlafuncinde comparacincompar(),ypuestasenlamatrizlistanomb.SiselectesNULL,se seleccionantodaslasentradas. intalphasort(conststructdirent**a,conststructdirent**b); Puedeserusadacomofuncindecomparacinparaquelafuncinscandir()pongalasentradas dedirectorioenordenalfabtico. AcontinuacinsetieneunaversinsimpledelcomandodeUNIXls
#include<dirent.h> #include<unistd.h> #include<sys/param.h> #include<stdio.h> #defineFALSO0 #defineVERDADERO!FALSO externintalphasort(); chartrayectoria[MAXPATHLEN];

main() { intcontar,i; structdirent**archivos; intselecc_arch(); if(getwd(trayectoria)==NULL) { printf("Errorobteniendolatrayectoriaactual\n"); exit(0); } printf("Directoriodetrabajoactual:%s\n",trayectoria); contar=scandir(trayectoria,&archivos,selecc_arch,alphasort); /*Sinoseencontraronarchivos*/ if(contar<=0) { printf("Nohayarchivosenestedirentorio\n"); exit(0); } printf("Hay%darchivos.\n",contar); for(i=0;i<contar;++i) printf("%s",archivos[i]>d_name); printf("\n");/*flushbuffer*/ } intselecc_arch(structdirent*entry) { if((strcmp(entry>d_name,".")==0)|| (strcmp(entry>d_name,"..")==0)) return(FALSO); else return(VERDADERO); }

scandirregresalospseudodirectorios(.),(..)ytambintodoslosarchivos.Enesteejemplose filtranlospseudodirectoriosparaquenosemuestrenhaciendoquelafuncinregreseFALSO. Losprototiposdelasfuncionesscandiryalphasorttienendefinicionesenlacabecera dirent.h MAXPATHLENestadefinidaensys/param.hylafuncingetwd()enunistd.h. Sepuedeirmslejosqueloanteriorybuscarporarchivosparticulares. Reescribiendolafuncinselecc_archparaqueslomuestrelosarchivosconlossufijos.c,.h y.o.


intselecc_arch(structdirent*entry) { char*ptr; if((strcmp(entry>d_name,".")==0)|| (strcmp(entry>d_name,"..")==0)) return(FALSO); /*Revisarlasextensionesdelosarchivos*/ ptr=rindex(entry>d_name,'.');/*Probarquetengaunpunto*/ if((ptr!=NULL)&& ((strcmp(ptr,".c")==0) ||(strcmp(ptr,".h")==0)

||(strcmp(ptr,".o")==0)) ) return(VERDADERO); else return(FALSO); }

Lafuncinrindex()esunafuncinparamanejodecadenasqueregresaunapuntadoralaltima ocurrenciadelcaractercenlacadenas,ounapuntadorNULLsicnoocurreenlacadena. (index()esunafuncinsimilarperoasignaunapuntadoralaprimeraocurrencia.)

18.2Rutinasdemanipulacindearchivos: unistd.h,sys/types.h,sys/stat.h
Existenvariasllamadasalsistemaquepuedenseraplicadasdirectamentealosarchivosguardados enundirectorio.

18.2.1Permisosdeaccesosaarchivos
Lafuncinintaccess(constchar*trayectoria,intmodo);determinalos permisosdeusuarioparaunfichero,deacueroconmodo,queestadefinidoen#include <unistd.h>,loscualespuedenser:

R_OKpruebaelpermisodelectura. W_OKpruebaelpermisodeescritura. X_OKpruebaelpermisodeejecucinobsqueda. F_OKpruebasisepermitelacomprobacindelaexistenciadelfichero.

Lafuncinaccess()regresa:0sihahabidoxito,o1encasodefallayaerrnoseleasigna unvaloradecuado.Verlaspginasdelmanparaverlalistadeerrores.

18.2.1.1errno
Algunasllamadasalsistema(yalgunasfuncionesdebiblioteca)danunvaloralenteroerrnopara indicarquehahabidounerror.Estaesunavariableespecialdelsistema. ParausarerrnoenunprogramadeC,debeserdeclaradodelasiguienteforma:
externinterrno;

EstapuedesermanualmentepuestodentrodeunprogramaenC,deotraformasimplementeretiene elltimovalor. Lafuncinintchmod(constchar*trayectoria,mode_tmodo);cambiaelmodo delarchivodadomediantetrayectoriaparaunmododado.

chmod()devuelve0encasodexitoy1encasodeerrorademsseasignaalavariableerrno unvaloradecuado(revisarlaspginasdemanparaverlostiposdeerrores)

18.2.2Estadodeunarchivo
Setienendosfuncionestilesparaconocerelestadoactualdeunarchivo.Porejemplosepuede sabequetangrandeesunarchivo(st_size),cuandofuecreado(st_ctime),etc(verladefinicindela estructuraabajo).Lasdosfuncionestienensusprototiposen<sys/stat.h>

intstat(constchar*nomb_arch,structstat*buf)obtieneinformacinacercadelarchivo apuntadopornomb_arch.Noserequierenpermisosdelectura,escrituraoejecucin,pero todoslosdirectorioslistadosennomb_archdebernestardisponibles. intfstat(intdesarch,structstat*buf)obtienelamismainformacinqueelanterior,pero sloelarchivoabiertoapuntadopordesarch(talycomolodevuelveopen())es examinadoenlugardenomb_arch.

Lasfuncionesstat()yfstat()regresan0encasoxito,1sihuboerroryerrnoes actualizadoapropiadamente. bufesunapuntadoralaestructurastatenlacuallainformacinescolocada.Laestructura statestadefinidaeninclude<sys/stat.h>,comosigue:


structstat { dev_tst_dev;/*dispositivo*/ ino_tst_ino;/*inodo*/ mode_tst_mode;/*proteccion*/ nlink_tst_nlink;/*numerodeenlacesfisicos*/ uid_tst_uid;/*IDdelusuariopropietario*/ gid_tst_gid;/*IDdelgrupopropietario*/ dev_tst_rdev;/*tipodispositivo(sies dispositivoinodo)*/ off_tst_size;/*tamaototal,enbytes*/ unsignedlongst_blksize;/*tamaodebloqueparael sistemadeficherosdeE/S*/ unsignedlongst_blocks;/*numerodebloquesasignados*/ time_tst_atime;/*horaultimoacceso*/ time_tst_mtime;/*horaultimamodificacion*/ time_tst_ctime;/*horaultimocambio*/ };

Semuestraunejemploquehaceusodelafuncinstat:
#include<stdio.h> #include<sys/stat.h>/*Paralaestructurastat*/ #include<unistd.h> main(intargc,char**argv) { structstatbuf; printf("%s\n",argv[0]); if(stat(argv[0],&buf)==1) {

perror(argv[0]); exit(1); } else { printf("Tamaodelarchivo%s%dbytes.\n",argv[0],buf.st_size); } }

18.2.3Manipulacindearchivos:stdio.h,unistd.h
Existenalgunasfuncionesparaborraryrenombrararchivos.Quizslaformamscomnesusando lasfuncionesdestdio.h:
intremove(constchar*pathname); intrename(constchar*viejo,constchar*nuevo);

Dosllamadasalsistema(definidasenunistd.h)lascualessonactualmenteusadasporlas funcionesremove()yrename()tambinexisten,perosonprobablementemsdficilesde recordar,almenosqueseestesuficientementefamiliarizadoconUNIX.

intunlink(constchar*pathname);borraunnombredelsistemadearchivos.Sidicho nombreeraelltimoenlaceaunarchivo,yningnprocesotieneelarchivoabierto,el ficheroesborradoyelespacioqueocupabavuelveaestardisponible.Regresa0encasode xito,1encasodeerroryponeunvalorenerrnoparaindicarlo. intlink(constchar*oldpath,constchar*newpath);creaunnuevoenlace(tambin conocidocomoenlacefsicoaunarchivoexistente.

Lasfuncionesstat()yfstat()regresan0encasoxito,1sihuboerroryponelavariable errnoconalgnvalorindicandoeltipodeerror.

18.2.4Creacindearchivostemporales:<stdio.h>
Losprogramasconfrecuencianecesitancreararchivosslodurantelavidadeunprograma.Existen dosfuncionesconvenientes(ademsdealgunasvariantes)paralarealizacindelatarea mencionada.Elmanejo(borradodearchivos,etc.)estomadoconcuidadoporelsistemaoperativo. LafuncinFILE*tmpfile(void);creaunarchivotemporal(enmododelectura/escritura binaria)yabreelcorrespondienteflujo.Elarchivoseborrarautomticamentecuandoelprograma termine. Lafuncinchar*tmpnam(char*s);creaunnombrenicoparaunarchivotemporalusando elprefijodetrayectoraP_tmpdirdefinidoen<stdio.h>.

18.3Ejercicios
1. EscribirunprogramaenCparasimularelcomandolsldeUNIXquemuestretodoslos

archivosdeldirectorioactual,suspermisos,tamao,etc. 2. Escribirunprogramaparamostrarlaslneasdeunarchivoquecontengaunapalabradada comoargumentoalprograma,esdecir,unaversinsencilladelautilidadgrepdeUNIX. 3. Esribirunprogramaparamostrarunalistadearchivosdadoscomoargumentos,parando cada20lneashastaqueunateclaseapresionada(unaversinsimpledelautileramorede UNIX). 4. Escribirunprogramaquelistetodoslosarchivosdeldirectorioactualytodoslosarchivosen lossubsecuentesdirectorios.

Subsecciones

19.1Funcionesb sicasparaeltiempo 19.2Ejemplosdeaplicacionesdefuncionesdeltiempo. 19.2.1Ejemplo1:Tiempo(ensegundos)parahaceralgnclculo. 19.2.2Ejemplo2:Inicializarlasemilladeunnmeroaleatorio. 19.3Ejercicios

19.Funcionesparaeltiempo
EnestecaptuloserevisarcomosepuedeusarelrelojconllamadasalsistemaUNIX. Existenmuchasfuncionesparaeltiempoquelasquesernconsideradasaquusarlaspginasde manyloslistadosdelabibliotecaestndardefuncionesparamsdetalles. Elusomscomndelasfuncionesdetiemposon:

conocereltiempo, tomareltiempoaprogramasyfuncionesy ponervaloresasemillas.

19.1Funcionesbsicasparaeltiempo
Algunasprototiposdelasfuncionesbsicasparaeltiemposonlassiguientes:

time_ttime(time_t*t)devuelveeltiempotranscurrido,medidoensegundosdesde``la poca''0horas,0minutos,0segundos,tiempouniversalcoordinado(GMT)del1^odeenero de1970.Estamedidasellamael``tiempodecalendario''.Sitnoesnulo,elvalordevuelto tambinseguardaenlazonadememoriaalaqueapuntat.Encasodeerror,sedevuelve ((time_t)1)yseasignaalavariableerrnounvalorapropiado. ftime(structtimeb*pt)devuelvelahoraylafechaactualesenpt,queestadeclaradaen <sys/timeb.h>comosigue:


structtimeb { time_ttime;/*Segundosdesdeepoca,igualque `time'.*/ unsignedshortintmillitm;/*millisegundosadicionales. */ shortinttimezone;/*Tiempolocalmedidoenminutos oestedeGMT.*/ shortintdstflag;/*Nocerosiseusahorariodeverano */

};

Encasodexito,sedevuelveeltiempotranscurridoensegundosdesdelapoca.Encasode error,sedevuelve((time_t)1)yseasignaalavariableerrnounvalorapropiado.

char*ctime(time_t*timep)tomaunargumentodetipotime_t(longinteger)que representaeltiempodecalendadrioyloconvierteaunacadenade26caracteresdelaforma producidaporlafuncinasctime().Enprimerlugardescomponelossegundosauna estructuratmllamandoalocaltime(),yentoncesllamaaasctime()paraconvertir laestructuratmaunacadena. char*asctime(conststructtm*timeptr)convierteunvalordetiempocontenidoenuna estructuratmaunacadenade26caracteresdelaforma: dddmmmddhh:mm:ssaaaa Lafuncinasctime()regresaunapuntadoralacadena.

19.2Ejemplosdeaplicacionesdefuncionesdel tiempo.
Comosemencionopreviamente,bsicamenteexistentresposiblesusosdelasfuncionesdetiempo.

19.2.1Ejemplo1:Tiempo(ensegundos)parahaceralg n clculo.
Esteesunejemplosencilloqueilustralasllamadasalafuncintiempoendistintosmomentos:
/*timer.c*/ #include<stdio.h> #include<sys/types.h> #include<time.h> main() { inti,j; time_tt1,t2; (void)time(&t1); for(i=1;i<=300;++i) { printf("%d%d%d\n",i,i*i,i*i*i); for(j=0;j<1000000;j++);/*Unpequeoretardo*/ } (void)time(&t2); printf("\nTiempoparahacer300cuadradosycubos=%dsegundos\n", (int)t2t1); }

19.2.2Ejemplo2:Inicializarlasemilladeunn mero aleatorio.


Sehavistounejemplosimilarpreviamente,enestaocasinseusalafuncinlrand48()para generarunasecuenciadenmeros:
/*random.c*/ #include<stdio.h> #include<sys/types.h> #include<time.h> main() { inti; time_tt1; (void)time(&t1); srand48((long)t1); /*usartimeensegundosparaponerlasemilla*/ printf("5numerosaleatorios(semilla=%d):\n",(int)t1); for(i=0;i<5;++i) printf("%d",lrand48()); printf("\n\n"); }

Lafuncinlrand48()devuelveenteroslargosnonegativosdistribuidosuniformememnteentre0 y .

Unafuncinsimilareslafuncindrand48queregresanmerosdedobleprecisinenelrango . srand48()poneelvalordelasemillaparaestosgeneradoresdenmerosaleatorios.Es importantetenerdiferentessemillascuandosellamealasfuncionesdeotraformaelmismo conjuntonmerospseudoaleatoriosseragenerados.Lafuncintime()siempredaunasemilla nica(siempreycuandohayatranscurridoporlomenos1segundo).

19.3Ejercicios
1. EscribirunprogramaenCquemidaeltiempodeunfragmentodecdigoenmilisegundos. 2. EscribirunprogramaenCparaproducirunaseriedenmerosaleatoriosdepuntoflotante enlosrangosa)0.01.0,b)0.0n,dondenescualquiervalorflotante.Lasemilladeber estarpuestaparaquesegaranticeunasecuencianica.

Subsecciones

20.1EjecutandocomandosdeUNIXdesdeC 20.2 execl() 20.3 fork() 20.4 wait() 20.5 exit() 20.6Ejercicios

20.Controldeprocesos:<stdlib.h>, <unistd.h>
Unprocesoesbsicamenteunnicoprogramaejecutndose.Estepodraserunprogramadel ''sistema(porejemplo,login,csh,update,etc).unprogramainiciadoporelusuario(gimpo algunohechoporelusuario). CuandoUNIXejecutaunprocesoleasignaacadprocesounnmeronicoprocessIDopid. ElcomandopsdeUNIXlistatodoslosprocesosqueseestnejecutandoenlamquina,listando tambinelpid. LafuncindeCintgetpid()regresarelpiddeunprocesoquellameaestafuncin. Unprogramausualmenteejecutaunsloproceso.Sinembargodespuessevercomosepuede hacerqueunprogramacorracomovariosprocesosseparadoscomunicados.

20.1EjecutandocomandosdeUNIXdesdeC
SepuedenejecutarcomandosdesdeunprogramadeCcomosiseestuvieraenlalneadecomandos deUNIXusandolafuncinsystem().NOTA:sepuedeahorrarbastantetiempoyconfusinen vezdeejecutarotrosprogramas,scripts,etc.parahacerlastareas. intsystem(char*mandato)dondemandatopuedeserelnombredeunautilerade UNIX,unshellejecutableounprogramadelusuario.Lafuncinregresaelstatusdesalidadel shell.Lafuncintienesuprototipoen<stdlib.h> Ejemplo:llamadadelcomandolsdesdeunprograma
main() { printf("Archivoseneldirectorioson:\n"); system("lsl"); }

Lafuncinsystemesunallamadaqueestaconstruidadeotras3llamadasdelsistema:execl(), wait()yfork()(lascualestienensuprototipoen<unistd.h>).

20.2execl()
Lafuncinexecltieneotras5funcionesrelacionadasverlaspginasdeman. Lafuncinexeclrealizalaejecucin(execute)ysale(leave),esdecirqueunprocesoser ejecutadoyentoncesterminadoporexecl. Estadefinidacomo:
execl(constchar*camino,constchar*arg0,...,char*argn,0);

Elltimoparmetrodebersersiempre .EsteesunterminadorNulo.Comolalistade argumentosseavariablesedebeindicardealgunaformaaCcuandoseterminelalista.El terminadornulohaceloanterior. Elapuntadorcaminoindicaelnombredeunarchivoquecontieneelcomandoqueserejecutado, arg0apuntaaunacadenaqueeselmismonombre(oalmenossultimocomponente). arg1,...,argnsonapuntadoresalosargumentosparaelcomandoyel solamenteindica elfindelalistadeargumentosvariables. Porlotantonuestroejemploquedadelasiguienteforma:
#include<unistd.h> main() { printf("Losarchivoseneldirectorioson:\n"); execl("/bin/ls","ls","l",0); printf("Estonoseejecuta!!!\n"); }

20.3fork()
Lafuncinintfork()cambiaunprocesonicoen2procesosidnticos,conocidoscomoel padre(parent)yelhijo(child).Encasodexito,fork()regresa alprocesohijoyregresael identificadordelprocesohijoalprocesopadre.Encasodefalla,fork()regresa alproceso padre,poneunvaloraerrno,ynosecreaunprocesohijo. Elprocesohijotendrsupropioidentificadornico(PID). Elsiguienteprogramailustraunejemplosencillodelusodefork,dondedoscopiassonhechasy seejecutanjuntas(multitarea).
main()

{ intvalor_regr=0; printf("Bifurcandoelproceso\n"); valor_regr=fork(); printf("Eliddelprocesoes%dyelvalorregresadoes%d\n", getpid(),valor_regr); execl("/bin/ls","ls","l",0); printf("Estalineanoesimpresa\n"); }

Lasalidapodrasercomolasiguiente:
Bifurcandoelproceso Eliddelprocesoes2662yelvalorregresadoes2663 Eliddelprocesoes2663yelvalorregresadoes0

Losprocesostienenunnicoidentificador,elcualserdiferenteencadaejecucin. EsimposibleindicarconantelacincualprocesoobtendrelCPU.Cuandounprocesoesduplicado en2procesossepuededetectarfcilmente(encadaproceso)sielprocesoeselhijooelpadreya quefork()regresa paraelhijo.Sepuedenatraparcualquiererror,yaquefork()regresaun ,porejemplo:


intpid;/*identificadordelproceso*/ pid=fork(); if(pid<0) { printf("Nosepudoduplicar!!\n"); exit(1); } if(pid==0) { /*Procesohijo*/ ...... } else { /*Procesopadre*/ ...... }

20.4wait()
Lafuncinintwait()(int*status)forzaraunprocesopadreparaqueespereaun procesohijoquesedetengaotermine.LafuncinregresaelPIDdelhijoo encasodeerrror.El estadodelasalidadelhijoesregresadoenstatus.

20.5exit()
Lafuncinvoidexit(intstatus)terminaelprocesoquellamaaestafuncinyregresaen lasalidaelvalordestatus.TantoUNIXylosprogramasbifurcadosdeCpuedenleerelvalorde status. Porconvencin,unestadode significaterminacinnormalycualquierotroindicaunerroroun eventonousual.Muchasllamadasdelabibliotecaestndartienenerroresdefinidosenlacabecera dearchivosys/stat.h.Sepuedefcilmentederivarsupropiaconvencin. Unejemplocompletodeunprogramadebifurcacinsemuestraacontinuacin:
/* fork.cejemplodeunprogramadebifurcacin ElprogramapideelingresodecomandosdeUNIXquesondejadosenuna cadena.Lacadenaesentonces"analizada"encontrandoblancos,etc Cadacomandoysuscorrespondientesargumentossonpuestosen unarreglodeargumentos,execvpesllamadaparaejecutarestoscomandos enunprocesohijogeneradoporfork() */ #include<stdio.h> #include<sys/types.h> #include<unistd.h> main() { charbuf[1024]; char*args[64]; for(;;) { /* *Pideyleeuncomando. */ printf("Comando:"); if(gets(buf)==NULL) { printf("\n"); exit(0); } /* *Dividirlacadenaenargumentos. */ parse(buf,args); /* *Ejecutarelcomando. */ ejecutar(args); } } /* *parsedivideelcomandoqueestaenbuf *enargumentos. */ parse(char*buf,char**args) {

while(*buf!=(char)NULL) { /* *Quitarblancos.Usarnulos,paraque *elargumentoprevioseaterminado *automaticamente. */ while((*buf=='')||(*buf=='\t')) *buf++=(char)NULL; /* *Guardarlosargumentos */ *args++=buf; /* *Brincarsobrelosargumentos. */ while((*buf!=(char)NULL)&&(*buf!='')&&(*buf!='\t')) buf++; } *args=(char)NULL; } /* *ejecutargeneraunprocesohijoyejecuta *elprograma. */ ejecutar(char**args) { intpid,status; /* *Obtenerunprocesohijo. */ if((pid=fork())<0) { perror("fork"); exit(1); /*NOTA:perror()generaunmensajedeerrorbreveenla *salidadeerroresdescribiendoelultimoerrorencontrado *duranteunallamadaalsistemaofunciondelabiblioteca. */ } /* *Elprocesohijoejecutaelcodigodentrodelif. */ if(pid==0) { execvp(*args,args); perror(*args); exit(1); /*NOTA:lasversionesexecv()yexecvp()deexecl()sonutilescuando elnumerodeargumentosesdesconocidopreviamente. Losargumentosparaexecv()yexecvp()sonelnombredelarchivo que seraejecutadoyunvectordecadenasquecontienenlos argumentos. Elultimoargumentodecademadeberaserunapuntadora0(NULL) execlp()yexecvp()sonllamadosconlosmismosargumentosque

execl()yexecv(),peroduplicanlasaccionesdelshellen labusquedadeunarchivoejecutableenunlistadedirectorios. Lalistadedirectoriosesobtenidadelambiente. */ } /* *Elpadreejecutaelwait. */ while(wait(&status)!=pid) /*vacio*/; }

20.6Ejercicios
1. CrearunprogramaenCendondeseuselafuncinpopen()paraentubarlasalidadel comandorwhodeUNIXenelcomandomoredeUNIX.

Subsecciones

21.1ArchivosCabezera 21.2VariablesyFuncionesExternas 21.2.1Alcancedelasvariablesexternas 21.3VentajasdeUsarVariosArchivos 21.4Comodividirunprogramaenvariosarchivos 21.5OrganizacindelosDatosencadaArchivo 21.6LautileraMake 21.6.1ProgramandoMake 21.7Creaci ndeunArchivoMake(Makefile) 21.8UsodemacrosconMake 21.9Ejecucinde Make

21.CompilacindeProgramasconArchivos M ltiples
Enestecaptuloserevisalosaspectosteoricosyprcticosquenecesitanserconsideradoscuando sonescritosprogramasgrandes. Cuandoseescribenprogramasgrandessedeberprogramarenmdulos.Estossernarchivos fuentesseparados.Lafuncinmain()deberestarenunarchivo,porejemploenmain.c,ylos otrosarchivostendrnotrasfunciones. Sepuedecrearunabibliotecapropiadefuncionesescribiendounasuitedesubrutinasenunooms mdulos.Dehecholosmdulospuedensercompartidosentremuchosprogramassimplemente incluyendolosmdulosalcompilarcomoseveracontinuacin. Setienevariasventajassilosprogramassonescritosdeestaforma:

losmdulosdeformanaturalsedividirnengruposcomunesdefunciones. sepuedecompilarcadamdulosseparadamenteyligarloconlosmdulosyacompilados. lasutilerastalescomomakenosayudanamantenersistemasgrandes.

21.1ArchivosCabezera
Siseadoptaelmodelomodularentoncessequerrtenerparacadamdulolasdefinicionesdelas variables,losprototiposdelasfunciones,etc.Sinembargo,qusucedesivariosmdulosnecesitan compartirtalesdefiniciones?Entalcaso,lomejorescentralizarlasdefinicionesenunarchivo,y compartirelarchivoentrelosmdulos.Talarchivoesusualmentellamadounarchivocabecera. Porconvencinestosarchivostienenelsufijo.h Sehanrevisadoyaalgunosarchivoscabeceradelabibliotecaestndar,porejemplo:
#include<stdio.h>

Sepuedendefinirlospropiosarchivoscabeceraysepuedenincluirenelprogramacomosemuestra enseguida:
#include"mi_cabecera.h"

Losarchivoscabeceraporlogeneralslocontienendefinicionesdetiposdedatos,prototiposde funcionesycomandosdelpreprocesadordeC. Considerarelsiguienteprogramadeejemplo: main.c


/* *main.c */ #include"cabecera.h" #include<stdio.h> char*Otra_cadena="HolaaTodos"; main() { printf("Ejecutando...\n"); /* *LlamaraEscribirMiCadena()definidaenotroarchivo */ EscribirMiCadena(MI_CADENA); printf("Terminado.\n"); }

EscribirMiCadena.c
/* *EscribirMiCadena.c */ externchar*Otra_cadena; voidEscribirMiCadena(EstaCadena) char*EstaCadena; { printf("%s\n",EstaCadena);

printf("VariableGlobal=%s\n",Otra_cadena); }

cabecera.h
/* *cabecera.h */ #defineMI_CADENA"HolaMundo" voidEscribirMiCadena();

Cadamdulosercompiladoseparadamentecomosevermsadelante. Algunosmdulostienenladirectivadepreprocesamiento#include"cabecera.h"yaque compartendefinicionescomunes.Algunoscomomain.ctambinincluyenarchivoscabecera estndar.Lafuncinmain.cllamaalafuncinEscribirMiCadena()lacualestaenel mdulo(archivo)EscribirMiCadena.c ElprototipovoiddelafuncinEscribirMiCadenaestadefinidaencabecera.h. Observarqueengeneralsedebedecidirentretenerunmdulo.cquetengaaccesosolamenteala informacinquenecesitaparasutrabajo,conlaconsecuenciademantenermuchosarchivos cabeceraytenerprogramasdetamaomoderadoconunoodosarchivoscabecera(probablemente lomejor)quecompartanmsdefinicionesdemdulos. Unproblemaquesetienealemplearmdulossonelcompartirvariables.Sisetienenvariables globalesdeclaradasysoninstanciadasenunmdulo,cmopuedenserpasadasaotrosmdulos paraqueseanconocidas? Sepodranpasarlosvalorescomoparmetrosalasfunciones,pero:

puedeserestolaboriososisepasanlosmismosparmetrosamuchasfuncionesosilalista deargumentosesmuylarga. arreglosyestructurasmuygrandessondifcilesdeguardarlocalmenteproblemasde memoriaconelstack.

21.2VariablesyFuncionesExternas
Lasvariablesyargumentosdefinidosdentrodelasfuncionesson``internas'',esdecir,locales. Lasvariables``externas''estndefinidasfueradelasfuncionesseencuentranpotencialmente disponiblesatodoelprograma(globales)peroNOnecesariamente.Lasvariablesexternasson siemprepermanentes. EnellenguajeC,todaslasdefinicionesdefuncionessonexternas,NOsepuedentener declaracionesdefuncionesanidadascomoenPASCAL.

21.2.1Alcancedelasvariablesexternas
Unavariableexterna(ofuncin)noessiempretotalmenteglobal.EnellenguajeCseaplicala siguienteregla: Elalcancedeunavariableexterna(ofuncin)iniciaenelpuntodedeclaracinhastaelfindel archivo(mdulo)dondefuedeclarada. Considerarelsiguientecdigo:
main() {...} intque_alcance; floatfin_de_alcance[10]; voidque_global() {...} charsolitaria; floatfn() {...}

Lafuncinmain()nopuedeveralasvariablesque_alcanceofin_de_alcance,perolas funcionesque_global()yfn()sipueden.Solamentelafuncinfn()puedevera solitaria. Estaestambinunadelasrazonesporlasquesedebenponerlosprototiposdelasfuncionesantes delcuerpodelcdigo. Porloqueenelejemplolafuncinmainnoconocernadaacercadelasfunciones que_global()yfn().Lafuncinque_global()nosabenadaacercadelafuncinfn(), perofn()sisabeacercadelafuncinque_global(),yaqueestaaparecedeclarada previamente. Laotraraznporlacualseusanlosprototiposdelasfuncionesespararevisarlosparmetrosque sernpasadosalasfunciones. Siserequierehacerreferenciaaunavariableexternaantesdequeseadeclaradaoqueestadefinida enotromdulo,lavariabledebeserdeclaradacomounavariableexterna,porejemplo:
externintque_global;

Regresandoalejemplodeprogramacinmodular,setieneunaarreglodecaracterestipoglobal Otra_cadenadeclaradoenmain.cyqueestacompartidoconEscribirMiCadenadondeesta declaradacomoexterna. Sedebetenercuidadoconelespecificadordealmacenamientodeclaseyaqueelprefijoesuna declaracin,NOunadefinicin,estoes,nosedaalmacenamientoenlamemoriaparaunavariable externasolamenteledicealcompiladorlapropiedaddelavariable.Lavariableactualslodeber estardefinidaunavezentodoelprogramasepuedentenertantasdeclaracionesexternascomose requieran.

Lostamaosdelosarreglosdebernserdadosdentrodeladeclaracin,peronosonnecesariosen lasdeclaracionesexternas,porejemplo:
main.cintarr[100]; arch.cexternintarr[];

21.3VentajasdeUsarVariosArchivos
Lasventajasprincipalesdedispersarunprogramaenvariosarchivosson:

Equiposdeprogramadorespuedentrabajarenelprograma,cadaprogramadortrabajaenun archivodiferente. Puedeserusadounestiloorientadoaobjetos.Cadaarchivodefineuntipoparticularde objetocomountipodedatoylasoperacioneseneseobjetocomofunciones.La implementacindelobjetopuedemantenerseprivadoalrestodelprograma.Conloanterior selogranprogramasbienestructuradosloscualessonfcilesdemantener. Losarchivospuedencontenertodaslasfuncionesdeungruporelacionado,porejemplo todaslasoperacionesconmatrices.Estaspuedenseraccesadascomounafuncindeuna biblioteca. Objetosbienimplementadosodefinicionesdefuncionespuedenserreusadasenotros programas,conloquesereduceeltiempodedesarrollo. Enprogramasmuygrandescadafuncinprincipalpuedeocuparunpropioarchivo. Cualquierotrafuncindebajonivelusadaenlaimplemantacinpuedeserguardadaenel mismoarchivo,porloquelosprogramadoresquellamenalafuncinprincipalnose distraernporeltrabajodebajonivel. Cuandoloscambiossonhechosaunarchivo,solamenteesearchivonecesitaser recompiladoparareconstruirelprograma.LautileramakedeUNIXesmuytilpara reconstruirprogramasconvariosarchivos.

21.4Comodividirunprogramaenvarios archivos
Cuandounprogramaesseparadoenvariosarchivos,cadaarchivocontendrunaomsfunciones. Unarchivoincluirlafuncinmain()mientraslosotroscontendrnfuncionesquesernllamados porotros.Estosotrosarchivospuedensertratadoscomofuncionesdeunabiblioteca. Losprogramadoresusualmenteiniciandiseandounprogramadividiendoelproblemaensecciones msfcilmentemanejables.Cadaunadeestasseccionespodrnserimplementaddascomounao msfunciones.Todaslasfuncionesdecadaseccinporlogeneralestarnenunsloarchivo. Cuandosehaceunaimplementacintipoobjetodelasestructurasdedatos,esusualtenertodaslas funcionesqueaccesanseobjetoenelmismoarchivo.Lasventajasdeloanteriorson:

Elobjetopuedeserfcilmentereusadoenotrosprogramas.

Todaslasfuncionesrelacionadasestanguardadasjuntas. Losltimoscambiosalobjetorequierensolamentelamodificacindeunarchivo.

Elarchivocontieneladefinicindeunobjeto,ofuncionesqueregresasanvalores,hayuna restriccinenlallamadadeestasfuncionesdesdeotroarchivo,almenosqueladefinicindelas funcionesestnenelarchivo,noserposiblecompilarcorrectamente. LamejorsolucinaesteproblemaesescribirunarchivocabeceraparacadaarchivodeC,estos tendrnelmismonombrequeelarchivodeC,peroterminarnen.h.Elarchivocabeceracontiene lasdefinicionesdetodaslasfuncionesusadasenelarchivodeC. CuandounafuncinenotroarchivollameunafuncindenuestroarchivodeC,sepuededefinirla funcinusandoladirectiva#includeconelarchivoapropiado.h

21.5OrganizacindelosDatosencada Archivo
Cualquierarchivodebertenersusdatosorganizadosenunciertoorden,tipcamentepodrserla siguiente:

Unprembuloconsistentedelasdefinicionesdeconstantes(#define),cabecerasde archivos(#include)ylostiposdedatosimportantes(typedef). Declaracindevariablesglobalesyexternas.Lasvariablesglobalespodranestar inicializadasaqu. Unaomsfunciones.

Elordenanterioresimportanteyaquecadaobjetodeberestardefinidoantesdequepuedaser usado.Lasfuncionesqueregresanvaloresdebernestardefinidosantesdequeseanllamados.Esta definicinpodraserunadelassiguientes:


Ellugarenquelafuncinestadefinidayllamadaenelmismoarchivo,unadeclaracin completadelafuncinpuedesercolocadadelantedecualquierllamadadelafuncin. Silafuncinesllamadadesdeunarchivodondenoestadefinida,unprototipodeber aparecerantesquellamadadelafuncin.

Unafuncindefinidacomo:
floatenc_max(floata,floatb,floatc) {...}

podrtenerelsiguienteprototipo:
floatenc_max(floata,floatb,floatc);

Elprototipopuedeaparecerentrelasvariablesglobaleseneliniciodelarchivofuente. Alternativamentepuedeserdeclaradoenelarchivocabeceraelcualesledousandoladirectiva #include.

EsimportanterecordarquetodoslosobjetosenCdebernestardeclaradosantesdeserusados.

21.6LautileraMake
LautileraMakeesunmanejadorinteligentedeprogramasquemantienelaintegridaddeuna coleccindemdulosdeunprograma,unacoleccindeprogramasounsistemacompletono tienenqueserprogramas,enlaprcticapuedesercualquiersistemadearchivos(porejemplo, captulosdetextodeunlibroqueestasiendotipografiado).Suusoprincipalhasidoenlaasistencia deldesarrollodesistemasdesoftware. EstautilerafueinicialmentedesarrolladaparaUNIX,peroactualmenteestadisponibleenmuchos sistemas. Observarquemakeesunaherramientadelprogramador,ynoespartedellenguajeCodealguno otro. Supongamoselsiguienteproblemademantenimientodeunacoleccingrandedearchivosfuente:
main.cf1.c......fn.c

Normalmentesecompilarnlosarchivosdelasiguientemanera:
gccomainmain.cf1.c.......fn.c

Sinembargosisesabequealgunosarchivoshansidocompiladospreviamenteysusarchivosfuente nohansidocambiadosdesdeentonces,entoncessepuedeahorrartiempodecompilacinligando loscdigosobjetosdeestosarchivos,esdecir:


gccomainmain.cf1.c...fi.o...fj.o...fn.c

SepuedeusarlaopcincdelcompiladordeCparacrearuncdigoobjeto(.o)paraunmdulo dado.Porejemplo:
gcccmain.c

quecrearunarchivomain.o.Noserequiereproporcionarningunaligadealgunabibliotecaya queserresueltaenlaetapadeligamiento. Setieneelproblemaenlacompilacindelprogramadesermuylarga,sinembargo:

Seconsumetiempoalcompilarunmdulo.csielmdulohasidocompiladoantesyno hasidomodificadoelarchivofuente,porlotantonohaynecesidadderecompilarlo.Se puedesolamenteligarlosarchivosobjeto.Sinembargo,noserfcilrecordarcuales archivoshansidoactualizados,porloquesiligamosunarchivoobjetonoactualizado,el programaejecutablefinalestarincorrecto.

Cuandosetecleaunasecuencialargadecompilacinenlalneadecomandossecometen erroresdetecleo,obien,setecleaenformaincompleta.Existirnvariosdenuestrosarchivos quesernligadosaligualquearchivosdebibliotecasdelsistema.Puedeserdifcilrecordar lasecuenciacorrecta.

Siseusalautileramaketodoestecontroleshechoconcuidado.Engeneralslolosmdulosque seanmsviejosquelosarchivosfuentesernrecompilados.

21.6.1ProgramandoMake
Laprogramacindemakeesdirecta,basicamenteseescribeunasecuenciadecomandosque describecomonuestroprograma(osistemadeprogramas)serconstrudoapartirdelosarchivos fuentes. Lasecuenciadeconstrucinesdescritaenlosarchivosmakefile,loscualescontienenreglasde dependenciayreglasdeconstruccin. Unaregladedependenciatienedospartesunladoizquierdoyunladoderechoseparadospor:
ladoizquierdo:ladoderecho

Elladoizquierdodaelnombredeldestino(losnombresdelprogramaoarchivosdelsistema)que serconstrudo(target),mientraselladoderechodalosnombresdelosarchivosdeloscuales dependeeldestino(porejemplo,archivosfuente,archivoscabecera,archivosdedatos). Sieldestinoestafueradefechaconrespectoalaspartesqueleconstituyen,lasreglasde construccinsiguiendolasreglasdedependenciasonusadas. PorlotantoparaunprogramatpicodeCcuandounarchivomakeesejecutadolassiguientes tareassonhechas: 1. Elarchivomakeesledo.ElMakefileindicacualesobjetosyarchivosdebibliotecase requierenparaserligadosycualesarchivoscabecerayfuentenecesitansercompiladospara crearcadaarchivoobjeto. 2. Lahoraylafechadecadaarchivoobjetosonrevisadoscontraelcdigofuenteylosarchivos cabeceradeloscualesdependen.Sicualquierfuenteoarchivocabecerasonmsrecientes queelarchivoobjeto,entonceslosarchivoshansidomodificadosdesdelaltima modificacinyporlotantolosarchivosobjetonecesitanserrecompilados. 3. Unavezquetodoslosarchivosobjetoshansidorevisados,eltiempoylafechadetodoslos archivosobjetosonrevisadoscontralosarchivosejecutables.Siexistearchivosejecutables viejossernrecompilados. Observarquelosarchivosmakepuedenobedecercualquiercomandoqueseatecleadoenlalnea decomandos,porconsiguientesepuedenusarlosarchivosmakeparanosolamentecompilar archivos,sinotambinparahacerrespaldos,ejecutarprogramassilosarchivosdedatoshansido cambiadosolimpiezadedirectorios.

21.7CreacindeunArchivoMake(Makefile)
Lacreacindelarchivoesbastantesimple,secreaunarchivodetextousandoalgneditordetextos. ElarchivoMakefilecontienesolamenteunalistadedependenciasdearchivosycomandosqueson necesariosparasatisfacerlos. Semuestraacontinuacinunejemplodeunarchivomake:
prog:prog.of1.of2.o gccoprogprog.of1.of2.olm... prog.o:cabecera.hprog.c gcccprog.c f1.o:cabecera.hf1.c gcccf1.c f2.o:.... ...

Lautileramakelointerpretardelasiguienteforma: 1. progdependedetresarchivos:prog.o,f1.oyf2.o.Sicualquieradelosarchivos objetohacambiadodesdelaltimacompilacinlosarchivosdebenserreligados. 2. prog.odependede2archivos,siestoshancambiadoprog.odeberserrecompilado.Lo mismosucedeconf1.oyf2.o. Losltimos3comandosenmakefilesonllamadosreglasexplcitasyaquelosarchivosenlos comandossonlistadospornombre. Sepuedenusarreglasimplcitasenmakefileparageneralizarreglasyhacermscompactala escritura. Sisetiene:
f1.o:f1.c gcccf1.c f2.o:f2.c gcccf2.c

sepuedegeneralizara:
.c.o:gccc$<

Locualseleecomo.ext_fuente.ext_destino:comandodonde$<esunaformabreve paraindicarlosarchivosquetienenlaextensin.c SepuedeninsertarcomentariosenunMakefileusandoelsmbolo#,endondetodoslos caracteresquesiguena#sonignorados.

21.8UsodemacrosconMake
Sepuedendefinirmacrosparaqueseanusadaspormake,lascualessontipcamenteusadaspara guardarnombresdearchivosfuente,nombresdearchivosobjeto,opcionesdelcompiladoroligasde bibliotecas. Sedefinenenunaformasimple,porejemplo:
FUENTES=main.cf1.cf2.c CFLAGS=ggdbC LIBS=lm PROGRAMA=main OBJETOS=(FUENTES:.c=.o)

endonde(FUENTES:.c=.o)cambialaextensin.cdelosfuentesporlaextensin.o Parareferirseousarunamacroconmakesedebehacer$(nomb_macro),porejemplo:
$(PROGRAMA):$(OBJETOS) $(LINK.C)o$@$(OBJETOS)$(LIBS)

Enelejemplomostradoseobservaque:

Lalneaquecontiene$(PROGRAMA):$(OBJETOS)generaunalistadedependencias yeldestino. Seempleanmacrosinternascomo$@.

Existenvariasmacrosinternasacontinuacinsemuestranalgunasdeellas: $* $@ $ Partedelnombredelarchivodeladependenciaactualsinelsufijo. Nombrecompletodeldestinoactual. Archivo.cdeldestino

Unejemplodeunmakefileparaelprogramamodulardiscutidopreviamentesemuestraa continuacin:
# #Makefile # FUENTES.c=main.cEscribirMiCadena.c INCLUDES= CFLAGS= SLIBS= PROGRAMA=main OBJETOS=$(FUENTES.c:.c=.o) #Destino(target)especial(iniciacon.) .KEEP_STATE: debug:=CFLAGS=ggdb

alldebug:$(PROGRAMA) $(PROGRAMA):$(INCLUDES)$(OBJETOS) $(LINK.c)o$@$(OBJETOS)$(SLIBS) clean: rmf$(PROGRAMA)$(OBJETOS)

ParavermsinformacindeestautileradentrodeLinuxusarinfomake

21.9EjecucindeMake
Parausarmakesolamentesedeberteclearenlalneadecomandos.Elsistemaoperativo automticamentebuscaunarchivoconelnombreMakefile(observarquelaprimeraletraes maysculayelrestominsculas),porlotantosisetieneunarchivoconelnombreMakefileyse tecleamakeenlalneadecomandos,elarchivoMakefiledeldirectorioactualserejecutado. Sepuedeanularestabsquedadeestearchivotecleandomakefmakefile. Existenalgunasotrasopcionesparamakelascualespuedenserconsultadasusandoman.

Subsecciones

22.1EntubandoenunprogramadeC <stdio.h> 22.1.1 popen() Tuber aformateada 22.1.2 pipe() Tuber adebajonivel

22.Comunicacinentreprocesos(IPC InterprocessCommunication),PIPES
Acontinuacinseiniciarlarevisindecomomltiplesprocesospuedenestarsiendoejecutadosen unamquinayquizssiendocontrolados(generadosporlafuncinfork())porunodenuestros programas. Ennumerosasaplicacioneshayunanecesidadclaraparaqueestosprocesossecomuniquenparael intercambiodedatosoinformacindecontrol.Hayunoscuantosmtodosparahacerloanterior.Se puedenconsiderarlossiguientes:

Tubera(Pipes) Seales(Signals) ColasdeMensajes Semforos MemoriaCompartida Sockets

Enestecaptuloseestudiaelentubamientodedosprocesos,enlossiguientescaptulosserevisan losotrosmtodos.

22.1EntubandoenunprogramadeC <stdio.h>
Elentubamientoesunprocesodondelaentradadeunprocesoeshechaconlasalidadeotro.Seha vistoejemplosdeloanteriorenlalneadecomandosdeUnixcuandoseusaelsmbolo|. SevercomohacerloanteriorenunprogramadeCteniendodos(oms)procesosdivididos.Lo primeroquesedebehaceresabrirunatubera,enUnixpermitedosformasdehacerlo:

22.1.1popen()Tuberaformateada
FILE*popen(char*orden,char*tipo)AbreunatuberadeE/Sdondeelcomandoes

elprocesoqueserconectadoalprocesoqueloestallamandodeestaformacreandoelpipe.Eltipo es"r"paralectura,o"w"paraescritura. Lafuncinpopen()regresaunapuntadoraunflujooNULLparaalgntipodeerror. Unatuberaabiertaconpopen()debersiemprecerrarseconpclose(FILE*flujo). Seusafprintf()yfscanf()paracomunicarseconelflujodelatubera.

22.1.2pipe()Tuberadebajonivel
intpipe(intdescf[2])Creaunpardedescritoresdearchivo,queapuntanaunnodoide unatubera,ylosponeenelvectordedoselementosapuntadopordescf.descf[0]espara lecturaydescf[1]esparaescritura. pipe()regresa0encasodexito,yencasodeerrorsedevuelve1yseponeunvalorapropiado enerrno. Elmodelodeprogramacinestndaresqueunavezquelatuberahasidopuesta,dos(oms) procesoscooperativosserncreadospordivisinylosdatossernpasadosempleandoread()y write(). Lastuberasabiertasconpipe()debernsercerradasconclose(intfd).Acontinuacinse muestraunejemplodeentubamientoqueseutilizaparaestarenviandodatosalprograma gnuplot,empleadoparagraficar.Ladescripcindelasfuncionesdelosmduloseslasiguiente:

Elprogramatienedosmdulos,grafica.cquecontienelafuncinmain()y graficador.cquecontienelasrutinasparaenviarlosdatosalprogramagnuplot. Elprogramasuponequesetieneinstaladoelprogramadegraficacingnuplotenel directorio/usr/bin. Elprogramagrafica.cllamaalprogramagnuplot. Dosflujossongeneradosusandoelprogramagrafica.c,enunodeellossegrficala funciny=0.5ey=aleat(01.0)yenelotrolasfuncionesy=sen(x)e y=sen(1/x). Dostuberassoncreadascadaunaconunflujodedatos. Gnuplotgeneraen``vivo''lasalidadelasgrficas.

Ellistadodelcdigoparagrafica.ceselsiguiente:
/*grafica.c *Ejemplodelatuberias(pipe)deUnix.Sellamaalpaquete"gnuplot" *paragraficardesdeunprogramaenC. *Lainformacionesentubadaagnuplot,secrean2tuberias,unadibujarala *graficadey=0.5ey=random01.0,laotragraficaray=sen(1/x)ey=senx */ #include"externals.h" #include<signal.h> #defineDEG_TO_RAD(x)(x*180/M_PI) voidsalir();

FILE*fp1,*fp2,*fp3,*fp4; main() { floati; floaty1,y2,y3,y4; /*abrirarchivosenloscualesseguardaranlosdatosagraficar*/ if(((fp1=fopen("plot11.dat","w"))==NULL)|| ((fp2=fopen("plot12.dat","w"))==NULL)|| ((fp3=fopen("plot21.dat","w"))==NULL)|| ((fp4=fopen("plot22.dat","w"))==NULL)) {printf("Errornosepuedeabrirunoovariosarchivosde datos\n"); exit(1); } signal(SIGINT,salir);/*Atraparlallamadadelafunciondesalidactrlc */ IniciarGraf(); y1=0.5; srand48(1);/*ponersemilla*/ for(i=0;;i+=0.01)/*incrementarisiempre*/ {/*usarctrlcparasalirdelprograma*/ y2=(float)drand48(); if(i==0.0) y3=0.0; else y3=sin(DEG_TO_RAD(1.0/i)); y4=sin(DEG_TO_RAD(i)); /*cargararchivos*/ fprintf(fp1,"%f%f\n",i,y1); fprintf(fp2,"%f%f\n",i,y2); fprintf(fp3,"%f%f\n",i,y3); fprintf(fp4,"%f%f\n",i,y4); /*asegurarsequelosbufferssoncopiadosaldisco*/ /*paraquegnuplotpuedaleerlosdatos*/ fflush(fp1); fflush(fp2); fflush(fp3); fflush(fp4); /*graficaralotgraph*/ Graf1Vez(); usleep(10000);/*dormirporuncortotiempo(250microsegundos)*/ } } voidsalir() { printf("\nctrlcatrapada:\nTerminandolastuberias\n"); PararGrafica(); printf("Cerrandolosarchivosdedatos\n"); fclose(fp1); fclose(fp2); fclose(fp3); fclose(fp4); printf("Borrandolosarchivosdedatos\n"); BorrarDat(); }

Elmdulograficador.ceselsiguiente:
/**********************************************************************/ /*modulo:graficador.c*/ /*Contienerutinasparagraficarunarchivodedatosproducidopor*/ /*programa.Enestecasosegraficaendosdimensiones*/ /**********************************************************************/ #include"externals.h" staticFILE*plot1, *plot2, *ashell; staticchar*iniciargraf1="plot[][0:1.1]'plot11.dat'withlines, 'plot12.dat'withlines\n"; staticchar*iniciargraf2="plot'plot21.dat'withlines,'plot22.dat'with lines\n"; staticchar*comando1="/usr/bin/gnuplot>dump1"; staticchar*comando2="/usr/bin/gnuplot>dump2"; staticchar*borrarchivos="rmplot11.datplot12.datplot21.datplot22.dat"; staticchar*set_term="setterminalx11\n"; voidIniciarGraf(void) { plot1=popen(comando1,"w"); fprintf(plot1,"%s",set_term); fflush(plot1); if(plot1==NULL) exit(2); plot2=popen(comando2,"w"); fprintf(plot2,"%s",set_term); fflush(plot2); if(plot2==NULL) exit(2); } voidBorrarDat(void) { ashell=popen(borrarchivos,"w"); exit(0); } voidPararGrafica(void) { pclose(plot1); pclose(plot2); } voidGraf1Vez(void) { fprintf(plot1,"%s",iniciargraf1); fflush(plot1); fprintf(plot2,"%s",iniciargraf2); fflush(plot2); }

Elarchivodecabeceraexternals.hcontienelosiguiente:
/*externals.h*/ #ifndefEXTERNALS #defineEXTERNALS

#include<stdio.h> #include<stdlib.h> #include<math.h> /*prototipos*/

Conlafinalidaddetenerunmejorcontrolenlacompilacindelprogramaseluedeusarelsiguiente archivoMakefile:
FUENTES.c=grafica.cgraficador.c INCLUDES= CFLAGS= SLIBS=lm PROGRAMA=grafica OBJETOS=$(FUENTES.c:.c=.o) $(PROGRAMA):$(INCLUDES)$(OBJETOS) gcco$(PROGRAMA)$(OBJETOS)$(SLIBS) grafica.o:externals.hgrafica.c gcccgrafica.c graficador.o:externals.hgraficador.c gcccgraficador.c clean: rmf$(PROGRAMA)$(OBJETOS)

Subsecciones

23.1Creaci nynombradodesockets 23.2Conectandosocketsdeflujo 23.2.1Transferenciadedatosenunflujoycerrado

23.Sockets
Lossocketsproporcionanunacomunicacindedosvas,puntoapuntoentredosprocesos.Los socketssonmuyverstilesysonuncomponentebsicodecomunicacinentreinterprocesose intersistemas.Unsocketesunpuntofinaldecomunicacinalcualsepuedeasociarunnombre.Este tieneuntipoyunoomsprocesosasociados. Lossocketsexistenenlosdominiosdecomunicacin.Unsocketdedominioesunarepresentacin quedaunaestructuradedireccionamientoyunconjuntodeprotocolos.Lossocketsseconectan solamenteconsocketsenelmismodominio.Veintitrsdominiosdesocketssonidentificados(ver <sys/socket.h>),deloscualessolamentelosdominiosdeUNIXeInternetsonnormalmente socketsdeLinuxusadosparacomunicarseentreprocesosenunslosistema,comootrasformasde comunicacinentreprocesos. EldominiodeUNIXdaunespaciodedireccionesdesocketenunsistema.Lossocketsdedominio deUNIXsonnombradosconlasrutasdeUNIX.Lossocketspuedentambinserusadospara comunicarprocesosentrediferentessistemas.Elespaciodedireccionesdelsocketentrelossistemas conectadosesllamadoeldominiodeInternet. LacomunicacindeldominiodeInternetusalasuitedelprotocolodeInternetTCP/IP. Lostiposdesocketdefinenlaspropiedadesdecomunicacinvisiblesparalaaplicacin.Los procesossecomunicansolamenteentrelossocketsdelmismotipo.Existencincotiposdesockets. Socketdeflujo daunflujodedatosdedosvas,confiable,ysinduplicadossinlmitesdegrabacin.Elflujo operaenformaparecidaaunaconversacintelefnica.EltipodelsocketesSOCK_STREAM, elcualeneldominiodeInternetusaTCP(TransmissionControlProtocol). Socketdedatagrama soportaunflujodemensajesdedosvas.Enunsocketdedatagramapodrarecibirmensajes endiferenteordendelasecuenciadelacuallosmensajesfueronenvados.Loslmitesde grabacinenlosdatossonpreservados.Lossocketsdedatagramaoperanparecidosapasar cartashaciaadelanteyhaciaatrsenelcorreo.EltipodesocketesSOCK_DGRAM,elcual eneldominiodeinternetusaUDP(UserDatagramProtocol). Socketdepaquetesecuencial daunaconexindedosvas,secuencialyconfiableparadatagramasdeunalongitudfija

mxima.EltipodesocketesSOCK_SEQPACKET.Nohayprotocoloimplementadoparaeste tipodecualquierfamiliadeprotocolos. rawsocket daaccesoalosprotocolosdecomunicacinsubyacente. Lossocketssonusualmentedatagramasorientados,perosuscaractersticasexactasdependendela interfazdadaporelprotocolo.

23.1Creacinynombradodesockets
Sellamaalafuncinintsocket(intdominio,inttipo,intprotocolo);para crearunextremodeunacomunicacin(socket)eneldominioespecificadoydeltipoindicado.Si unprotocolonoesespecificado.elsistemausaunopredefinidoquesoporteeltipodesocket especificado.Elmanejadordelsocket(undescriptor)esdevuelto.Unprocesoremotonotiene formadeidentificarunsockethastaqueunadireccinseligadaaeste.Losprocesosde comunicacinseconectanatravsdedirecciones.EneldominiodeUNIX,unaconexinesta compuestausualmentedeunoodosnombresderutas.EneldominiodeInternet,unaconexinesta compuestadedireccioneslocalesyremotasyparteslocalesyremotas.Enmuchosdominios,las conexionesdebensernicas. Sellamaalafuncinintbind(intsockfd,structsockaddr*nomb, socklen_tlongdir)paraenlazaruncaminoounadireccindeInterneaunconector (socket).Haytresformasdiferentesdellamarabind(),dependiendodeldominiodelsocket.

ParalossocketsdeldominiodeUNIXconrutasconteniendo14,omenoscaracteresse puedeusar:
#include<sys/socket.h> ... bind(sd,(structsockaddr*)&direccion,longitud);

SilatrayectoriadeunsocketdeldominiodeUNIXrequieresmscaracteres,usar:
#include<sys/un.h> ... bind(sd,(structsockaddr_un*)&direccion,longitud);

ParasocketsdeldominiodeInternetusar:
#include<net/netinet.h> ... bind(sd,(structsockaddr_in*)&direccion,longitud);

EneldominiodeUNIX,elenlazadodenombrescreaunsocketconnombreenelsistemade archivos.Usarunlink()orrm()paraeliminarelsocket.

23.2Conectandosocketsdeflujo
Laconexindesocketsesusualmenteasimtrica.Unprocesousualmenteactacomounservidory elotroprocesoeselcliente.Elservidorenlazasusocketauncaminoodireccinpreviamente acordada,yentoncesbloqueaelsocket.ParaunconetorSOCK_STREAM,elservidorllamaala funcinintlisten(ints,intbacklog),paraindicarcuantaspeticionesdeconexin sernpuestasenlacola.Unclienteinicialaconexinalsocketdelservidormedianteunallamadaa lafuncinintconnect(insts,structsockaddr*nomb_serv,int longdirec).UnallamadaeneldominiodeUNIXescomolasiguiente:
structsockaddr_unserver; ... connect(sd,(strucsockaddr_un*)&server,long);

mientraseneldominiodeInternetlallamadapodraser:
structsockaddr_inserver; ... connect(sd,(strucsockaddr_un*)&server,long);

Sielsocketdelclientenoestaenlazadoalmomentodehacerlallamadaparalaconexin,elsistema automticamenteseleccionayligaunnombrealsocket.ParaunsocketSOCK_STREAM,el servidorllamaalafuncinaccept()paracompletarlaconexin. Lafuncinintaccept(ints,structsockaddr*addr,int*longdirec) regresaunconectornuevoelcualesvlidosolamenteparalaconexinparticular.Unservidor puedetenermltiplesconexionesSOCK_STREAMactivasalmismotiempo.

23.2.1Transferenciadedatosenunflujoycerrado
SeempleanvariasfuncionesparaenviaryrecibirdatosdeunsocketSOCK_STREAM.Estasson write(),read(),intsend(ints,constvoid*msg,size_tlon,int flags),yintrecv(ints,void*buf,size_tlon,intflags).Las funcionessend()yrecv()sonparecidasaread()ywrite(),perotienenalgunasbanderas operacionalesadicionales. ElargumentoflagsdeunallamadaarecvseformaaplicandoeloperadordebitsOlgicoaunoo msdelosvaloressiguientes: MSG_OOB Pidelarecepcindedatosfueradebandaquenoserecibiranenelflujodedatosnormal. Algunosprotocolosponendatosdespachadosconprontitudenlacabezadelacoladedatos normales,yas,estaopcinnopuedeemplearsecontalesprotocolos. MSG_PEEK Hacequelaoperacinderecepcindevuelvadatosdelprincipiodelacoladerecepcinsin quitarlosdeall.As,unaprximallamadaderecepcindevolverlosmismosdatos. MSG_WAITALL

Estaopcinhacequelaoperacinsebloqueehastaquesesatisfagalapeticin completamente.Sinembargo,lallamadapuedeaundevolvermenosdatosdelospedidossise capturaunaseal,siocurreunerrorounadesconexin,osilosprximosdatosquesevana recibirsondeuntipodiferentedelquesehadevuelto. MSG_NOSIGNAL EstaopcindesactivaelqueseproduzcaunasealSIGPIPEsobrelosconectoresorientadosa conexincuandoelotroextremodesaparece. MSG_ERRQUEUE Estaopcinindicaqueloserroresencoladosdebenrecibirsedesdelacoladeerroresde conectores.Elerrorsepasaenunmensajeauxiliarconuntipodependientedelprotocolo (paraIPv4steesIP_RECVERR).Elusuariodebeproporcionaunbufferdetamaosuficiente. Veacmsg(3)paraobtenermsinformacinsobremensajesauxiliares.

Sobreestedocumento...
ManualdeC ThisdocumentwasgeneratedusingtheLaTeX 2 HTML translatorVersion200221(1.70) Copyright1993,1994,1995,1996,NikosDrakos,ComputerBasedLearningUnit,Universityof Leeds. Copyright1997,1998,1999,RossMoore,MathematicsDepartment,MacquarieUniversity, Sydney. Thecommandlineargumentswere: latex2htmlmanual ThetranslationwasinitiatedbyHctorTejedaVon20050812

También podría gustarte