Exercicios Programação

De volta ao exercício 1...já percebi tudo aquilo que tenho de fazer e já fiz isto (não olhem para os for que isso ainda não está pronto), mas estou a ter um problema ao declarar as variáveis na função increment. O que eu fiz foi:

Código:
//combinações com letras
#include <iostream>
using namespace std;
int increment(int n, (arr[n]))
{
    for (int x=65; x<=90; x++)
    {
    for (int s=0; s< (n-1); s++)
    putchar (arr[s]);
    arr[s-1]=x;
    }
    return arr[n];
}
int main()
{
    int n;
    cout << "Este programa cria palavras com n letras" << endl;
    cout << "\nIntroduza o numero de letras:";
    cin >> n;
    int arr[n];
    for (int z=0; z<n; z++)
    arr[z]=65;
    for (int s=0; s<n; s++)
    putchar (arr[s]);
    increment(arr[s]);
    cin.get();
    cin.get();
    return 0;
}

Quando compilo dá erro, porque não consigo declarar arr[n], dentro da função increment, que iria ser a função que iria incrementar de AAAA, para AAAB...claro que ainda não está pronto, até porque precisa de um if para quando chegar a aaaz passar a aaba, mas primeiro tenho que declarar as variáveis, certo???
 
Não executo os programas na linha de comandos porque não sei trabalhar com a linha de comandos...lool.
Se estás a aprender a programar não custa muito aprender alguma coisa da linha de comandos, basta o dir (ou ls em linux) e o cd para conseguires correr o programa a partir da linha de comandos.
Código:
    factorial(a);
    r=factorial(a);
    cout << r;
    cin.get();
    cin.get();
O factorial(a); e o cout << r; não estão aí a fazer nada, já estás a calcular o factorial ao guardar o seu valor em r.

Precisas dos dois cin.get(); provavelmente por estar aí o cout << r; penso eu,



EDIT: Quanto ao último post:

Vai para aí uma confusão com o array a passar de um lado para o outro.

Primeiro a declaração do arr[n] na função increment é int arr se quiseres receber um único inteiro, e seria assim de acordo com a chamada da função: increment( arr ), mas dúvido que seja isto que queiras, pelo que devia ser increment( arr ); na chamada e int arr[] ou int *arr na sua declaração na função increment.

Depois ainda tens outros erros como o arr[s-1]=x; e increment(arr); porque a variável foi definida dentro de um for e essas declarações estão fora do scope dos for's.

Para fazeres isso devias saber mais sobre arrays, mas isso iria levar a ponteiros que inicialmente ainda iria complicar mais.
 
Última edição:
O factorial(a); e o cout << r; não estão aí a fazer nada, já estás a calcular o factorial ao guardar o seu valor em r.

Precisas dos dois cin.get(); provavelmente por estar aí o cout << r; penso eu,



EDIT: Quanto ao último post:


Para fazeres isso devias saber mais sobre arrays, mas isso iria levar a ponteiros que inicialmente ainda iria complicar mais.

De facto o factorial(a) não faz nada, mas o cout << r faz, uma vez que sem ele não apareceria o resultado no programa (não estou a executar na linha de comandos).

Se achas que devia saber mais sobre arrays e ponteiros, então vou ver se aprendo isso primeiro (que é o que vem mais ou menos a seguir no tutorial que estou a seguir) e só depois é que tento fazer o exercício, porque também já tinha chegado á conclusão que não percebo quase nada de arrays.

De qualquer forma obrigado pela ajuda.
 
Peo que percebi tinha de fazer algo do tipo:

Código:
//Função factorial
#include <iostream>
using namespace std;

int factorial (int a)
{
    if (a <=1)
    cout << 1;
    else
    cout << (a * factorial (a - 1));
}
    
int main()
{
    int a;
    cout << "Este programa calcula o factorial de um dado numero" << endl;
    cout <<"\nIntroduza um numero:";
    cin >> a;
    factorial(a);
    cin.get();
    cin.get();
    return 0;
}
Ou seja, definir a função main sem argumentos e depois declarar a variavel a, mas mesmo assim ainda não dá...dá-me uns numeros estranhos, porque acho que continuo com o problema anterior (a variavel a devia ser declarada e preenchida (com o cin >> a) globalmente.
O que me parece que está a acontecer é que tenho duas variáveis a diferentes (uma em cada função) e eu queria que fosse uma só.

Quando defines a função main com argumentos o que tu estas a dizer é que ao executares o programa vais ter de executar com argumentos..

Seria algo assim na linha de comandos:

Código:
o_teu_programa 212

Em que 212 é o argumento (int a)

Fazer

int main (int a)

é diferente de fazer

int main()
{
int a;
/...
}

Aqui estás a definir uma variavel, em cima estás a dizer que a função main recebe um argumento. Obviamente que não dá erro porque a variavel está declarada como sendo o argumento da função, e até funciona correctamente. Mas é uma maneira incorrecta de resolver o problema.

Os erros são os que já te mostraram.


Não executo os programas na linha de comandos porque não sei trabalhar com a linha de comandos...lool.
Obrigado pela ajuda Aparicio, já consegui fazer o exercício...fiz:

Código:
//Função factorial
#include <iostream>
using namespace std;

int factorial (int a)
{
    if (a <=1)
    {
    return 1;
    }
    else
    {
    return (a * factorial (a - 1));
    }
}
    
int main()
{
    int a, r;
    cout << "Este programa calcula o factorial de um dado numero" << endl;
    cout <<"\nIntroduza um numero:";
    cin >> a;
   [COLOR=Red] //factorial(a);
    r=factorial(a);[/COLOR]
    cout << r;
    cin.get();
    cin.get();
    return 0;
}


Já tinha feito a parte que disseste MPalhas (porque como o programa estava tinha de primir para aí umas 6 vezes em ENTER), mas de qualquer forma muito obrigado pela ajuda...quanto ao facto de eu precisar apenas de 1 cin.get() na função main acho que está incorrecto, porque se só tiver 1 ele executa e fecha logo o programa, por isso necessita de 2.

Agora que já percebi mais ou menos a recursividade em c++ vou voltar a tentar fazer o exercício 1 (das combinações de letras) e se tiver alguma dúvida coloco aqui.


P.S. Muito obrigado pela ajuda pessoal...tem sido fundamental para eu aprender o básico de programação (porque eu até sei mais ou menos as coisas mas ainda não tenho o raciocínio treinado enquanto programador).

Repara no que está a vermelho. Estas a chamar a função factorial duas vezes. Na primeira vez a função retorna qualquer coisa, mas tu não guardas esse resultado em nenhuma variavel na função main. No segundo caso guardas o que a função retorna na variavel r. Por isso, a primeira linha a vermelha é desnecessária.

Já agora, não sei se concordam comigo, mas eu sou da opinião que se deve inicializar uma variavel a zero (dependendo dos casos claro), tipo:

Código:
int a = 0, r = 0;

Neste caso até não dá problemas, mas acho que é uma boa pratica.

Em relação ao cin.get() não funcionar quando é usado apenas uma vez, isso pode-se ser devido a teres alguma coisa no buffer de entrada (penso que era isto). Julgo que um fflush(stdin); limpa o buffer, mas não tenho a certeza.
 
Já agora, não sei se concordam comigo, mas eu sou da opinião que se deve inicializar uma variavel a zero (dependendo dos casos claro), tipo:

Código:
int a = 0, r = 0;
Neste caso até não dá problemas, mas acho que é uma boa pratica.
Se for variáveis para lhes atribuir um valor como neste exercício não acho necessário, por exemplo variáveis para usar nos for's atribui-se-lhes o valor no for.
Agora quando se espera que a variável seja zero aí se não se puser claro que pode vir a dar problemas visto que poderá não ser zero.

Em relação ao cin.get() não funcionar quando é usado apenas uma vez, isso pode-se ser devido a teres alguma coisa no buffer de entrada (penso que era isto). Julgo que um fflush(stdin); limpa o buffer, mas não tenho a certeza.

Ainda estive para sugerir isso mas depois fui pesquisar e não se deve fazer isso, como o fazer correctamente não sei ( não deve haver um forma standard ), mas dessa forma é incorrecto.

http://www.cplusplus.com/reference/clibrary/cstdio/fflush.html

Why fflush(stdin) is wrong

Things to Avoid in C/C++ -- fflush(stdin)
 
Ainda estive para sugerir isso mas depois fui pesquisar e não se deve fazer isso, como o fazer correctamente não sei ( não deve haver um forma standard ), mas dessa forma é incorrecto.

Código:
scanf[COLOR=#66CC66]([/COLOR][COLOR=#FF0000]"%*[^[COLOR=#000099][B]\n[/B][/COLOR]]%*c"[/COLOR][COLOR=#66CC66])[/COLOR];
 
Optimização:
Para qualquer n, não é possível dividí-lo por qualquer número entre raíz quadrada de n e n. Ou seja, não vale a pena dividir pelos números inteiros no intervalo [raíz(n), n]

Ou percebi mal a definição ou está incompleta. Significa que para o 16 não é possivel dividí-lo entre nunhum inteiro entre 4 e 16?!?!? Se for isto então e o 8? E como este há muitos mais, a não ser que me esteja a escapar alguma coisa.

Por outro lado se o número tiver raiz quadrada então não é primo, tem pelo menos três números pelo qual é divisivel (1, raiz(x),x )
 
Última edição:
Era mesmo entre sqrt(n) e n/2 que eu queria dizer, já que é óbvio que entre n/2 e n (exclusive) nunca é possível. Aquilo está apenas a explicar porque é que só vale a pena dividir entre 2 e sqrt(n), e não entre 2 e n/2 :)
 
Boas,

Depois de estar a estudar mais um pouco sobre arrays (como sugeriu o Aparicio), tive a alterar algumas coisas no exercicio 1 e já consigo declarar o array, mas estou com um problema. Já fiz o seguinte:

Código:
//combinações de letras
#include <iostream>
using namespace std;
int increment (int arr[], int n)
{
    for (int x=65; x<=90; x++)
    {
    for (int s=0; s< (n-1); s++)
    {
    putchar (arr[s]);
    arr[s]=x;
    }
    }
    return arr[n];
}
int main()
{
    int n;
    cout << "Este programa cria palavras com n letras" << endl;
    cout << "\nIntroduza o numero de letras:";
    cin >> n;
    int arr[n];
    for (int z=0; z<n; z++)
    arr[z]=65;
    for (int s=0; s<n; s++)
    {
    putchar (arr[s]);
    increment (arr, n);
    }
    cin.get();
    cin.get();
    return 0;
}

Mas isto não dá nada de jeito :D porque devolve-me muitas letras e nada do que quero.

P.S. Estou a usar o putchar() como sugeriu o MPalhas.

P.S. 2: O meu problema é na função increment(), mas se me ajudassem a fazer todas as combinações em que só variasse a última letra (AA, AB...AZ) depois acho que já conseguiria fazer o resto.


cumps


EDIT: Já vi que disseram que estes exercícios são simples para quem está a começar, mas acho que não são assim tão simples...especialmente este, mas concordo quando dizem que se aprende bastante com isto, porque eu também já aprendi algumas coisas nestes exercícios, sobretudo porque vou tirando as dúvidas que vou tendo, por isso muito obrigado pela ajuda.
 
Última edição:
Em vez de meteres valores como 65 e 90 a representar as letras, podes por 'A' e 'Z' que é equivalente.

Isso parece-me for's a mais, para usar esse método fiz basicamente isto só para dar uma ideia:

Código:
do printf("%s\n", s );
    while( inc( s, n - 1 ) );
Trato o array como uma string "verdadeira", ou seja só imprimo quando cada linha está completa e não carácter a carácter.
A string começa por ser AAA ( para 3 letras por ex. ), depois esse ciclo imprime a string enquanto a puder incrementar.

A função inc() incremente a string na posição do 2º argumento ( AAA = 2, AAA = 1, AAA = 0 ), seguindo a ideia do post do Kayvlim.

Isto é, a sub Main chama a função Increment para incrementar a última posição "AAAA", ficando "AAAB". Isto é num ciclo.
A própria função Increment() faz a transformação de "A" para "B", da letra que está na posição passada como parâmetro da função, de modo a que, se estivermos a incrementar "AAAZ", passa para "AABA", mas faz isto por recursividade - se a última posição estiver "preenchida", ela (função) chama-se a ela mesma para incrementar a posição anterior. Assim, na situação "AZZZ", a função é chamada tantas vezes quantas necessárias para passar a "BAAA" (ela chama-se a ela mesma três vezes).

A função inc() retorna 1 se incrementar e 0 quando já não puder incrementar mais, ou seja quando chega ao ZZZ fazendo com que o while termine.



Saber como se faria isto manualmente é fácil e o código também não é muito difícil, chegar de um ao outro é que pode não ser fácil, mas aí é que está o desafio.
 
Última edição:
Em vez de meteres valores como 65 e 90 a representar as letras, podes por 'A' e 'Z' que é equivalente.

Mas se usar as letras tenho que fazer pelo eu primeiro método, certo?? Ou seja, não uso o putchar() e defino um array como inicialmente para guardar as letras, por esemplo: abc[]="ABC...XYZ" e depois outro array que é o que me vai dando as combinações de letras?

Isso parece-me for's a mais, para usar esse método fiz basicamente isto só para dar uma ideia:

Código:
do printf("%s\n", s );
    while( inc( s, n - 1 ) );

Esta parte também não percebi...o printf() não é só em C?? Eu uso c++.
Também não percebi o argumento do printf ("%s\n", s)...ou é escrever o conteúdo de s e mudar de linha (\n)?

Trato o array como uma string "verdadeira", ou seja só imprimo quando cada linha está completa e não carácter a carácter.
A string começa por ser AAA ( para 3 letras por ex. ), depois esse ciclo imprime a string enquanto a puder incrementar.

A função inc() incremente a string na posição do 2º argumento ( AAA = 2, AAA = 1, AAA = 0 ), seguindo a ideia do post do Kayvlim.

A função inc() retorna 1 se incrementar e 0 quando já não puder incrementar mais, ou seja quando chega ao ZZZ fazendo com que o while termine.

Como é que tratas o array como uma string, ou seja, como é que o defines como sendo uma string...pelo que percebi guardas-lo numa variavel (neste caso s) e depois escreves o conteúdo desta variável no ecrã (que contém todo o conteúdo do array).


P.S. Peço desculpa pela enorme confusão neste post, mas espero que tenha acertado nalguma coisa :x
 
Mas se usar as letras tenho que fazer pelo eu primeiro método, certo?? Ou seja, não uso o putchar() e defino um array como inicialmente para guardar as letras, por esemplo: abc[]="ABC...XYZ" e depois outro array que é o que me vai dando as combinações de letras?

o que ele quer dizer é isto:

Código:
for (int x=65; x<=90; x++)
...


for (int x='A'; x<='Z'; x++)

estes dois ciclos são exactamente iguais. em C/C++ podes atribuir caracteres a variaveis inteiras, e o que fica guardado é o seu código ASCII, neste caso, entre 65 e 90.

assim como também podes fazer por exemplo, putchar(65) para imprimir a letra 'A'.

Esta parte também não percebi...o printf() não é só em C?? Eu uso c++.
Também não percebi o argumento do printf ("%s\n", s)...ou é escrever o conteúdo de s e mudar de linha (\n)?

em C++ podes usar tudo o que se usa em C, como o printf.
no printf, o primeiro argumento é a string a ser escrita, e o %s indica que vai ser escrita ali uma string, e que é dada também como parametro da função. por isso é como disseste, escreve o valor de s e muda de linha[/QUOTE]
 
o que ele quer dizer é isto:

Código:
for (int x='A'; x<='Z'; x++)

Por acaso não sabia que dava para fazer isso...assim facilita bastante. Depois disto estou com outro problema...para já está assim o exercício:

Código:
//combinações de letras
#include <iostream>
using namespace std;
int increment (int arr[], int n)
{
    for (int x='A'; x<='Z'; x++)
    {
    for (int s=0; s< (n-1); s++)
    {
    arr[s]=x;
    }
    }
    return arr[n];
}
int main()
{
    int n;
    cout << "Este programa cria palavras com n letras" << endl;
    cout << "\nIntroduza o numero de letras:";
    cin >> n;
    int arr[n];
    do printf("%s\n", [COLOR=red]s[/COLOR]);
    while ( increment (s, n-1));
    cin.get();
    cin.get();
    return 0;
}

O meu problema é ao declarar a variável S...não sei onde é que vou declará-la, porque o que percebi é que ela devia guardar o array para depois escreve-lo todo no ecrã.

A função increment também não deve estar completa, mas acho que já está melhor uma vez que esta função apenas deve retornar o valor e não imprimi-lo no ecrã (isso vai ser feito pela função main.
 
O método que eu disse era só para mostrar como não era preciso complicar tanto, mas se quiseres fazer assim:

Nesse teu código o s será o mesmo que o arr, ou utilizas um nome ou outro.

Código:
char arr[ n + 1 ]; // Também pode ser int, mas como é para caracteres o char serve melhor
...
do printf( "%s\n", arr );
    while ( increment ( arr, n - 1 ) );
Ao declarar o array ( ou string ) têm que se por + 1 porque para mostrar o array têm que ser terminada com um 0 (null terminated).

O que ainda tens que por antes do ciclo é preencher a array com 'A' n vezes (com um ciclo ou com a função memset), o array fica logo terminado com 0 porque foi declarado com n + 1. Convém por a seguir arr[n] = 0; porque esse valor pode não ser exactamente 0.


Agora o que tens de fazer é implementar a função increment, que já agora não precisa de nenhum for.

O que a função increment faz é pegar no array arr e incrementar a posição no segundo argumento.

Tens que ter em conta que quando a posição a incrementar for 'Z' terá de passar para 'A' e terá de incrementar a posição seguinte, aqui vêm a recursão.

E a função terá de retornar 1 excepto quando já não puder incrementar mais, quando for ZZZ por exemplo.
 
Última edição:
Back
Topo