Ir ao conteúdo
  • Cadastre-se

danieltm64

Membro Pleno
  • Posts

    23
  • Cadastrado em

  • Última visita

  1. danieltm64

    Matrizes

    Olá Brunassilvas, Antes de escrever código, você deve ter uma ideia clara do algoritmo que você vai implementar. Qual algoritmo você está usando? Qual foi a estratégia geral que você tinha em mente com esse código? Uma forma de resolver esse problema seria criar dois vetores cujos tamanhos são iguais ao número de elementos na matriz, e em um vetor você guarda os elementos encontrados na matriz, e no outro vetor você coloca o número de vezes que aquele elemento foi encontrado na matriz. Assim, quando você for percorrer a matriz, basta você verificar se o elemento atual já se encontra no primeiro vetor, e caso positivo você apenas incrementa o valor na posição correspondente do outro vetor. Caso o elemento atual da matriz não está no primeiro vetor, você coloca esse elemento na última posição não ocupada do vetor e coloca o número 1 na posição correspondente do segundo vetor. Ao final do processo você terá dois vetores, um deles terá os valores encontrados na matriz, e o outro dirá quantas vezes cada um desses valores foi encontrado na matriz. Imagino que há outros algoritmos para resolver esse problema, mas o descrito acima é apenas uma sugestão.
  2. A função que você está tendo problemas é essa:? /* Percorre todos os campos da lista e imprime ate o ponteiro proximo chegar em NULL. */ void edita_dados(Dados *dados, int item, char *nome, int idade) { int i = 0; while(dados != NULL && i <= item) { dados = dados->proximo; } if(dados != NULL && i == item) { strcpy(dados->nome,nome); dados->idade = idade; } printf("Editado com sucesso.\n"); printf("Pressione uma tecla para continuar.\n"); getch(); } Veja bem, você permanece no while enquanto dados for diferente de NULL e enquanto i for menor que ou igual a item, mas você não muda i dentro do while. Não vejo como isso pode estar certo, então tente incrementar a variável i dentro do while. Além disso, você só para o while quando dados for igual a NULL, ou seja, você não consegue nada com esse loop. Tente assim: while(dados->proximo != NULL && i < item) { dados = dados->proximo; ++i; } Dessa forma, dados apontará para um elemento válido (e não NULL), e a variável i indicará o número do elemento da lista para o qual dados aponta, e no if seguinte você estará comparando esse número com item, e esse teste deverá dizer se você encontrou o item desejado. Se você encontrou o item desejado, o nome e a idade serão copiados para dados. Além disso, na função editar, você atribui o retorno de edita_dados a principal, sendo que edita_dados é definido como tendo void como tipo de retorno. Isso não está certo, não faz sentido atribuir nada a uma variável. Nos protótipos no topo do arquivo, você tem o seguinte: Dados *edita_dados(Dados *dados, char *nome, int idade); mas você define a função assim: void edita_dados(Dados *dados, int item, char *nome, int idade) { ... Isso tem que ser regularizado. Se você adotar void como tipo de retorno (essa é minha sugestão), então na função editar, substitua isso: principal = edita_dados(principal, item, nome, idade); por isso: edita_dados(principal, item, nome, idade); Essas mudanças são apenas coisas que eu percebi, não testei essas mudanças e não sei se vão resolver o seu problema, mas tente aplicar essas mudanças e vê se ajuda.
  3. Michel, você poderia mencionar os títulos desses livros, e as edições deles? Assim ficaria mais fácil de esclarecer a sua dúvida, mas já adianto que se o livro não usa std:: e nem using namespace std; em lugar algum (especialmente em código), então provavelmente é bem antigo.
  4. Faça um sistema operacional quântico. lol Zoeiras a parte, uma ideia legal seria um programa gráfico que te mostra todos os detalhes de um repositório local Git. Seu programa executa os comandos Git e mostra na janela gráfica quais arquivos foram modificados, staged, etc. Ou então um programa que monta frases aleatórias. Tipo, frases mesmo, com estrutura, coesão, gramática correta e tal, mas com conteúdo completamente aleatório. Seria engraçado.
  5. Troque int main(void); por int main(void) ou seja, remova o ponto-e-vírgula. E no for interno, troque matriz[j] por matriz[i][j] mas o programa ainda imprimirá bobagem, porque você tem que preencher a matriz, senão ele imprime o que tiver na memória em que a matriz estiver armazenada.
  6. E qual é a mensagem de erro?
  7. Sim, você pode programar para Android em C++. O SDK do Android tem o tal do Android NDK (Native Development Kit, ou "Kit de Desenvolvimento Nativo"), que permite compilar código C++ (ou qualquer outra linguagem nativa) e rodá-lo no Android. O Qt é uma framework enorme em C++ que aproveita o Android NDK e torna todo o processo de desenvolvimento bem fácil, além de suportar diversas outras plataformas. Com Qt, você pode programar sua aplicação em C++ e basta compilá-la uma vez para cada plataforma em que você deseja que seu programa rode. Usando o Qt, você escreve seu código uma vez e o Qt trata das diferenças entre as diversas plataformas. Qt roda no Windows, Mac, Linux, Android, iOS, Windows Phone, BlackBerry, e também mais alguns menos conhecidos. É claro que aplicativos de smartphone (Android, iOS, etc.) devem ter uma interface de usuário adaptada para dispositivos móveis, enquanto um programa de desktop (Windows, Mac, etc.) deve ter uma interface de usuário adaptada para computadores de mesa, mas Qt não te impede de usar exatamente o mesmo código em todas essas plataformas. O que você pode fazer é criar uma interface gráfica para todas as plataformas móveis, e outra interface gráfica para todas as plataformas desktop. Assim, você cria a interface gráfica duas vezes mas escreve a lógica da sua aplicação uma vez só, e você alcança um público gigantesco com muito menos trabalho do que se você usasse as ferramentas nativas de cada plataforma que você deseja suportar. Já Qt Creator é uma IDE fantástica para desenvolver programas em C++ com Qt e programas em C++ que não fazem uso de Qt (a escolha é sua). Qt Creator é ele próprio feito em C++ com a framework Qt, então ele roda com a mesma aparência e funcionalidade no Windows, Mac e Linux. Isso é ótimo, porque você pode começar seu novo aplicativo no Windows e no dia seguinte continuar trabalhando nele no Linux, por exemplo. Até o formato do projeto é o mesmo. Além disso, Qt Creator é famoso por seu excelente desempenho. Ele integra um editor de código moderno e um editor gráfico que permite que você faça as telas/janelas do seu programa de forma visual, arrastando e soltando widgets como botões, campos de texto, etc. Qt e Qt Creator são gratuitos e open source, e eles são licenciados predominantemente sob a LGPLv3, mas algumas partes são GPLv3 (isso fica muito claro no site e no instalador, então não tem surpresa). O que isso significa é que você pode usar o Qt e o Qt Creator gratuitamente para desenvolver programas multiplataforma sem precisar de divulgar o código fonte do seu programa, podendo inclusive vendê-lo sem pagar um tostão pelo Qt e Qt Creator. A única restrição é que você vincule (ou "linka") o seu código com as bibliotecas do Qt de forma dinâmica (por exemplo, .dll no Windows, .so no Linux, .dylib no Mac, etc.), ou seja, você não pode vincular seu código com Qt de forma estática. A consequência prática disso é que em vez de poder criar um arquivo executável só, com todo o código necessário, é preciso colocar o código do Qt em arquivos de biblioteca separados e colocá-los lado-a-lado com o arquivo executável da sua aplicação. Por exemplo, no Windows, quem navegar até a pasta de instalação do seu programa vai ver as DLLs do Qt lá. Agora, se você quer desenvolver um aplicativo para smartphone, aí a coisa complica, porque a sua única obrigação com a LGPLv3 é fornecer ao seu usuário um meio de relinkar o seu programa com versões modificadas das bibliotecas Qt, que em plataformas desktop é fácil, basta vincular seu programa com Qt dinamicamente. Se você consegue fornecer ao seu usuário um meio de relinkar seu programa com versões modificadas das bibliotecas Qt em smartphones (eu pessoalmente fico muito confuso com relação ao procedimento de fazer isso, é um pouco mais complexo do que simplesmente vincular com o Qt dinamicamente, mas você pode dar uma pesquisada), então você pode usar o Qt de graça mesmo para aplicativos de smartphone sem divulgar seu código fonte. Já se você quiser que o seu aplicativo/programa seja licenciado sob a GPLv3 (ou seja, você disponibilizará seu código fonte e seu programa será software livre), então você pode usar o Qt sob a licença GPLv3 e não precisa se preocupar, porque seu código estará disponível mesmo então qualquer pessoa poderá recompilar seu programa e vinculá-lo com versões modificadas das bibliotecas Qt. Tem também a licença comercial, que é bem cara mas permite que você vincule com o Qt estaticamente em todas as plataformas, e não requer que você permita aos seus clientes relinkarem seu programa com versões modificadas das bibliotecas Qt, e não requer que você divulgue o código fonte do seu programa. Eles não falam o preço da licença comercial, mas os preços já foram divulgados uma vez muitos anos atrás e era bem caro (naquela época, pelo menos). Se você não se importa com as condições de uma dessas licenças, recomendo que você brinque um pouco com Qt, é bem fácil e a documentação dele é excelente. https://www.qt.io/
  8. Vamos lá. O nome que você escolheu para a sua classe não é ideal. Uma classe representa uma "coisa" ou "entidade", enquanto um método representa uma "ação" ou "operação". Pense em uma classe como um substantivo e pense em um método como um verbo. O nome que você escolher deve caber nesse formato. Então em vez de chamar sua classe de MonitorarPasta, talvez o nome MonitoradorDePasta seja melhor. Já os nomes que você escolheu para os métodos da classe MonitorarPasta não seguem o estilo de código convencional do C#. Em C#, nome de método normalmente começa com letra maiúscula, ao contrário do que se tem em Java, onde nome de método normalmente começa com letra minúscula. Assim, sugiro que você renomeie o método monitoraPasta para MonitorarPasta. Em C#, quando você deseja acessar algum dado de um objeto, não é comum usar métodos cujo nome começa com "get". Por exemplo, se você tem uma classe Pessoa, normalmente você não acessa o nome e a idade com métodos getNome e getIdade, e sim com propriedades. Uma propriedade nada mais é do que um método do tipo "get" e um método do tipo "set" com a mesma sintaxe de um atributo normal. No exemplo da classe Pessoa, você teria a propriedade Nome e a propriedade Idade, que seriam usados assim: // Exemplo de como usar propriedades com uma classe fictícia Pessoa pessoa = new Pessoa(); // usando propriedade pública para alterar um atributo privado. pessoa.Nome = "Luís"; pessoa.Idade = 25; // usando propriedade pública para ler um atributo privado. Console.WriteLine(pessoa.Nome + " tem " + pessoa.Idade + " anos de idade."); Assim, você acessa o dado não através de dois métodos mas através de uma propriedade, e essa propriedade sabe como ler e alterar o dado. No seu caso, você deveria colocar o diretório e o filtro como propriedades em vez de métodos. Fica assim: // atributos privados private string diretorio; private string filtro; // propriedades públicas public string Diretorio { get { return diretorio; } set { diretorio = value; } } public string Filtro { get { return filtro; } set { filtro = value; } } Na parte "get" você retorna o valor do atributo, e na parte "set" você altera o valor do atributo. Notei que você inicializa e prepara o watcher no método monitorarPasta, sendo que isso deveria ir no construtor, pois o construtor roda só uma vez, já o método monitorarPasta pode ser chamado várias vezes. Como é possível que o usuário da sua classe altere o diretório e o filtro antes de chamar o método monitorarPasta, é correto atualizar o diretório e o filtro do watcher nesse método. Não tenho certeza, mas acho que o que você queria era imprimir o nome completo do arquivo que foi criado, mas utilizando um objeto intermediário em vez de usar o FileSystemWatcher diretamente. O erro é que você inicia o monitoramento e logo em seguida você tenta acessar o nome do arquivo que foi criado, sendo que nenhum arquivo foi criado no curtíssimo intervalo de tempo entre começar o monitoramento e tentar acessar o nome do arquivo. Em vez disso, você deveria ter um evento em sua classe MonitorarPasta que é levantado quando o watcher detecta que um arquivo foi criado. Depois, no Main, após instanciar mp, você deve associar o evento de mp com métodos da classe Program. Assim, quando o objeto mp detectar a criação de um arquivo (através do watcher interno), um método é chamado e imprime o nome completo do arquivo. O código com todas as modificações fica assim: using System; using System.IO; namespace Destaques_do_Windows { class Program { static void Main(string[] args) { MonitoradorDePasta mp = new MonitoradorDePasta("C:\\Users\\Joao\\Desktop\\Manipula Arquivo", "*.txt"); mp.ArquivoCriado += new MonitoradorDePasta.ArquivoCriadoEventHandler(mp_ArquivoCriado); mp.MonitorarPasta(); Console.ReadLine(); } static void mp_ArquivoCriado(object sender, string nomeCompleto) { Console.WriteLine(nomeCompleto); } } class MonitoradorDePasta { private FileSystemWatcher watcher; private string diretorio; private string filtro; public string Diretorio { get { return diretorio; } set { diretorio = value; } } public string Filtro { get { return filtro; } set { filtro = value; } } public delegate void ArquivoCriadoEventHandler(object sender, string nomeCompleto); public event ArquivoCriadoEventHandler ArquivoCriado; public MonitoradorDePasta(string diretorio, string filtro) { this.diretorio = diretorio; this.filtro = filtro; watcher = new FileSystemWatcher(diretorio, filtro); watcher.Created += new FileSystemEventHandler(watcher_Created); watcher.Error += new ErrorEventHandler(watcher_Error); } public void MonitorarPasta() { watcher.Path = diretorio; watcher.Filter = filtro; watcher.EnableRaisingEvents = true; } private void watcher_Error(object sender, ErrorEventArgs e) { Console.WriteLine(e.GetException().Message); } private void watcher_Created(object sender, FileSystemEventArgs e) { ArquivoCriado(this, e.FullPath); } } } Como escrevo a maior parte do meu código em inglês, tem alguns termos em inglês que eu não sei a tradução portuguesa adotada na literatura brasileira. Por exemplo, delegates ("intermediários"?) têm nomes que normalmente terminam com Handler ("Lidador"?), mas não sei a tradução amplamente aceita, então no código que eu coloquei, chamei um delegate de ArquivoCriadoEventHandler. Enfim, adapte o código como preferir. Espero ter ajudado.
  9. Olá jpsan, Filter é uma propriedade, e não um método. Logo, em vez disso: watcher.Filter("*.jpg"); escreva isso: watcher.Filter = "*.jpg"; Além disso, você só quer escrever watcher.EnableRaisingEvents = true; depois de ter configurado o watcher por completo, senão você começa a monitorar um diretório antes de ter definido o tipo de arquivo a monitorar e os métodos para chamar ao detectar alguma mudança no diretório monitorado. Percebi uma coisa estranha no seu código. Veja: static void watcher_Created(object sender, FileSystemEventArgs e) { if (!File.Exists(e.FullPath)) { Console.WriteLine(e.FullPath); //Console.WriteLine("1"); } } Aqui você só imprime o nome completo do arquivo que acabou de ser criado se ele não existir. Penso que você quis dizer algo do tipo: static void watcher_Created(object sender, FileSystemEventArgs e) { Console.WriteLine(e.FullPath); } Acredito que não há necessidade nem de verificar se o arquivo existe mesmo, pois o método watcher_Created só é chamado quando um arquivo é criado. O código completo, com as modificações feitas, fica assim: using System; using System.IO; namespace Monitoramento_de_Arquivos_e_Sub_Pastas { class Program { static private FileSystemWatcher watcher; static void Main(string[] args) { watcher = new FileSystemWatcher("C:\\Users\\Joao\\Desktop\\Manipula Arquivo"); watcher.Created += new FileSystemEventHandler(watcher_Created); watcher.Error += new ErrorEventHandler(watcher_Error); watcher.Filter = "*.jpg"; // essa linha mudou watcher.EnableRaisingEvents = true; // essa linha mudou de lugar Console.ReadLine(); } static void watcher_Error(object sender, ErrorEventArgs e) { Console.WriteLine(e.GetException().Message); } static void watcher_Created(object sender, FileSystemEventArgs e) { Console.WriteLine(e.FullPath); // o if desse método foi removido } } }
  10. Olá yasminalves, Você declara uma matriz 5 por 5 e acessa ela em um laço for. Quando o laço for começa assim: for(i=1;i<5;i++) você está dizendo que a variável i vai variar de 1 a 4, pois assim que i < 5 deixar de ser verdadeiro, o laço acaba. Você provavelmente quis dizer assim: for(i=0;i<5;i++) pois assim, o i vai variar de 0 a 4, ou seja, o laço vai rodar 5 iterações. Faça a mesma alteração para o outro laço for, fica assim: for(j=0;j<5;j++) Mais adiante, você acessa a matriz com um único índice, mas a sua matriz tem duas dimensões. Você acessa a matriz assim: matriz[j] = '||'; mas você provavelmente quis dizer assim: matriz[i][j] = '|'; afinal, para quê ter dois fors e usar o índice de apenas um, não é mesmo? Além disso, a matriz é de chars, então você só pode guardar um caractere em cada posição. O mesmo se aplica para a variável adivinha, que é do tipo char, então você deve inicializá-lo com '|', não '||'. Também é preciso atualizar a linha de código que imprime um elemento da matriz. Troque isso: printf("%c ",matriz[j]); por isso: printf("%c ",matriz[i][j]);
  11. Olá Vitor, A linha de código arq.seekp(9, ios::end); pula para a décima posição a partir do fim, não do início. Tenta assim: arq.seekp(9, ios::beg); A linha de código acima pula para a décima posição a partir do início do arquivo.
  12. Olá, Philipe. Apenas para recordar, uma lista simplesmente encadeada é uma lista encadeada em que cada nodo contém, além do dado a ser armazenado, um apontador para o nodo seguinte, enquanto uma lista duplamente encadeada é uma lista encadeada em que cada nodo contém, além do dado a ser armazenado, dois apontadores: um para o nodo anterior e outro para o nodo seguinte. Uma multi-lista é uma lista encadeada em que cada nodo contém múltiplos apontadores. Uma lista duplamente encadeada é um caso particular de multi-lista, mas o termo ‘multi-lista’ é comumente usado para referir-se a listas encadeadas com 3 apontadores ou mais. O propósito de multi-listas é ordenar um único conjunto de dados de várias maneiras eficientemente. Por exemplo, suponhamos que cada elemento da lista representa um funcionário, e cada funcionário tem nome, salário e sexo. Cada nodo da lista contém um funcionário e 3 apontadores. Assim você pode ter um único conjunto de funcionários e, de maneira muito eficiente, você pode percorrer essa lista de funcionários em diversas ordens, como: percorrer por nome em ordem alfabética, percorrer por salário em ordem crescente, e percorrer por sexo. Exemplo: Começo: * Apontador (Nome): Nodo 1 * Apontador (Salário): Nodo 2 * Apontador (Sexo Masculino): Nodo 3 * Apontador (Sexo Feminino): Nodo 2 Nodo 1 * Nome: Antônio * Salário: 3000 * Sexo: Masculino * Apontador (Nome): Nodo 3 * Apontador (Salário): NULL * Apontador (Sexo): NULL Nodo 2 * Nome: Paula * Salário: 1000 * Sexo: Feminino * Apontador (Nome): NULL * Apontador (Salário): Nodo 3 * Apontador (Sexo): NULL Nodo 3 * Nome: Bernardo * Salário: 2000 * Sexo: Masculino * Apontador (Nome): Nodo 2 * Apontador (Salário): Nodo 1 * Apontador (Sexo): Nodo 1 Como você pode ver, cada nodo possui 3 apontadores, e se você sempre seguir o apontador associado ao nome do funcionário, você percorrerá a lista em ordem alfabética dos nomes dos funcionários, e se você sempre seguir o apontador associado ao salário do funcionário, você percorrerá a lista em ordem crescente de salário, e assim por diante. Assim, o dado só existe uma vez e eficientemente você consegue ordenar os dados de acordo com diversos critérios. Para verificar isso, note que o apontador associado ao nome no começo aponta para o nodo 1, cujo funcionário tem nome começando com A, e esse nodo aponta para o nodo 3, cujo funcionário tem nome começando com B, e esse nodo aponta para o nodo 2, cujo funcionário tem nome começando com P. Assim os funcionários estão ordenados por nome em ordem alfabética. O mesmo vale para o salário, pois o começo aponta para o nodo 2, cujo funcionário tem o menor salário, e esse nodo aponta para o nodo 3, cujo funcionário tem um salário maior, e esse nodo aponta para o nodo 1, cujo funcionário tem o maior salário. Com relação ao sexo masculino, o começo aponta para o nodo 3, cujo funcionário é homem, e esse nodo aponta para o nodo 1, cujo funcionário também é homem. Já com o sexo feminino, o começo aponta para o nodo 2, cujo funcionário é mulher. Com base nesse exemplo, um elemento da multi-lista poderia ser definido da seguinte forma em C: struct nodo { char *nome; int salario; bool sexo; struct nodo *proximoNome; struct nodo *proximoSalario; struct nodo *proximoSexo; } Ou, se você quiser permitir percorrer a lista de trás pra frente, um elemento da multi-lista poderia ser definido assim: struct nodo { char *nome; int salario; bool sexo; struct nodo *anteriorNome; struct nodo *proximoNome; struct nodo *anteriorSalario; struct nodo *proximoSalario; struct nodo *anteriorSexo; struct nodo *proximoSexo; }
  13. Olá, eliumoraes. A linha setbuf(stdin, NULL); basicamente desassocia a entrada padrão do seu programa. você não quer isso, tire essa linha do seu código. Agora falta trocar isso: scanf("%[^\n]s",k); por isso: scanf(" %[^\n]s",k); Não tenho certeza quanto a isso, mas acredito que colocando esse espaço adicional na string passada para scanf, você permite que haja espaço entre as entradas do usuário. Se você não acrescentar esse espaço, o programa não vai ler entrada do teclado após o usuário entrar o valor de p (verifique por conta própria). Com essas mudanças, o programa deve funcionar.
  14. Olá, Vitor. Primeiro, note que você está alocando espaço o suficiente para o arquivo inteiro, sendo que você acaba gravando apenas a metade. A primeira mudança é então trocar isso: buffer = (char*) malloc (sizeof(char)*(lSize)); por isso: buffer = (char*) malloc (sizeof(char)*(lHalfSize)); Depois, perceba que você especifica sizeof(int) como o tamanho de um elemento a ser lido/escrito nas funções fread/fwrite, sendo que você aloca buffer com sizeof(char). Além disso, você especifica sizeof(buffer) como o número de elementos a serem lidos/escritos, porém isso apenas calcula o tamanho de um apontador (normalmente 4 ou 8 bytes), e não o número de elementos realmente armazenados em buffer. A segunda mudança é então trocar isso: fread (buffer, sizeof(int), sizeof(buffer), arq1); fwrite (buffer , sizeof(int), sizeof(buffer), arq2); por isso: fread (buffer, sizeof(char), lHalfSize, arq1); fwrite (buffer , sizeof(char), lHalfSize, arq2); Pois assim, você diz que devem ser lidos/escritos lHalfSize elementos, cada um com sizeof(char) bytes. Com essas mudanças, o seu programa deve funcionar.
  15. Olá, Roger. A variável inteiro estava ficando tão grande que dava overflow, ou seja, ficava tão grande que voltava pra zero. Além disso, seu código imprime a variável inteiro (que é do tipo unsigned int) com %d na string que você passa para a função printf, e %d é usado para imprimir valores do tipo int (com sinal), e é por isso que o seu programa imprime valores negativos. Para resolver esses dois problemas, troque isso: unsigned int inteiro = 0; por isso: unsigned long long int inteiro = 0; para que a variável possa armazenar números maiores. Além disso, troque: printf("inteiro: %d\n\n", inteiro); por: printf("inteiro: %llu\n\n", inteiro); para imprimir valores do tipo unsigned long long int. Agora resta alterar o código que de fato grava o número na string. Veja que no seu código você faz isso da seguinte forma: sprintf(buf, "%d.%d", inteiro, inteiro); Oras, aqui você está gravando a variável inteiro (que a esse ponto do programa contém a parte fracionária) duas vezes, separando-os por um ponto. Isso não está certo, você deve primeiro gravar inteiro na string seguido de um ponto antes de entrar no laço de repetição (gravando assim a parte inteira e o separador decimal), e depois do laço de repetição você tem que gravar essa variável de novo (agora com a parte fracionário) ao final da string. Isso é feito da seguinte forma: você declara uma variável inteira, vamos chamá-la de deslocamento, essa variável conterá o número de caracteres que foram gravados na string. Assim, acrescente isso logo antes do laço de repetição: int deslocamento = sprintf(buf, "%d.", (int)f); Isso vai gravar a parte inteira na string. Depois, no final, troque isso: sprintf(buf, "%d.%d", inteiro, inteiro); por isso: sprintf(buf + deslocamento, "%llu", inteiro); para gravar a parte fracionária depois dos deslocamento caracteres que foram gravadas antes de entrar no laço de repetição. A função agora deve estar assim: void ConvertFloatToString(float f, char *buf) { float temp; float ret; float num; unsigned long long int inteiro = 0; temp = (int)f; // Carrega a variavel temp com a parte intira do valor; temp = f - temp; // Carrega temp com a parte decimal do valor; printf("Parte decimal do valor a ser convertido: %f\n\n\n", temp); int deslocamento = sprintf(buf, "%d.", (int)f); do { inteiro = inteiro * 10; // Multipica por 10 para poder fazer o acumulo das numeros decimais; num = (int)temp; // a variavel "num" recebe apenas a parte inteira do numero; ret = temp - num; // esse calculo retira a parte inteira e atribua somente a parte decimal a variavel "ret"; //========================================================================= printf("temp1: %f <----------\n", temp); temp = ret * 10; // Multipica por 10 para transformar a primeira casa decimal, após a virgula, em um inteiro; printf("temp2: %f <----------\n", temp); //======================================================================= inteiro = inteiro + num; // Esse calculo acumula os valores decimais transformados em inteiro; printf("ret: %f\n", ret); printf("num: %f\n", num); printf("temp: %f\n", temp); printf("inteiro: %llu\n\n", inteiro); }while(ret > 0.0f); // Faca isso enquanto o valor decimal for maior do que 0,0; /* * Aqui eu tranformo os dis valores inteiros eum uma string representando o valor * original de float, e coloco um ponto entre os dois inteiros; */ sprintf(buf + deslocamento, "%llu", inteiro); } Rodando esse código na minha máquina, obtenho como resposta final buf: 12.5300997895426670592 sendo que o valor que foi passado para dentro da função é 12.5301f, e isso acontece porque números de ponto flutuante são representações binárias de números decimais, então introduz-se um pequeno erro ao armazenar um número em formato de ponto flutuante. É por isso que não se aconselha a usar o operador != diretamente para verificar se um float é diferente de outro, recomenda-se verificar se a diferença entre os dois floats é maior que um limiar, pois dessa forma você está considerando o erro que ocorre em números de ponto flutuante.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...