Aula 10 - Resoluções não publicadas


Exercício 1

#include <stdio.h>
#include <stdlib.h>

/*
 * Declaracao das funcoes a usar na funcao main():
 */

/* Funcoes de entrada e saida: */
int ler(char[], int, FILE *);
int escrever(char[], FILE *);

/* Funcoes para processamento de cadeias de caracteres: */
int comprimento(char[]);
int copia(char[], char[]);
int concatena(char[], char[]);
int copian(char[], char[], int);
int concatenan(char[], char[], int);
int compara(char[], char[]);
int dentro(char[], char[]);


int main(void)

{
#define N 1000 /* tamanho das matrizes. */
#define M 20 /* total de nomes. */

    char nomes[M][N], aux[N];
    int i, j, k;
    
    /* Leitura dos nomes: */
    printf("\n\nIntroduza nomes:\n");
    for(i = 0; i < M; i++)
    {
	ler(nomes[i], N, stdin);
	/* Eliminar o '\n' final: */
	if(nomes[i][comprimento(nomes[i]) - 1] == '\n')
	    nomes[i][comprimento(nomes[i]) - 1] = '\0';
    }
    
    /* Ordenacao: */
    for(i = 0; i < M - 1; i++)
    {
	k = i;
	for(j = i + 1; j < M; j++)
	    if(compara(nomes[j], nomes[k]) < 0)
		k = j;
	if(k != i)
	{
	    copia(aux, nomes[i]);
	    copia(nomes[i], nomes[k]);
	    copia(nomes[k], aux);
	}
    }
    
    /* Escrita ordenada: */
    printf("Nomes:\n");
    for(i = 0; i < M; i++)
    {
	escrever(nomes[i], stdout);
	fputc('\n', stdout);
    }
	
    return EXIT_SUCCESS;
}


/* 
 * Notas:
 * 1. A leitura deve-se fazer ate':
 *    a) ser lido o caracter '\n',
 *    b) ser atingido o final da entrada, e
 *    c) se terem lido tamanho-1 caracteres (para caber o '\0').
 * 2. Faz-se a leitura para c do tipo int para que seja possivel
 *    discriminar o valor especial EOF (devolvido por fgetc() para
 *    assinalar que atingiu o fim da entrada) dos outros possiveis
 *    caracteres lidos.
 * 3. O teste i < tamanho - 1 e' o primeiro para que, se for falso,
 *    nao se chegue a ler nenhum caracter, que teria forcosamente de
 *    ser descartado, o que seria um erro.
 * 4. Ao ser executada a instrucao return a funcao termina
 *    imediatamente, o que foi usado para evitar alguns else... 
 */
int ler(char cadeia[], int tamanho, FILE *entrada)

{
    int c, i;

    /* Se o comprimento for <= 1 nao e' possivel ler nada: */
    if(tamanho <= 1)
    {
	/* Se o comprimento for 1 ha' que colocar o terminador na cadeia: */
	if(tamanho == 1)
	    cadeia[0] = '\0';
	return 0;
    }

    /* Ciclo de leitura: */
    for(i = 0; i < tamanho -1 && (c = fgetc(entrada)) != '\n' && c != EOF; i++)
	cadeia[i] = c;

    /* Tera' o ciclo terminado por se atingir o limite da matriz ou o fim da
       entrada? */
    if(i == tamanho - 1 || c == EOF)
    {
	/* Em ambos os casos falta colocar o terminador na posicao i: */
	cadeia[i] = '\0';
	/* Se nao se conseguiu ler qualquer caracter devolve-se EOF: */
	if(i == 0)
	    return EOF;
	return i;
    }
    /* Neste caso o ciclo terminou num fim-de-linha que, no entanto, nao foi
       colocado em cadeia! */
    cadeia[i] = '\n';
    cadeia[i + 1] = '\0';
    return i + 1;
}


int escrever(char cadeia[], FILE *saida)

{
    int i;
    
    for(i = 0; cadeia[i] != '\0'; i++)
	fputc(cadeia[i], saida);
    return i;
}


int comprimento(char cadeia[])

{
    int i;
    
    for(i = 0; cadeia[i] != '\0'; i++)
	/* Nada! */;
    
    return i;
}


int copia(char cadeia1[], char cadeia2[])

{
    int i;
    
    for(i = 0; (cadeia1[i] = cadeia2[i]) != '\0'; i++)
	/* Nada! */;

    return i;
}


int concatena(char cadeia1[], char cadeia2[])

{
    int i, j;
    
    i = comprimento(cadeia1);

    for(j = 0; (cadeia1[i] = cadeia2[j]) != '\0'; i++, j++)
	/* Nada! */;

    return i;
}


int copian(char cadeia1[], char cadeia2[], int n)

{
    int i;
    
    for(i = 0; i < n && cadeia2[i] != '\0'; i++)
	cadeia1[i] = cadeia2[i];

    if(i < n)
	cadeia1[i] = '\0';
    
    return i;
}


int concatenan(char cadeia1[], char cadeia2[], int n)

{
    int i, j;
    
    i = comprimento(cadeia1);

    for(j = 0; j < n && cadeia2[j] != '\0'; i++, j++)
	cadeia1[i] = cadeia2[j];

    cadeia1[i] = '\0';
 
    return i;
}


int compara(char cadeia1[], char cadeia2[])

{
    int i;
    
    for(i = 0; cadeia1[i] == cadeia2[i] && cadeia1[i] != '\0'; i++)
	/* Nada! */;
    
    if(cadeia1[i] == cadeia2[i])
	return 0;
    else if(cadeia1[i] > cadeia2[i])
	return 1;
    else
	return -1;
}


/* 
 * Note-se na utilizacao das instrucoes return, que simplificam bastante
 * o codigo.
 */
int dentro(char cadeia1[], char cadeia2[])

{
    int i, j1, j2;
    
    if(cadeia2[0] == '\0')
        return 0;

    for(i = 0; cadeia1[i] != '\0'; i++)
    {
        for(j1 = i, j2 = 0; cadeia1[j1] == cadeia2[j2] && 
                            cadeia1[j1] != '\0'; j1++, j2++)
            /* Nada... */;
        if(cadeia2[j2] == '\0')
            /* cadeia1 esta' contida em cadeia2, posicao e' i: */
            return i;
        if(cadeia1[j1] == '\0')
            /* O que sobra de cadeia1 e' muito curto: */
            return -1;
    }
    return -1;
}

Página concebida e mantida por Eng. Manuel Menezes de Sequeira (última actualização 2006/07/07)
Copyright © 1996-2001 ISCTE