Ir ao conteúdo

isrnick

Membro Pleno
  • Posts

    1.558
  • Cadastrado em

  • Última visita

Tudo que isrnick postou

  1. Essa nomenclatura é do Windows API (Win32) e é uma convenção velha, na época eles achavam mais importante minimizar os comandos pra digitar menos do que facilitar a leitura, o própria linguagem C segue a mesma lógica... Bom se você sabe a convenção e entende a língua inglesa até vai fazer mais sentido, o problema é que não dá pra entender sem saber a convenção. Se tivesse sido criado hoje em dia certamente usariam algo mais legível, mas a Windows API está aí a muito tempo então pra usá-la tem que aprender a convenção... Busque por Windows Coding Conventions e você vai achar vários links, seguem dois: https://docs.microsoft.com/pt-br/windows/win32/learnwin32/windows-coding-conventions https://docs.microsoft.com/en-us/windows/win32/stg/coding-style-conventions
  2. @MB_ note que para calcular fn(x) deve multiplica o termo anterior f(n-1)(x) por (-1) invertendo seu sinal, assim a cada novo termo o sinal é invertido (positivo, negativo, positivo, negativo, etc).
  3. Acho que finalmente corrigi tudo...
  4. @MB_ Obrigado, o lado esquerdo está errado mesmo... Deixa eu arrumar. (O restante está correto.)
  5. A série do exercício é: O seu erro principal foi calcular n! , observe que n! cresce muito rapidamente, e como o tipo int só armazena uma faixa limitada de números, em pouco tempo o valor de n! fica maior do que uma variável do tipo int pode armazenar. Observe que a série divide pelo fatorial, logo solução que não estoura o a capacidade da variável deve calcular 1/n! pois isso fica cada vez menor, ao invés de crescer. Para calcular isso pode usar o fato de que 1/n! = 1/(n-1)! * 1/n para calcular o próximo valor. Mas note que esta série também pode ser escrita como: Onde fn(x) é o n-ésimo termo da série, e temos que: Assim basta saber o termo anterior da série para calcular o termo atual. Edit: Corrigi para f0 = 1 . Edit 2: Corrigi o expoente e incluí o (x) nas funções f.
  6. Sobre o motivo da linguagem C usar * para indireção/desreferenciamento, se deve ao fato de que a linguagem B já o usava assim, e o C apenas copiou do B. Agora o motivo por que o B escolheu usar esses caracteres que já tinham outras funções, ao invés de escolher outros caracteres, isso ocorreu pois o teclado usado no computador no qual a linguagem B foi desenvolvida tinha uma quantidade limitada de caracteres, e após certo ponto se tornou necessário reutilizar caracteres. https://softwareengineering.stackexchange.com/questions/252023/why-does-c-use-the-asterisk-for-pointers Sim, mudar o caractere para algum sem uso, ou menos usado, melhoria a legibilidade do código. Mas a proposta do C é ser uma linguagem de sistema minimalista, no sentido de que a quantidade de recursos fundamentais e da biblioteca padrão sejam os mínimos necessários para facilitar a implementação de um compilador para qualquer nova arquitetura ou plataforma que surja, tornando mais fácil compilar códigos C para a nova plataforma. Existe uma quantidade grande de codebases fundamentais em C, incluindo kernels, SOs, compiladores de outras linguagens, e bibliotecas para uma infinidade de recursos, que são mantidos a décadas (as vezes quase inalterados), então mudanças no C devem ser uma adição ao invés de uma alteração, a menos que não haja opção, para não quebrar a compatibilidade códigos legados. Então, permitir maneiras alternativas de fazer a mesma coisa implicaria ter 2 modos de fazer a mesma coisa, o que aumentaria a complexidade da linguagem, indo contra sua proposta. Isso não quer dizer que o comitê não aceita adicionar mais nenhuma alteração ao padrão do C, mas deve ser algo que adicione funcionalidade não apenas altere uma existente, e tem que ser uma funcionalidade absolutamente necessária, caso contrário a funcionalidade deverá ser obtida através de bibliotecas de terceiros ou implementada pelo programador. Logo, as chances de fazerem esse tipo de alteração por motivo de legibilidade, praticidade ou conveniência é perto de zero. Agora quanto ao problema da falta de segurança dos ponteiros, sim o C é uma linguagem muito insegura, colocando a responsabilidade no programador de fazer verificações e checagens tal que garanta o uso seguro da memória, e sim isso é consequência do histórico da linguagem, e provavelmente não vai ser modificado pelos mesmos motivos acima. Mas se você quer uma alternativa com ponteiros seguros, pelo menos agora existe a opção de usar a linguagem RUST, porém a notação nele foi herdada do C então você não vai escapar do * e & para ponteiros e endereços. Mas talvez você tenha mais sucesso sugerindo esse tipo de mudança para o RUST, visto que é uma linguagem nova e teoricamente ainda dá tempo de fazer esse tipo de alteração, a questão é conseguir convencer a comunidade de que essa é uma alteração necessária, visto que para bem ou mal essa notação já é muito aceita.
  7. void quadros_inv(int n){ if(n > 1){ printf("%d, ", n*n); quadros_inv(n-1); } else { printf("1"); } } Assim imprimiria os quadrados perfeitos até n² em ordem decrescente, mas o enunciado falou que a função "devolve a lista", então acho que a intenção era retornar a lista ao invés de imprimir dentro da função... O que aumenta a complexidade do problema. Pelo fato de usar o termo 'lista' no enunciado, e não arranjo ou vetor, e a saída estar com colchetes [ ], me faz pensar que esse exercício originalmente foi proposto para Python e não C ou C++, aí sim faria mais sentido "devolver uma lista". (Sim, buscando online até achei numa lista exercícios de Python, o exercício 9 nesse link: https://www.math.tecnico.ulisboa.pt/~ccal/python/ex02.html )
  8. Para o '0' apenas coloque mais case (antes do default) para checar se é '0' colocando apenas um break assim ele não soma em nenhum contador. Já no caso do 11 tem várias possibilidades, mas como só tem 2 candidatos uma solução seria ler 2 caracteres e se o segundo caractere for diferente de '\n' incrementa o nulos e usa continue para pular para o próximo ciclo do loop, assim qualquer coisa com mais de 1 caractere é considerado voto nulo. int c; ... scanf("%c%c", &op, &c); op=toupper(op); if (c != '\n'){ while ((c=getchar()) != '\n' && c != EOF); //limpa a entrada padrão nulos++; continue; } Note que seu programa tem limite de no máximo 9 candidatos, pois só serão válidas opções com 1 dígito, para fazer algo que aceita qualquer quantidade de candidatos precisaria mudar o método.
  9. A>B>C não existe no C++, é necessário fazer 2 comparações e usar o operador lógico E para checar que as 2 são verdadeiras: A>B && B>C
  10. A função scanf retorna o número de parâmetros que foram lidos com sucesso, então como vai ler apenas um número float, deve checar se o retorno do scanf é igual a 1. do { printf("\nDigite o valor da base: "); if (scanf("%f", &base) == 1){ break; } printf("Valor invalido! Digite novamente.\n"); } while(1);
  11. Ou similar: Pode parecer conveniente, mas não existe em C. O valor entre os [] tem que ser uma constante. Ou você aloca um tamanho arbitrário que ache suficiente ou aloca dinamicamente depois de ler o valor na entrada... Exste sim, o nome disso é arranjo/vetor de comprimento variável (Variable Length Array ou VLA), e foi introduzido na versão C99 da linguagem C. Mas é necessário ter cuidado ao usar, pois existe um limite de tamanho máximo para alocar um vetor assim, ainda mais se levar em conta que está alocando vetor de um struct que pode ocupar bastante espaço, então o certo nesse caso seria limitar o tamanho de qtd digitado pelo usuário para ir até um valor máximo apenas, ou então usar alocação dinâmica mesmo.
  12. É o típico problema de ficar sobrando um '\n' na entrada padrão (stdin) depois do scanf ler a parte relevante para ele. Veja essa explicação que dei em outro tópico: Uma solução parcial seria colocar um getchar() na linha logo após o scanf só para limpar o '\n'. E um outro citação de post anterior meu que é relevante: Que IDE está usando? A execução não fecha imediatamente, o programa é executado normalmente até o fim, e encerra normalmente, o problema é que quando o programa acaba a janela fecha sem dar tempo para você visualizar o que foi impresso. Várias coisas podem ser feitas, tipicamente iniciantes costumam usar a função system("pause"); antes do fim da função main para pausar o programa antes de fechar a janela.
  13. A quantidade de contatos no arquivo é igual ao tamanho/comprimento do arquivo dividido pelo tamanho/comprimento de 1 contato: fseek(arq, 0, SEEK_END); //Vai para o fim do arquivo size_t quantidadedecontatos = ftell(arq) / sizeof(CONTATO); rewind(arq); //Volta para o inicio do arquivo Aloca o vetor: CONTATO *cttv = malloc(quantidadedecontatos * sizeof *cttv); Ler todos os contatos e guardar no vetor: fread(cttv,sizeof(CONTATO),quantidadedecontatos,arq); Acessa os dados de cada contato usando seu respectivo índice: cttv[0].nome cttv[0].fone ...etc... Aí usa algum algoritmo de ordenação para ordenar os dados no vetor (Insertion Sort, Bubble Sort, Selection Sort, etc). E é basicamente a mesma coisa para escrever todos os dados do vetor no arquivo (lembre-se que nesse caso deve abrir o arquivo em modo de escrita). fwrite(cttv,sizeof(CONTATO),quantidadedecontatos,arq); E não pode esquecer de liberar a memória alocada dinamicamente para o vetor quando não precisa mais dele: free(cttv);
  14. Realmente, fazer ordenação diretamente dentro do arquivo é muito trabalhoso e ineficiente, faz muito mais sentido colocar todos os contatos em um vetor na memória, ordenar o vetor, e no fim escrever todos os contatos ordenados no arquivo novamente. Você deve criar um vetor com tipo CONTATO (dependendo da quantidade aloca dinamicamente), e ao invés de ler apenas 1 contato no fread você lê todos os contatos do arquivo de uma vez e guarda nesse vetor. Aí pode usar um algoritmo de ordenação para ordenar os dados no vetor.
  15. A versão C++17 da norma do C++ incluiu na linguagem a biblioteca padrão <filesystem> para lidar com sistemas de arquivos, e oficialmente deve usar std::filesystem::copy para copiar diretórios e arquivos. https://en.cppreference.com/w/cpp/filesystem/copy E no seu caso usaria assim: std::filesystem::copy("/dir1", "/dir3", std::filesystem::copy_options::recursive); Ou seja, setando a flag das opções de cópia como recursivo, para copiar o diretório dir1 e todo seu conteúdo, incluindo as subpastas, para o dir3 (também cria o dir3 caso não exista). O problema é que isso é algo relativamente novo, ainda sendo implementado nas versões mais recentes dos compiladores, então dependendo do compilador que você está usando, e de sua versão, ainda há algumas inconsistências, e o modo de uso pode variar um pouco de um para o outro. No MSVC (microsoft) por exemplo a biblioteca filesystem ainda consta como experimental, então precisa usar a biblioteca <experimental/filesystem> e std::experimental::filesystem , isso porque na versão C++14 da norma ela já constava como experimental, mas o MSVC ainda não se adaptou a C++17 completamente. (O mesmo é válido para o GCC com flag -std=c++14 .) Já no GCC com flag -std=c++17, pode usar a bibliteca normalmente sem "experimental", mas para versões do GCC anteriores ao GCC 9 também é necessário linkar a biblioteca usando -lstdc++fs, mas a partir do GCC 9 não é mais necessário. E para usar filesystem em versões anteriores da linguagem é necessário usar a biblioteca não padrão Boost, que é uma biblioteca onde muitos recursos extras para a linguagem são implementados, sendo que alguns, como aconteceu com a biblioteca filesystem, podem acabar sendo adicionados como parte da biblioteca padrão do C++ em versões futuras da norma da linguagem. (Note que também poderia usar filesystem do Boost nas versões mais recentes da linguagem, então é uma outra alternativa.) Também existem outras opções, como a biblioteca não padrão dirent.h que também está disponível em vários Sistemas Operacionais, ou no caso específico do Windows também poderia usar os recursos da Win32API (windows.h). Outros links relevantes: https://stackoverflow.com/questions/33149878/experimentalfilesystem-linker-error https://www.boost.org/ https://stackoverflow.com/questions/19944753/linking-compiling-a-program-that-uses-boost-filesystem-hpp
  16. O erro é por que não existe essa pasta 'caminho', você deveria ajustar para o seu caso colocando a pasta e nome do arquivo que vai usar no seu programa. Então isso vai depois que define o nome do arquivo de saída, que inclui data e hora se me lembro corretamente de outro tópico. adicionado 49 minutos depois Obs: Esse programa inteiro poderia ser substituído por um shell script simples assim: FILE1=$(date +/caminho/da/pasta/de/ArqsJuntosData%FHora%Hh%Mm%Ss.csv) FILE2=$(ls -1 *.csv | head -1) head -1 $FILE2 > $FILE1 FILES=$(ls *.csv) tail -qn +2 $FILES >> $FILE1 mv $FILES /caminho/da/pasta/de/backup 1- FILE1 é o nome do arquivo com tudo junto 2- FILE2 é o primeiro arquivo CSV encontrado na pasta atual 3- Pega o cabeçalho do FILE2 e põe no FILE1 4- FILES são os nomes de todos os arquivos CSV na pasta atual 5- Adiciona o conteúdo de todos os arquivos CSV na pasta atual ao FILE1 6- Move todos os arquivos CSV da pasta atual para a pasta backup
  17. O seu arquivo CSV usa com vírgula ou ponto-e-vírgula como separador de colunas? Assumindo que use ponto-e-vírgula, usando a linguagem C seria algo desse tipo: FILE *arq = NULL; arq = fopen("caminho/arquivodesaida.csv", "w"); //cria e abre o arquivo if (!arq){ //checa se falhou na tentativa de abrir o arquivo perror("Erro"); exit(1); } //Imprime o cabeçalho no arquivo fprintf(arq, "Nome;Sobrenome;Empresa;Cargo\n"); fclose(arq); //fecha o arquivo Assim cria o arquivo com o cabeçalho na primeira linha. Aí se vai usar o programa tail para pegar o conteúdo dos arquivos, ainda precisa usar >> para anexar fim do arquivo, ao invés de > que sobrescreveria o conteúdo do arquivo. tail -qn +2 arquivo1.csv aquivo2.csv arquivo3.csv >> caminho/arquivodesaida.csv
  18. Se for manter usando apenas os comandos do Linux ao invés dos recursos da linguagem C, uma opção seria usar o programa head primeiro com argumento -qn 1 para pegar apenas a primeira linha de 1 dos arquivos, e no tail usaria >>, ao invés de >, para anexar ao fim do arquivo ao invés de sobrescrever/apagar o conteúdo anterior do arquivo. head -qn 1 arquivo1.csv > saida.csv tail -qn +2 arquivo1.csv aquivo2.csv arquivo3.csv >> saida.csv Assim o primeiro comando pega apenas a primeira linha do arquivo1 e põe na saida. E o segundo comando anexa à saída os conteúdos dos 3 arquivos a partir da segunda linha de cada um.
  19. void main() é um erro... A função main deve ser do tipo int, e nela é retornado 0 para indicar para o sistema que o programa foi encerrado corretamente, sem erros ou interrupção inesperada, ou então retorna um valor diferente de 0 para indicar que algo anômalo ocorreu durante a execução do programa. No C++ não há diferença entre int main() e int main(void), em ambos os casos está explícito que a função não recebe nenhum parâmetro. Mas em C quando não é indicado nenhum parâmetro no protótipo da função significa que ela pode ser chamada com qualquer quantidade de parâmetros ou sem nenhum parâmetro, então se tiver uma função como: void func(){ } Poderia chamá-la passando quaisquer parâmetros: func(1, "abc", 2.5); Ou sem nenhum parâmetro: func(); Mas especificando void como o único tipo do parâmetro da função, só é possível chamar a função sem passar nenhum parâmetro: void func(void){} //só podemos chamar essa função assim: func(); Logo, é considerado mais tecnicamente correto sempre colocar void quando a função não recebe parâmetros. Portanto em C a diferença é que int main() pode ser chamado com qualquer quantidade de parâmetros, enquanto int main(void) só pode ser chamado sem parâmetros. Sempre usar int main(void) é a pratica recomendada quando não usar parâmetros na função main. Obs: É usado main com parâmetros quando deseja-se pode passar argumentos durante a chamada do executável do seu programa, tipicamente o protótipo usado é: int main(int argc, char *argv[]) Onde, argc indica a quantidade de argumentos recebidos, e argv é um vetor de strings contendo cada argumento, sendo argv[0] o próprio nome do arquivo executável do programa. Pesquise na internet para entender mais sobre isto.
  20. Não use scanf, isso é da linguagem C. No C++ deve usar cin para entrada de dados, que deve ser o que você aprendeu.
  21. Por causa do modo como você fez seu programa isso é uma pergunta sobre linux não de linguagem C. Você está usando a função system() para executar o programa cat do linux para concatenar os arquivos, mas para pular linha você poderia mudar para o programa tail com parâmetro -qn +2 para pular para a segunda linha de cada arquivo. Por exemplo: tail -qn +2 arquivo1.csv aquivo2.csv arquivo3.csv > saida.csv Vai concatenar os 3 arquivos na saída sempre começando a partir da segunda linha. https://superuser.com/questions/62970/unix-cat-starting-from-line Note que isto faria com que não tenha nenhum cabeçalho na saída, nem mesmo o primeiro cabeçalho. Então se fizer assim terá que fazer algo a mais se quiser colocar o cabeçalho no começo do arquivo.
  22. Posta como está o código agora.
  23. Mude essa linha: copia[i] = entrada[j]; Para: copia[j] = entrada[i]; Assim só vai copiar a letra da entrada que já está minúscula.
  24. Já fez impressão de matrizes? Seria como imprimir apenas a metade triangular inferior de uma matriz. Pense em cada degrau da escada como uma linha, e cada letra do nome como uma coluna. O primeiro for é responsável por contar as linhas apenas (logo, nele é impresso o caractere nova linha '\n'), e o segundo for é responsável por contar as colunas de cada linha (logo, nele são impressas as letras do nome). O nome tem tam letras então haverão tam linhas, e o número de colunas impressas em cada linha é igual ao número da linha (= índice da linha + 1) atual.
  25. Sim, no meu código estou assumindo que o arq_ent não foi fechado com fclose(), aí uso rewind para voltar ao início do arquivo e aí é só ler dês do início com fgets() novamente. Talvez você também deva adicionar esse alltrim() e Converte() ao meu código para processar o texto do registro...

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...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!