Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Manual de C
Manual de C
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...
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,
1.2ElmodelodecompilacindeC
Enlafigura1.1semuestranlasdistintastapasquecubreelcompiladorparaobtenerelcdigo ejecutable.
Figura1.1:ModelodecompilacindeC.
1.3Elpreprocesador
Estapartedelprocesodecompilacinsercubiertaconmsdetalleenelcaptulo12referenteal preprocesador.Sinembargo,sedaalgunainformacinbsicaparaalgunosprogramasdeC. Elpreprocesadoraceptaelcdigofuentecomoentradayesresponsablede:
quitarloscomentarios interpretarlasdirectivasdelpreprocesadorlascualesiniciancon#.
Porejemplo:
#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);
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
Losltimosdospasospudieronsercombinadosenunoslo,entonceshubieramospodidoteclear:
$arrslibmm.acubo.ofactorial.o
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
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)
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.
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?
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:
Estooriginqueenelveranode1983seestablecierauncomitpararesolverestasdiscrepancias,el cualempezatrabajarenunestndarANSIC,lacualfuecompletadaen1988.
2.2CaractersticasdeC
Algunasdelascaractersticasmsimportantesquedefinenellenguajeyquehanpermitidoquesea tanpopular,comolenguajedeprogramacinson:
Lasdiversasrazonesporlacualsehaconvertidoenunlenguajedeusoprofesionalson:
Unpuntoencontraesquetieneunadeteccinpobredeerrores,locualenocasioneses problemticoparalosprincipiantes.
2.3EstructuradeunprogramaenC
UnprogramadeCtienebsicamentelasiguienteforma:
Paraunprogramasedebetenerunafuncinmain(). Unafuncintienelaforma:
tiponombre_de_la_funcion(parmetros) { variableslocales sentenciasdeC
NOTAS:
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
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;
2.4.2Lecturayescrituradevariables
EllenguajeCusasalidaformateada.Lafuncinprintftieneuncaracterespecialparaformatear (%)uncaracterenseguidadefineunciertotipodeformatoparaunavariable.
Observarqueseantepone&alosnombresdelasvaribles,exceptoalacadenadecaracteres.Enel captulo8quetratasobreapuntadoresserevisarmsafondoelusodeesteoperador.
2.5Constantes
ANSICpermitedeclararconstantes.Cuandosedeclaraunaconstanteesunpocoparecidoa declararunavariable,exceptoqueelvalornopuedesercambiado. Lapalabraclaveconstseusaparadeclararunaconstante,comosemuestraacontinuacin:
consta=1; inta=2;
Notas:
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.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;
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:
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)
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
4.3Lasentenciadowhile
Alcontrariodelosciclosforywhilequecompruebanlacondicinenloaltodelbucle,elbucle do...whilelaexaminaenlapartebajadelmismo.Estacaractersticaprovocaqueunciclo do...whilesiempreseejecutealmenosunavez.Laformageneraldelcicloes: do{ sentencia;
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; } }
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;
Subsecciones
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];
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"); } }
5.2Cadenas
Adiferenciadeotroslenguajesdeprogramacinqueempleanuntipodenominadocadenastring paramanipularunconjuntodesimbolos,enC,sedebesimularmedianteunarreglodecaracteres,
Elcdigoanterioresequivalentea:
charcadena[5]={'h','o','l','a','\0'};
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.
o
charch; while(scanf("%c",&ch)==1)/*seleeuncaracter*/
Subsecciones
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); }
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.
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
Subsecciones
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];
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};
}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;
typedefunion { jetjetu; helicopterohelicopterou; avioncargaavioncargau; }transporteaereo; typedefstruct { inttipo; intvelocidad; transporteaereodescripcion; }un_transporteaereo
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;
asigna65(queeselcdigoASCIIde'A')anumeroentero.
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)
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(); }
Lasalidadelcdigoanteriores:
auto=0,static=0 auto=0,static=1 auto=0,static=2 auto=0,static=3 auto=0,static=4
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?
Cusaapuntadoresexplcitamentecon:
Cusaapuntadoresexplcitamentecon:
8.1Definicindeunapuntador
Unapuntadoresunavariablequecontieneladireccinenmemoriadeotravariable.Sepueden tenerapuntadoresacualquiertipodevariable.
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
100 x3
200 y1
1000 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.
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;
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]
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];
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
8.8Fallascomunesconapuntadores
Acontinuacinsemuestrandoserrorescomunesquesehacenconlosapuntadores.
Noasignarunapuntadoraunadireccindememoriaantesdeusarlo
int*x *x=100;
loadecuadoser,tenerprimeramenteunalocalidadfsicadememoria,digamosinty;
int*x,y; x=&y; *x=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.Asignacindinmicadememoriay Estructurasdinmicas
LaasignacindinmicadememoriaesunacaractersticadeC.Lepermitealusuariocreartiposde datosyestructurasdecualquiertamaodeacuerdoalasnecesidadesquesetenganenelprograma. Serevisarndosdelasaplicacionesmscomunes:
Arreglosdinmicos Estructurasdinmicasdedatos.
9.1Usodemalloc,sizeofyfree
Lafuncinmallocesempleadacomnmenteparaintentar``tomar''unaporcincontiguade memoria.Estadefinidacomo:
void*malloc(size_tsize);
intentaobtener100bytesyasignarlosaladireccindeinicioacp.
Esusualusarlafuncinsizeof()paraindicarelnmerodebytes,porejemplo:
int*ip; ip=(int*)malloc(100*sizeof(int));
9.2callocyrealloc
Existendosfuncionesadicionalesparareservarmemoria,calloc()yrealloc().Los prototipossondadosacontinuacin:
void*calloc(size_tnmemb,size_tsize); void*realloc(void*ptr,size_tsize);
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");
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.
Mostrar10valoresporlnea.
Subsecciones
10.Tpicosavanzadosconapuntadores
Sehanrevisadovariasaplicacionesytcnicasqueusanapuntadoresenloscaptulosanteriores.As mismosehanintroducidoalgunostemasavanzadosenelusodeapuntadores.Enestecaptulose profundizanalgunostpicosqueyahansidomencionadosbrevementeyotrosquecompletanla revisindeapuntadoresenC. Enestecaptulosedesarrollalosiguiente:
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*/
10.2Entradaenlalneadecomandos
Cpermiteleerargumentosenlalneadecomandos,loscualespuedenserusadosenlosprogramas. Losargumentossondadosotecleadosdespusdelnombredelprogramaalmomentodeser ejecutadoelprograma. Loanteriorsehavistoalmomentodecompilar,porejemplo:
gccoprogprog.c
dondegcceselcompiladoryoprogprog.csonlosargumentos. Parapoderusarlosargumentosenelcdigosedebedefinircomosiguelafuncinmain.
main(intargc,char**argv)
o
main(intargc,char*argv[])
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
10.3Apuntadoresafunciones
LosapuntadoresafuncionessonquizunodelosusosmsconfusosdelosapuntadoresenC.Los apuntadoresafuncionesnosontancomunescomootrosusosquetienenlosapuntadores.Sin embargo,unusocomnescuandosepasanapuntadoresafuncionescomoparmetrosenlallamada aunafuncin. Loanterioresespecialmentetilcuandosedebenusardistintasfuncionesquizspararealizartareas similaresconlosdatos.Porejemplo,sepuedenpasarlosdatosylafuncinqueserusadapor algunafuncindecontrol.ComosevermsadelantelabibliotecaestndardeCdafuncionespara ordenamiento(qsort)ypararealizarbsqueda(bsearch),alascualesselespuedenpasarfunciones. Paradeclararunapuntadoraunafuncinsedebehacer:
int(*pf)();
paraque
apuntealafuncin
Paraquetrabajeenformacompletaelcompiladoresconvenientequesetenganlosprototipos completosdelasfuncionesylosapuntadoresalasfunciones,porejemplo:
intf(int); int(*pf)(int)=&f;
Ahoraf()regresaunenteroytomaunenterocomoparmetro. Sepuedenhacercosascomo:
ans=f(5); ans=pf(5);
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;
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.Operadoresdebajonivelycamposdebit
Sehavistocomolosapuntadoresnosdancontrolsobrelasoperacionesdebajoniveldelamemoria. Muchosprogramas(porejemplo,aplicacionesdeltiposistemas)operanactualmenteabajonivel dondebitsindividualesdebensermanipulados. LacombinacindeapuntadoresyoperadoresanivelbithacendeCtilparamuchasaplicaciones debajonivelypuedencasireemplazaralcdigoensamblador.(Solamenteun10% aproximadamentedeUNIXestaencdigoensambladorelrestoesC.)
11.1Operadoressobrebits
LosoperadoressobrebitsdeCseresumenenlasiguientetabla: Operador & | ^ ~ << >> Accin Y O Oexclusiva(XOR) Complementoauno Negacin Desplazamientoalaizquierda Desplazamientoaladerecha
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
EnestafuncinseilustranvariascaractersticasdeC:
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;
Laformadeaccesarlosmiembrosesenlaformausual:
paquete.tipo=7;
Conestructuraanteriorsetieneque:
11.2.1Portabilidad
Loscamposdebitsonunaformaconvenientedeexpresarmuchasoperacionesdificiles.Sin embargo,loscamposdebitcarecendeportabilidadentreplataformas,poralgunadelassiguientes razones:
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)
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}
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
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"
12.1.4#ifInclusincondicional
Ladirectiva#ifevaluaunaexpresinconstanteentera.Siempresedebeterminarcon#endif paradelimitirelfindeestasentencia. Sepuedenasmismoevaluarotrocdigoencasosecumplaotracondicin,obien,cuandonose cumpleningunausando#elifo#elserespectivamente. Porejemplo,
#defineMEX0 #defineEUA1 #defineFRAN2
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
Comoloscomandosdelpreprocesadorpuedenestarencualquierpartedeunprograma,sepueden filtrarvariablesparamostrarsuvalor,cuandoseestadepurando,verelsiguienteejemplo:
x=y*3; #ifdefDEBUG printf("Depurando:variablesxeyigualesa\n",x,y); #endif
12.3Otrasdirectivasdelpreprocesador
Ladirectiva#errorforzaalcompiladorapararlacompilacincuandolaencuentra.Seusa principalmenteparadepuracin.Porejemplo:
#ifdefOS_MSDOS #include<msdos.h> #elifdefOS_UNIX #include"default.h" #else #errorSistemaOperativoincorrecto #endif
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
nosdarinformacinacercadestegeneradordenmerosaleatorios.
Subsecciones
14.Biblioteca<stdlib.h>
Parausartodaslasfuncionesdestabibliotecasedebetenerlasiguientedirectiva
#include<stdlib.h>
Lasfuncionesdelabibliotecapuedenseragrupadasentrescategorasbsicas:
Elusodetodaslasfuncionesessencillo.Seconsiderandentrodelcaptuloenformabreve.
14.1Funcionesaritmticas
Haycuatrofuncionesenterasbsicas:
intabs(intj); longintlabs(longintj); div_tdiv(intnumer,intdenom); ldiv_tldiv(longintnumer,longintdenom);
Fundamentalmentehaydosfuncionesparaenterosyparacompatibilidadconenteroslargos.
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:
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:
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); }
14.5Ejercicios
1. Escribirunprogramaquesimuleellanzamientodeundado. 2. Escribirunprogramaquesimuleelmelate,endondeseseleccionan6nmerosenterosenun rangode1al44 3. Escribirunprogramaqueleaunnmerodelalneadeentradaygenereunnmeroflotante aleatorioenelrangode0aelnmerodeentrada.
Subsecciones
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.
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);
16.1.2errno
Alavariableespecialdelsistemaerrnoalgunasllamadasalsistema(yalgunasfuncionesde biblioteca)ledanunvalorentero,paraindicarquehahabidounerror.Estavariableestadefinidaen lacabecera#include<errno.h>yparaserusadadentrodeunprogramadebeserdeclarada delasiguienteforma:
externinterrno;
16.1.3exit
Lafuncinexittieneelsiguienteprototipodeacuerdoalacabecera#include<stdlib.h>:
voidexit(intstatus);
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.
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.
Otrasfuncionesrelacionadasson:
intgetc(FILE*flujo); intputc(charch,FILE*flujo);
16.4E/Sformateada
SehanvistoyaalgunosejemplosdecomoCusalaE/Sformateada.Enestaseccinserevisarncon msdetalle.
16.4.1printf
Elprototipodelafuncinestadefinidocomo:
intprintf(constchar*formato,listaarg...);
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:
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...);
Paraelcasodeunarregloocadenasloserequiereelnombredelmismoparapoderusarscanfya quecorrespondealiniciodeladireccindelacadena.
charcadena[80]; scanf("%s",cadena);
16.5Archivos
Losarchivossonlaformamscomndelosflujos.
Loprimeroquesedebehaceresabrirelarchivo.Lafuncinfopen()hacelosiguiente:
FILE*fopen(constchar*nomb,constchar*modo);
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...);
Otrasfuncionesparaarchivosson:
intgetc(FILE*flujo)intfgetc(FILE*flujo) intputc(charch,FILE*s)intfputc(charch,FILE*s)
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
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:
paraverotrasopcionesusarman. Lafuncin:
intcreat(char*nomb,intperms);
puedetambinserusadaparacrearunarchivo. Otrasfuncionesson:
intclose(intfd); intread(intfd,char*buffer,unsignedlongitud); intwrite(intfd,char*buffer,unsignedlongitud);
quepuedenserusadasparacerrarunarchivoyleer/escribirundeterminadonmerodebytesdela memoria/haciaunarchivoenlalocalidaddememoriaindicadaporbuffer.
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".
Subsecciones
17.Manejodecadenas<string.h>
Recordandolapresentacindearregloshecha(captulo5)endondelascadenasestndefinidas comounarreglodecaracteresounapuntadoraunaporcindememoriaconteniendocaracteres ASCII.UnacadenaenCesunasecuenciadeceroomscaracteresseguidasporuncaracterNULLo \0:
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);
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');
lacualtendrresp=s1+2. Lafuncinstrtok()esunpocomscomplicadaencuantoaoperacin.Sielprimerargumento
Seempleauncicloforenunaformanoregulardeconteo:
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:
Elusodeestasfuncionesesdirectoyporlotanto,nosedanejemplos.
17.3Operacionesconlamemoria <memory.h>
Finalmenteseverunresumendealgunasfuncionesbsicasdememoria.Sinembargo,noson funcionesestrictamentedecadenas,perotienensuprototipoen#include<string.h>:
17.4Ejercicios
1. Escribirunafuncinsimilarastrlenquepuedamanejarcadenassinterminador.Tip:se necesitarconocerypasarlalongituddelacadena. 2. Escribirunafuncinqueregreseverdad,siunacadenadeentradaesunpalndromo.Un palndromoesunapalabraqueseleeigualdeizquierdaaderecha,odederechaaizquierda. Porejemplo,ANA. 3. Sugerirunaposibleimplementacindelafuncinstrtok(): 1. usandootrasfuncionesdemanejodecadenas. 2. desdelosprincipiosdeapuntadores. Cmoselograelalmacenamientodeunacadenaseparada? 4. Escribirunafuncinqueconviertatodosloscaracteresdeunacadenaamaysculas.
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.
SetieneacontinuacinlaemulacindelcomandocddeUnixconC:
#include<stdio.h> #include<unistd.h> #defineTAM80 main(intargc,char**argv)
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); }
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:
Lafuncinaccess()regresa:0sihahabidoxito,o1encasodefallayaerrnoseleasigna unvaloradecuado.Verlaspginasdelmanparaverlalistadeerrores.
18.2.1.1errno
Algunasllamadasalsistema(yalgunasfuncionesdebiblioteca)danunvaloralenteroerrnopara indicarquehahabidounerror.Estaesunavariableespecialdelsistema. ParausarerrnoenunprogramadeC,debeserdeclaradodelasiguienteforma:
externinterrno;
chmod()devuelve0encasodexitoy1encasodeerrorademsseasignaalavariableerrno unvaloradecuado(revisarlaspginasdemanparaverlostiposdeerrores)
18.2.2Estadodeunarchivo
Setienendosfuncionestilesparaconocerelestadoactualdeunarchivo.Porejemplosepuede sabequetangrandeesunarchivo(st_size),cuandofuecreado(st_ctime),etc(verladefinicindela estructuraabajo).Lasdosfuncionestienensusprototiposen<sys/stat.h>
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) {
18.2.3Manipulacindearchivos:stdio.h,unistd.h
Existenalgunasfuncionesparaborraryrenombrararchivos.Quizslaformamscomnesusando lasfuncionesdestdio.h:
intremove(constchar*pathname); intrename(constchar*viejo,constchar*nuevo);
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
Subsecciones
19.Funcionesparaeltiempo
EnestecaptuloserevisarcomosepuedeusarelrelojconllamadasalsistemaUNIX. Existenmuchasfuncionesparaeltiempoquelasquesernconsideradasaquusarlaspginasde manyloslistadosdelabibliotecaestndardefuncionesparamsdetalles. Elusomscomndelasfuncionesdetiemposon:
19.1Funcionesbsicasparaeltiempo
Algunasprototiposdelasfuncionesbsicasparaeltiemposonlassiguientes:
};
Encasodexito,sedevuelveeltiempotranscurridoensegundosdesdelapoca.Encasode error,sedevuelve((time_t)1)yseasignaalavariableerrnounvalorapropiado.
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); }
Lafuncinlrand48()devuelveenteroslargosnonegativosdistribuidosuniformememnteentre0 y .
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()
Lasalidapodrasercomolasiguiente:
Bifurcandoelproceso Eliddelprocesoes2662yelvalorregresadoes2663 Eliddelprocesoes2663yelvalorregresadoes0
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
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:
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"
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:
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;
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.
21.5OrganizacindelosDatosencada Archivo
Cualquierarchivodebertenersusdatosorganizadosenunciertoorden,tipcamentepodrserla siguiente:
Unafuncindefinidacomo:
floatenc_max(floata,floatb,floatc) {...}
podrtenerelsiguienteprototipo:
floatenc_max(floata,floatb,floatc);
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
SepuedeusarlaopcincdelcompiladordeCparacrearuncdigoobjeto(.o)paraunmdulo dado.Porejemplo:
gcccmain.c
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$<
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:
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
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:
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
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
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.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
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);
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