Estruturas de Dados Lista 1: soluções J. L. Rangel 1. Escreva um programa em C que lê três números inteiros do teclado, e imprime os três números em ordem crescente. #include <stdio.h> int leint(void) { printf(">"); scanf("%d",&i); return i; void troca(int *i, int *j){ int k=*i; *i=*j; *j=k; int main(void) { int i1, i2, i3; i1=leint(); i2=leint(); i3=leint(); if (i1>i2) troca(&i1, &i2); if (i2>i3) { troca(&i2, &i3); if (i1>i2) troca(&i1, &i2); printf("%d <= %d <= %d\n", i1, i2, i3); 4. Escreva uma função com protótipo int contaletra(char *s); que calcula o número de letras (maiúsculas e minúsculas) da cadeia s. /* letra verifica se c e uma letra veja tambem isalpha em <ctype.h> */ int letra(char c) { return ((c>='a') && (c<='z')) ((c>='a') && (c<='z')); (continua) Estruturas de Dados J.L. Rangel - 1
int contaletra(char *s) { int k=0; /* contador de letras */ int l=strlen(s); for (i=0; i<l; i++) if (letra(s[i])) k++; return k; Observação: veja na biblioteca <ctype.h> a função isalpha (diz se um caracter é uma letra) e outras funções semelhantes. 5. Escreva uma função que converte todas as letras de uma cadeia para maiúsculas. O protótipo pode ser void converte(char *s); /* min diz se c e' uma letra minuscula veja tambem islower em <ctype.h> */ int min(char c){ return (c>='a') && (c<='z'); /* veja tambem toupper em <ctype.h> */ void converte(char *s) { int l=strlen(s); int delta= 'a'-'a'; for (i=0; i<l; i++) if (min(s[i])) s[i]=s[i]-delta; Em vez de s[i]=s[i]-delta; em C se pode escrever s[i]-=delta; Estas abreviações devem ser usadas com cuidado, para não tornar os programas obscuros. 6. Escreva uma função que recebe como entrada uma cadeia, e devolve como saída uma cópia da cadeia. Esta função deve alocar o espaço necessário para a cópia. O protótipo pode ser char *copia(char *s); Solução (usando strcpy): #include <stdlib.h> #include <string.h> char *copia(char *s) { char *t=(char *)malloc(strlen(s)+1); return strcpy(t,s); Estruturas de Dados J.L. Rangel - 2
Esta outra solução é simples e elegante, mas não funciona! (Por que?) char *copia(char *s) { return s; 7. Idem, convertendo as letras da cópia para maiúsculas. Basta usar a função converte de (5). 8. Um código extremamente simples substitui cada letra pela letra seguinte, circularmente (Z é codificado como A). Por exemplo, Estruturas de Dados se transformaria em Ftusvuvsbt ef Ebept. Escreva funções para codificar e para decodificar cadeias segundo este código. /* ccod codifica um caracter */ char ccod(char c) { if ((c>='a') && (c<'z')) return ++c; if (c=='z') return 'A'; if ((c>='a') && (c<'z')) return ++c; if (c=='z') return 'a'; return c; /* cdec decodifica um caracter */ char cdec(char c) { if ((c>'a') && (c<='z')) return --c; if (c=='a') return 'Z'; if ((c>'a') && (c<='z')) return --c; if (c=='a') return 'z'; return c; /* scod codifica a cadeia s, por cima! */ void scod(char *s) { s[i]=ccod(s[i]); /* sdec decodifica a cadeia s, por cima! */ void sdec(char *s) { s[i]=cdec(s[i]); Estruturas de Dados J.L. Rangel - 3
9. Escreva um programa que lê uma frase (várias palavras) do teclado, e escreve as palavras uma por linha. Por exemplo, se a entrada fosse Estruturas de Dados a saída seria Estruturas de Dados Sugestão: O formato %[^\n] (qualquer coisa, exceto \n) pode ser usado por scanf para ler uma cadeia que contém brancos, até o Enter final. Além disso, há outras funções de leitura de cadeias, como gets e fgets, em <stdio.h>. #include <stdio.h> int main(void) { char s[80]; int m; /* m=1 -> mudar de linha no proximo branco */ printf(">"); /* com formato " %[^\n]" scanf le ate' o Enter do fim da entrada */ scanf(" %[^\n]",s); printf("[%s]\n",s); m=0; if (s[i]==' ') { if (m) { printf("\n"); m=0; else { printf("%c",s[i]); m=1; printf("\n"); O controle com m é necessário para mudar de linha só uma vez entre as palavras, mesmo que haja mais de um branco. O formato %[ ] só permite que sejam lidos os caracteres dentro dos colchetes; ^ quer dizer não, de forma que %[^\n] quer dizer qualquer coisa, até o fim da linha. Outras funções de <stdio.h> também leem uma linha, como gets, e fgets. (fgets é preferível, porque sua chamada especifica quantos caracteres podem ser lidos.) 10. Escreva uma função int igual(char *s1, char *s2); para descobrir se as cadeias s1 e s2 são iguais. Sugestão: comece descobrindo porque a solução abaixo não é aceitável. Estruturas de Dados J.L. Rangel - 4
/* bobagem! */ return s1==s2; A função dada verifica se o endereço das duas cadeias é o mesmo, em vez de verificar se os caracteres das duas cadeias são em mesmo número e iguais. Solução recursiva: if (s1[0]=='\0') return (s2[0]=='\0'); if (s2[0]=='\0') return 0; return (s1[0]==s2[0]) && igual(++s1,++s2); Solução iterativa (com for) for(i=0; (s1[i]!='\0') && (s2[i]!='\0'); i++) if (s1[i]!=s2[i]) return 0; /* aqui um dos dois caracteres e' nulo! */ return s1[i]==s2[i]; (abr 00) Estruturas de Dados J.L. Rangel - 5