Lista 1 - Linguagem de Programação C


 
9. Verificação da resposta do usuário
10. Manipulação de strings
11. Passagem de parâmetros para função
12. Linha de comando com argumentos
17. Strings: ponteiros, arranjos e alocação dinâmica
19. Detalhes 1

Obs.: Soluções alternativas para as correções dos problemas dos exercícios foram consideradas durante a correção.


9. Verificação da resposta do usuário (1,5)

É sempre recomendado verificar se o usuário fornece uma resposta válida frente a um conjunto de opções. Modifique o programa a seguir, utilizando a seqüência do-while, de modo a repetir o menu de opções sempre que esta for inválida. No programa a seguir, a execução é abortada se a opção for inválida.

/* prog9.c */

#include <stdio.h>

int main()
{
    char x;
    // O início do comando do-while deve estar antes da apresentação do menu
    // para que este seja repetido sempre que a opção for inválida (de acordo
    // com o pedido no enunciado do exercício).
    //
    do
    {
        printf("1. inclusao\n");
        printf("2. alteracao\n");
        printf("3. exclusao\n");
        printf(" Digite sua opcao:");

        x=getchar();

        switch(x)
        {
            case '1':
                /* sequencia de comandos para x == 1 */
            break;

            case '2':
                /* sequencia de comandos para x == 2 */
            break;

            case '3':
                /* sequencia de comandos para x == 3 */
            break;

            // A opção default do comando switch deve ser mantida para que a
            // mensagem "Opcao invalida" seja apresentada, se este for o caso.
            //
            // O comando exit(1) desta opção deve ser eliminado para que o
            // programa não mais termine sua execução caso a opção seja inválida.
            //
            default:
                printf("Opcao invalida\n");

                // comando usado apenas para ler o caracter "\n" (referente
                // a tecla "enter" que está no buffer, antes de ler a nova opção.
                //
                getchar();
        }
    } while (x != '1' && x != '2' && x != '3');

    /* demais comandos do programa */
}


10. Manipulação de strings (1,5)

Há várias funções para manipulação de strings, sendo importante destacar strcat(), strcmp(), strlen() e strcpy(). Estas funções estão definidas na biblioteca <string.h>. Escreva um programa que leia do teclado uma senha alfanumérica, utilize a função strcmp() para compará-la com uma senha definida internamente no programa e retorne ao usuário a validade ou não da senha fornecida por ele, em função do resultado da comparação.

/* prog10.c */

#include <stdio.h>
#include <string.h>

main()
{
    // variável usada para armazenar a senha, a qual pode ser qualquer arranjo de
    // caracteres.
    char *senha = "asdfgh";     // poderia ser também: char senha[7] = "asdfgh";

    // variável usada para armazenar a senha entrada pelo usuário.
    char s[7];

    printf ("Informe a senha: ");
    gets(s);             // poderia ser também: scanf("%s", s);

    if (!(strcmp(s, senha)))    // poderia ser também: if (strcmp(s, senha) == 0)
        printf("Senha Válida.\n");
    else
        printf("Senha Inválida.\n");
}


11. Passagem de parâmetros para função (2,0)

O programa abaixo toma dois dados inteiros recebidos pelo teclado e deveria imprimi-los em ordem crescente. Explique por que o programa não funciona corretamente e introduza as correções mínimas necessárias para torná-lo operante.

O programa não funciona corretamente porque a passagem de parâmetros para a função troca está sendo feita de forma errada. Ela está sendo feita por valor, assim a função troca manipula apenas valores de variáveis locais à função (ou seja, apenas cópias das variáveis dado1 e dado2, declaradas na função main). Para o programa funcionar corretamente, a passagem de parâmetros para a função troca deve ser feita por referência, assim a função manipularia os valores das próprias variáveis dado1 e dado2, declaradas na função main. A seguir, encontram-se as correções para que a passagem de parâmetros seja por referência:

/* prog11.c */

#include <stdio.h>

int main()
{
    int dado1, dado2;
    void troca(int *, int *);

    printf("Entre com dois dados inteiros: ");
    scanf("%d %d",&dado1, &dado2);

    troca(&dado1, &dado2);
    printf("Dados em ordem crescente: %d \t %d \n", dado1, dado2);

    return 0;
}

void troca(int *dado1, int *dado2)
{
    int temp;
    if(*dado1 > *dado2)
    {
        temp = *dado1;
        *dado1 = *dado2;
        *dado2 = temp;
    }
}


12. Linha de comando com argumentos (2,0)

É possível criar programas em C que aceitem argumentos na linha de comandos. A variável argc conterá o número de argumentos mais 1, e argv é um arranjo de ponteiros para strings, que irão apontar para posições de memória que recebem o nome do programa executável e a lista de argumentos.

Explique por que é necessário o uso da função atoi(), que converte um caractere para um inteiro.

Porque a variável (cont) usada no comando for e o segundo argumento (argv[1]) da linha de comandos são de tipos diferentes. Enquanto que a variável cont é do tipo inteiro, o argumento argv[1] é do tipo string (ponteiro para caracteres). Assim, para que a variável cont possa receber o conteúdo de argv[1], este conteúdo deve ser primeiramente convertido para inteiro.

Quantas são as opções de argumentos?

São três opções:

O que o programa faz em cada caso?

Levando em consideração que os argumentos passados são do tipo certo:

/* prog12.c */

#include <stdio.h>

int main(int argc,char *argv[])
{
    int disp,cont;

    if(argc < 2)
    {
        printf("Falta digitar o valor para contagem\n");
        exit(1);
    }

    if ((argc == 3) && (!strcmp(argv[2],"mostra")))
        disp = 1;
    else
        disp = 0;

    for(cont=atoi(argv[1]);cont;--cont)
        if(disp)
            printf("%d\n",cont);

    printf("%c",7);
}


17. Strings: ponteiros, arranjos e alocação dinâmica (2,0)

O programa a seguir apresenta problemas de implementação. Discrimine os problemas e proponha uma alternativa para eliminá-los, garantindo a execução da operação desejada. As linhas de código em que está presente a seqüência de comentário em branco (/* */) devem ser mantidas inalteradas no código alternativo a ser gerado, podendo ser introduzido código adicional entre estas linhas.

Problemas:

Existe incompatibilidades entre a declaração e o uso de algumas variáveis:

1) mens1: é declarada como um arranjo de caracteres (string), mas a sua atribuição é feita de forma incorreta. As possíveis soluções para este problema são:

char mens1[100];
strcpy(mens1, "Bem-vindo, ");
char *mens1;
mens1 = malloc(100);
*mens1 = "Bem-vindo, ";  
2) mens2: é declarada como um caracter, mas ela é manipulada como se ela fosse um ponteiro para caracteres (string). Como existe um comando de alocação de espaço na memória para ela (mens2 = malloc(100); /* */), o qual não pode ser alterado de acordo com o enunciado do exercício, então a única solução é realmente declará-la como um ponteiro para caracteres.
char *mens2;
mens2 = malloc(100); /* */
*mens2 = " aa lista de exercicios do curso EA877!\n";


Assim, duas opções possíveis para que o programa não apresente problemas de implementação, são:

/* prog17.c */
/* Este programa aceita o primeiro nome digitado pelo usuario e compoe uma frase a ser apresentada na tela */

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

int main()
{
    char *nome,mens1[100],*mens2;

    mens2 = malloc(100); /* */

    printf("Qual e' seu nome? "); /* */
    scanf("%s",nome); /* */

    strcpy(mens1, "Bem-vindo, ");
    *mens2 = " aa lista de exercicios do curso EA877!\n";

    printf("%s%s%s",mens1,nome,mens2); /* */
    return 0;
}

/* prog17.c */
/* Este programa aceita o primeiro nome digitado pelo usuario e compoe uma frase a ser apresentada na tela */

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

int main()
{
    char *nome,*mens1,*mens2;

    mens1 = malloc(100);
    mens2 = malloc(100); /* */

    printf("Qual e' seu nome? "); /* */
    scanf("%s",nome); /* */

    *mens1 = "Bem-vindo, ";
    *mens2 = " aa lista de exercicios do curso EA877!\n";

    printf("%s%s%s",mens1,nome,mens2); /* */
    return 0;
}


19. Detalhes 1 (1,5)

Por que não é possível corrigir, ao menos em alguns compiladores C, o nome do curso atribuído a p na forma:

char *p="EA878";
p[4] = '7'; /* erro! */

Porque está se tentando manipular o ponteiro p (isto é, acessar a quinta posição do conteúdo apontado por p), como se ele fosse uma string, ou seja, um arranjo de caracteres. Apesar de estas duas formas (ponteiros e strings) estarem intimamente relacionas em C, nem todos compiladores C aceitam essa forma direta de manipulação de ponteiros. A forma correta para essa manipulação seria: *(p + 4) = '7'.