Ir ao conteúdo
  • Cadastre-se

arfneto

Membro Pleno
  • Posts

    6.202
  • Cadastrado em

  • Última visita

Tópicos solucionados

  1. O post de arfneto em Cabo de rede CAT6e dando mensagem de não conectado foi marcado como solução   
    Deve ser mesmo o cabo.
     
    Para ninguém dizer que não testou coloque o PC perto do roteador e teste com outro cabo.
     
    Não precisa de cabos Cat6E para essas velocidades. 5E estaria ok, desde 1999. Verifique o encaixe desses conectores também. 
     
    Cabos de rede não devem ter mais de 5m. Esse é um cabo que vai direto ao roteador?
  2. O post de arfneto em Diferenças entre C e C++ para trabalho de curso técnico foi marcado como solução   
    A API do Windows está disponível em C. Windows foi escrito em C, como foi o Unix, o Linux (clone do Unix), o Android (Linux) e o MacOS (tmbém derivado de Linux).
     
    C++ foi criada a partir de C, usando um compilador que gerava C a partir de C++, no mesmo lugar em que trabalhavam os criadores de C e do Unix, e alguns ainda estavam lá (1985). 
     
     
    Não tem não. Você pode programar em C++ usando free functions e ignorar todo e qualquer conceito de objeto. O paradigma mais provável da  da linguagem é "abstrações a custo zero", como dizia o prof. Stroustrup, que criou a linguagem.
     
    Mas C++ incorpora por definição todas as construções de C e inclui a noção de classe e todo o suporte a objetos, incluindo herança, polimorfismo e sobrecarga, inclusive de operadores. E meta-programming, e co-rotinas. E a biblioteca STL que seria como a stdlib de C mas com uma quantidade ignorante de recursos, incuindo uma biblioteca com mais de 100 algortimos, e incluindo suporte a containers como listas, filas, conjuntos, pilhas, mapas e tal.
     
    É uma linguagem enorme.
     
     
  3. O post de arfneto em por que usar arquivos "HEADER.H" foi marcado como solução   
    Isso é o que tem em um header. É o esperado. Raramente tem código. Talvez a principal razão de usar um header file é não ter que enviar o fonte para todo mundo que usa o header... 
     
     
    Mais fácil encontrar a fonte do lado do Linux. (Extra oficial) pode ver nesse endereço algo https://github.com/bminor/glibc ou em https://github.com/lattera/glibc
     
    Mas a ideia é justamente o contrário: usar o header e as funções e escrever seus programas a partir dessas ferramentas.
     
     
     
  4. O post de arfneto em O que essa informação significa no roteador? foi marcado como solução   
    nada respondeu sobre o resto, mas o que importa na questão é isso:

    Se aparece assim só tem a ver com esse aparelho... Não ia mudar as duas pontas do outro lado ao mesmo tempo 😉 
     
     
    pois é.
  5. O post de arfneto em Como criar uma rede Bridge, Windows XP e 11 no Virtual Box foi marcado como solução   
    @Adriano Freitas47 apenas olhe os endereços. Modo bridge é o padrão. Não precisa fazer nada.
     
    Se está em modo bridge então sua placa de rede pode receber endereços direto do servidor DHCP de sua rede. E lógico que vai ter um endereço na mesma rede de seu host.
  6. O post de arfneto em Criação de uma rede lan em apartamento foi marcado como solução   
    Em geral o mais simples é medir antes. E usar um meio termo entre a realidade dos dispositivos e cabos e a cobertura do rádio. Considere que as antenas não são direcionais então não deve ser bom colocar o telefone na borda do site porque vai levar mais sinal pra fora do site e menos onde pode precisar dele. num corredor comprido por exemplo os aparelhos ficariam a 1/3 e 2/3 do caminho e não um em cada ponta.
     
    Use um celular e um aplicativo tipo o wifi analyzer que tem para os telefones da frutinha e do robo. E para Windows se for usar um laptop. E aí coloque esse aparelho de prova em alguns dos locais possíveis e simplesmente veja a cobertura com o celular. E anote. No geral se acaba colocando perto de alguma TV para usar um cabo curto entre a TV e o roteador e porque mesmo na falta de moveis adequados o roteador pode ficar pendurado lá atrás da TV já que muitas vezes elas ficam em um suporte ou ponto elevado. Claro, se tiver um escritório onde tenha computadores e impressoras de rede deve considerar. Apenas junte o máximo de informações antes de perder tempo carregando coisas. Use apenas 1 roteador e um aparelho portátil.  Claro que não precisa de internet, certo? A preocupação é só com a cobertura do wifi e o comprimento dos cabos.
     
     
    Para as velocidades em uso CAT6 só vai dar trabalho e despesa. Esses cabos são mais duros e mais grossos, mais difíceis de passar por dutos. CAT5e é garantido para até 95+5m de cabo em situações normais. E se estiver tipo em uma fábrica com grande interferência CAT6 provavelmente não vai resolver também, mas sim um cabo blindado, que pode ser Cat5E mesmo.
     
    Levar um cabo desde a distribuição fica logo impossível e gasta muito cabo e dutos. É um pesadelo a menos que more em um lugar em forma de estrela e consiga por um rack bem no centro. A noção de rede estruturada existe por isso. Use esses roteadores como roteadores -- e switches que são --- e coloque switches adicionais apenas onde faltarem portas. 
     
    Não ligue esses roteadores em cascata, sempre em paralelo enquanto possível
     
    Esse switch é ok mas em uma casa pode ser melhor 2 x 8 portas do que 1 x 16. Pense na topologia do lugar e na posição dos dispositivos antes de comprar qualquer coisa. Vai ter 3 portas em cada um desses roteadores. Pode ser pouco. Se acrescentar um switch de 5 ou 8 portas em locais adequados pode resolver bem.
     
     
    POE é uma mão na roda se precisar. Não é uma pretensão, é uma necessidade que aparece. Imagine um roteador ou AP no fundo da casa atrás da piscina e como seria legal poder legal energia e rede em um cabo só...
     
    Gerenciável é uma solução quando precisa gerenciar algo... Redes virtuais (VLAN) é o mais comum, segmentar o tráfego, controlar broadcass, segurnaça.
     
     
  7. O post de arfneto em Acessar uma rede através de outra! foi marcado como solução   
    Endereços de rede terminam em 0. Esse é um host, talvez o gateway da rede certo? DHCP não faz pare disso. A rede é 192.168.3.0
     
    Esse é outro host. A rede é 192.168.0.0/24
     
     
    Da rede 2 pode acessar a rede 1, é a rede acima dela. Pode precisar de rotas. O contrário não, ou ao menos não de um modo produtivo.
     
    Não deve ligar redes internas via WAN. Esse é seu problema,
  8. O post de arfneto em Adpatador Wireless USB ou Placa PCI Wireless foi marcado como solução   
    Compre algo com wifi6 ou wifi6E, AX não AC. 
     
    Dependendo do barramento USB em sua máquina pode não fazer diferença. Mas os limites de banda de PCIx ou USB3X são muito mais altos que o necessário para o potencial dessas placas de todo modo.
     
    USB tem o lance de ser portável para outras máquinas e pode ser um argumento.
  9. O post de arfneto em Qual é o melhor Cabo Cat para internet 600Mb foi marcado como solução   
    Não deve fazer a menor diferença. Mas se for mudar enenda que esses cabos são mais duros e mais grossos e como parte do padrão 6 tem uma canaleta plástica dura dentro. Se vai passar por um duto considere que pode dar mais trabaalho, e caber menos cabos. Noe que deve usar conectres CAT6 também ou não faria muito sentido. De todo modo não precisa disso, porque cabos Cat5E são garantidos para até 1000mbps, bem mais que 600, e provavelmente seus equipamentos não funcionam a mais de 1000 também. Isso para situações de não ter muita interferência e até 95+5 metros de cabo.
     
     
    Antes de gastar temp e dinheiro verifique o que o sistema reporta para essa conexão entre o roteador e o pc. E se puder TESTE com algum outro dispositivo na rede. Antes de se preocupar com a internet deve estar absolutamente certo de que a rede local está ok. Você pode precisar e ter uma ree local a 10.000mbps e estar ok com um link de de 200 mbps para a internet. Nada tem a ver uma coisa com a outra.
     
  10. O post de arfneto em Não sei que roteador devo comprar para conseguir usar 800+ mbps no meu pc. foi marcado como solução   
    800mbps é bem menos que 1000 mbps então qualquer roteador que tenha portas gigabit serve. Se vai usar wifi use qualquer um que tenha wifi6 ao menos. Nos últimos tempos comprei vários da marca tp-link modelo AX12, 1500 mbps em wifi e AX53, 3000 mbps em wifi, e nenhum deu qualquer tipo de problema até agora.
  11. O post de arfneto em Troca do modem CLARO foi marcado como solução   
    Em que cidade está isso? Parece tão estranho. Explico: tenho 3 contas na CLARO em cidades diferentes. Nessas quando há troca de firmware ou por alguma razão precisa trocar o modem, já no primeiro acesso vem uma tela dizendo que é preciso colocar uma nova senha e não consigo passar adiante sem isso. E o usuario original é CLARO_XXXXXX onde esse XXXXXX vem dos últimos 6 dígitos do endereço MAC do modem.
     
     
    Se colocar em modo bridge --- ponte --- o modem vira isso, uma ponte, apenas um conversor de mídia. E não consegue acessar nada porque ele não faz mais parte da rede.
     
     
  12. O post de arfneto em Modem Claro e roteador tplink com redes diferentes e funcionando como servidor d foi marcado como solução   
    Não há nada de especial nesse caso, mas é curioso no mínimo:
    qual a razão de usar tal máscara /27? .224 limita a rede a 32 endereços. são redes distintas para sala e quartos. Isso quer dizer que coisas simples como transferir mídia --- como um filme --- de um celular ligado no wifi numa rede para a outra pode ser complicado ou impossível vai ter uma perda grande de banda na segund rede por causa do múltiplo NAT. Pode chegar a uns 40% claro que vai precisar de DHCP na segunda rede. comparilhamento de impressoras ou arquivos é um inferno automação outro pesadelo  
    com as limitações de que falei, mas funciona.
     
     
    bridge é isso: ponte. Só vai perder. Perder portas ethernet, antenas, cobertura wifi, banda wifi.
     
     
    Rede IP é uma coisa, rede ethernet é outra. Wifi é outra. wifi também é ethernet mas é um subconjunto da rede ethernet
     
    No geral você quer uma única rede IP, com um único gateway padrão, o modem da operadora. E pode ter tantas redes wifi quanto precise.
     
     
    Isso não mexe no wifi da claro de modo algum.  
     
    Não deve usar roteadores ligados via WAN no roteador principal. Algumas das razões eu já expliquei acima. É comum fazer isso, a ponto de ser visto como normal, mas não é adequado.
     
     
     
    Não precisa desligar DHCP no segundo e é melhor mesmo não fazer isso, no mínimo por redundância e menor latência no DHCP. Deve excluir esse endereço .2 da faixa de DHCP de todo modo. 
     
    Não é preciso configurar como AP. E dependendo do roteador em uso não deve mesmo, porque alguns desabilitam as portas ethernet quando assim configurados, e esperam uma simples conexão pela WAN com o sinal para o wifi.
     
     
  13. O post de arfneto em Preciso fazer um download automático de uma tabela excel a cada hora foi marcado como solução   
    @Nosila19 Sim. pode usar automação e escrever um script para fazer isso. Então coloca na agenda do sistema para rodar nos horários determinados e pronto.
     
    Pode tentar AutoIt ou um script em Python usando pyautogui. Uso algo assim para reprogramar e reiniciar roteadores.
  14. O post de arfneto em Placa de rede internet 10 ou 100 mb/s foi marcado como solução   
    Não entendi. Esse cabo da foto é o que comprou?
     
     
    Não existe placa de rede internet. Só placa de rede. Não precisa de inerne para ter rede. Mas precisa de rede para ter internet. Mesmo que sejam 2 pontos só.
     
     
    Isso quer dizer que já fez o simples e testou o mesmo computador com os outros dois cabos e os outros dois computadores com esse cabo certo? E qual foi o resultado?
     
     
    Um cabo CAT6 não vai fazer a menor diferença. Só gastou dinheiro. Sua placa de rede vai até 1Gigabit, o padrão de 1999. E para esse padrão a categoria 5 foi revista e desde enão tem o cbos Cat5E, que são perfeitamente adequados para essa velociade, em 95+5 metros. Ou uma velocidade até bem maior se forem cabos curtos e não estiver em um ambiente de muita interefrência.
     
    O cabo da foto parece folgado e está claramene fora do padrão, E dá pra imaginar que os cabos tem duas pontas e mostrar uma só de nada adianta. Que pino está ligado em que pino seria a pergunta normal a fazer. A primeira, E os testes de que falei. 
     
    Esses são os padrões. 
     
    Para curtas distâncias qualquer um deve servir, mas não é esperto divergir desses dois esquemas.
  15. O post de arfneto em Velocidade de conexão menor do que o plano oferece foi marcado como solução   
    não é bem assim.
     
    Placas não "suportam internet". Sua placa nem deve estar conectada a internet mas sim a um roteador. Se desligar o roteador da internet a placa e a rede continuam funcionando.
     
    A velocidade da placa é dada pelo chipset instalado, nada tem a ver com internet ou plano de dados.
     
    Sua placa tem um chipset de rede embutido, e esse suporta conexões gigabit. ou FE a 100 mbps, ou mesmo a 10 mbps. 
     
    Mas nada tem a ver com o que sua placa suporta. Essa placa tem 2 slots x1 e um slot x16. Isso quer dizer que pode instalar placas de rede nos 3. Pelo formato pode instalar 2 placas 2500G nos slots x1 e uma placa 10.000G no X16. Nada tem a ver com internet.
     
    Essas propriedades são um limite e não uma definição. Você usa isso para LIMITAR uma conexão abaixo da velocidade que seria normal.
     
    E precisa ver o que tem do outro lado do cabo, os cabos, os conectores e tal.
  16. O post de arfneto em Ler um texto e transformá-lo em um Array Bidimencional foi marcado como solução   
    F7: bidimensional é a grafia correta, como em dimensão.
     
    Seu programa lê lexto e mostra texto, então mostre texto aqui e não essas imagens gigantes copiadas de sua tela. Ajude outros a ajudarem você: poste um mínimo arquivo de teste que mostra o que quer fazer, e um exemplo do seu problema acontencendo, em texto.
     
    Isso seria algo melhor que as duas telas gigantes:
     
    entrada.txt
     
    Pokemon Megaman Megamente Kyrbi Kaku
    Porque assim alguém pode copiar isso e colar em um arquivo e tentar reproduzir seu problema em minutos.
     
    E poste a saída do seu programa. Mas nem posso postar aqui a saída do programa que mostrou, porque ele sequer compila direito ainda.
     
    Sobre o programa:
     
    Quase todo o código está comentado. Qual o propósito?
     
    Esse comando, por exemplo:
     
                strncpy(                 &Text_Read[i][p],                 (char*)fgets(                     ((char*)getchar()), 1 * sizeof(char),                     ((FILE*)printf("%c", *(&One_Letra2)))),                 1 * sizeof(char));
    é algo que deve muito evitar, em especial se está começando a programar nessa linguagem. No caso de seu programa está errado mesmo, mas é algo que deve evitar mesmo que saiba o quie está fazendo.
     
    São muitas coisas que podem dar errado, isso se a ideia em si estiver certa.    
     
    `fgets` pode dar errado. Não está sequer testando e já passa o valor como argumento para `strncpy`. Não é boa ideia. leia o manual: `printf` retorna um `int`. Qual seria o sentido de converter para `FILE~`, algo que nem é suposto para ser tratado pelo programador? o operador `sizeof` retorna 1 para `char`. Então tudo isso seria para de algum modo copiar uma letrinha e um `NULL`?  pra que `strncpy`? Isso é algo que poderia ter comentado... Não seria melhor ver agora o tamanho da string e alocar do tamanho certo e copiar usando simplesmente strcpy? Está certo de entende o que é `FILE*`? Tem um livro? Mais sobre o código
     
      Seu programa tem muitos dos erros comuns que vemos aqui, e então vou copiar de uma lista que tenho e listar umas coisas que provavelmente deve evitar
     
    Não use acentos em nomes de variáveis ou comentários. Evite mesmo em strings  a menos que o enunciado exija. Não vai aprender nada e só vai ter problemas. Mais ainda evite usar Unicode e coisas como emojis. Nada acrescenta ao código e não sair em muitas telas, ou vai sair outra coisa. E se imprimir o programa pode não sair nada ou algum lixo. Evite comentários como "main é a função principal" ou "declaração de variáveis" ou coisas óbvias desse tipo. Comente o porque está fazendo algo, escreva para você mesmo no futuro, tipo daqui a 2 dias quando pode não lembrar para que era aquele ponteiro, por exemplo. evite retornar void de funções: em geral é um desperdício. E muitas vezes um erro. Use argumentos nas funções, e retorne algo delas. É mais esperto e expressivo. Use alguma ordem em suas funções, como a ordem alfabética por exemplo. Vai gostar disso quando seu programa tiver 50 funções ao invés de umas poucas. Muitos IDE mostram uma lista das funções, em geral na ordem em que foram declaradas, de modo que você pode clicar no nome e o editor vai direto para o código, mas se estiverem em ordem é claro que você só ganha. Nunca use variáveis globais. Isso é um pesadelo e sempre vai cair na sua cabeça. Em geral é proibido em empresas e escolas. Não declare NADA que use memória  fora de main(). Não declare mais que uma variável por linha. Não acrescenta nada e só dificulta a leitura. Inicialize todas as variáveis. Nunca leia valores do teclado para alimentar seu programa antes dele estar rodando. Só vai te atrasar e não acrescenta absolutamente nada. Use constantes, use funções que retornam a estrutura preenchida. Leia de arquivos: é trivial em C. Ao terminar os  testes aí sim incorpore a leitura. Um programa interativo é chato para testar. Durante o desenvolvimento ninguém quer interagir com o programa. Nunca escreva um programa interativo, mesmo que seja o objetivo final. Alinhe seu código com algum critério. Evite longas linhas com mais de 60 colunas. Use nomes significativos para as variáveis e fuja de coisas como aux, aux1 e aux2. E não use nomes de variáveis enormes porque em uma expressão fica muito difícil de ler. não use fflush(): isso só está definido para fluxos de saída. Em alguns compiladores pode até funcionar, mas é um sinal de fez algo errado e não sabe como consumir os dados. não use setbuf a menos que saiba a razão de fazer isso. streams usam buffers porque é esperto e não o contrário. Não existe "lixo de teclado": necessidades como de flush() na entrada indicam apenas que não entendeu bem o que está lendo e o que é a entrada via teclado, free form: o usuário pode digitar qualquer coisa e é o seu programa que tem que se virar O teclado tem ao menos 105 teclas de liberdade e o usuário pode digitar qualquer coisa em qualquer ordem. evite ler do teclado a menos que seja o objetivo do problema. Ler de arquivos é muito mais simples, seguro e fácil de reproduzir. Não há razão para ficar parado em frente a tela minutos inventando nomes de campos e coisas assim: o efeito é que vai acabar não testando direito porque é difícil controlar e repetir testes. Não misture entrada de dados ou formatação com a apresentação dos dados ou a lógica do programa, Isso é um desastre para manutenção e desenvolvimento. Um printf() de 6 linhas é **muito**, mas muito melhor que 6 printf() de 1 linha. E se só vai mostrar o texto puts() é ainda melhor e dezenas de vezes mais rápido que uma série de printf(). Escreva seu programa em torno dos dados.
     
    O que quer criar é o que todo programa `C` recebe: uma lista de strings. Esse é o protótipo normal de `main`:
     
            int main( int argc, char** argv);  
    E são os argumentos que seu programa --- e todo programa `C` recebe: uma lista de strings com o que o usuário digitou na linha de comando. O primeiro argumento é sempre o nome do programa. Isso deveria ser ensinado no PRIMEIRO programa do aluno, aquele tal `Hello World`. Mas não sou eu quem ensina ou decide isso 😄  
     
    Os dados:
     
    o que o programa recebe? O que o programa cria?
     
    O programa recebe o nome de um arquivo e cria uma lista de strings. Igualzinho ao que o sistema faz para todo programa `C`, como eu disse.
     
    Então faça igual, já que dá certo para todo programa vai dar certo para o seu:
     
        char nome_arquivo[250];     const char[] arquivo_padrao = "entrada.txt";     typedef struct     {         unsigned n_linhas; // quantas linhas no arquivo?         char**   L; // o vetor de linhas     } Array;
     
    Já seria um bom começo:
     
    tem onde ler o nome do arquivo. tem um nome padrão para o caso do cara não digitar nada. E assim para testar não tem que ficar digitando nomes de arquivo duzentas vezes. E pode ter arquivos de teste já separados. na saída vai ter o tal `Array` onde diz que o texto carregado tem n_linhas e as linhas vão estar todas arrumamindas no vetor L.    Parece simples assim.

      E 
     
      #include <stdio.h> typedef struct {     size_t N;  // quantas linhas no arquivo?     char**   L;  // o vetor de linhas } Array; int main(int argc, char** argv) {     char nome_arquivo[250];     const char arquivo_padrao[] = "entrada.txt";     return 0; }
     
    já compila e roda. Claro, só para apoio moral porque não faz nada.
     
     
     
    São mesmo duas dimensões. De todo modo entenda que C sequer tem arrays multidimensionais, como FORTRAN. Só existe array. Mas tem array de array, array de array de array e assim por diante...
     
    Então se declarar o simples
     
    char** Linha;  
    e gravar seu arquivo lá, vai ter a linha 0 em Linha[0], a linha 3 em Linha[3] e tal.
     
    Linha[0] é o que? char*, assim foi declarado. Então
    Linha é char** *Linha é char*, Linha[0] é char* **Linha é uma letrinha, char, assim foi declarado. assim sendo, Linha[12][0] é a primeira letra da linha 13 a ultima letra da terceira linha seria o que?   
    Seguindo com o exemplo que mostrei:
     
    #include <stdio.h> #include <stdlib.h> typedef struct { size_t N; // quantas linhas no arquivo? char** L; // o vetor de linhas } Array; int main(int argc, char** argv) { char nome_arquivo[250]; const char arquivo_padrao[] = "entrada.txt"; char* uma = "uma linha"; char* outra = "outra linha"; Array exemplo = {.L = NULL, .N = 0}; printf("exemplo tem %llu linhas\n", exemplo.N); exemplo.L = (char**)malloc(2 * sizeof(char*)); exemplo.L[1] = uma; exemplo.L[0] = outra; exemplo.N = 2; printf("exemplo tem %llu linhas\n", exemplo.N); return 0; }  
    Isso mostra
     
    exemplo tem 0 linhas exemplo tem 2 linhas  
    Mas é claro que vai querer mostrar o que tem dentro do vetor, as linhas, então uma função assim
     
    int ch_mostra(Array*,const char*); // mostra as linhas na tela  
    Seria a popular "mão na roda" e ainda aceita um título pra você não ter que ficar colocando os ultra chatos printf aqui e ali... Seria difícil escrever?
     
    int ch_mostra(Array* arr,const char* msg) { if (arr == NULL) return - 1; // sem linhas if (msg != NULL) printf("%s", msg); printf(" Vetor tem %llu linhas\n", arr->N); for (size_t i = 0; i < arr->N; i += 1) printf("#%llu\t\"%s\"\n", i, arr->L[i]); printf("\n******\n\n"); return 0; }  
    10 linhas está ok. 
     
    E mudando o programa aí de cima
     
    #include <stdio.h> #include <stdlib.h> typedef struct { size_t N; // quantas linhas no arquivo? char** L; // o vetor de linhas } Array; int ch_mostra(Array*,const char*); // mostra as linhas na tela int main(int argc, char** argv) { char nome_arquivo[250]; const char arquivo_padrao[] = "entrada.txt"; char* uma = "uma linha"; char* outra = "outra linha"; Array exemplo = {.L = NULL, .N = 0}; ch_mostra(&exemplo, "[array vazio]\n\n"); exemplo.L = (char**)malloc(2 * sizeof(char*)); exemplo.L[1] = uma; exemplo.L[0] = outra; exemplo.N = 2; ch_mostra(&exemplo, "[array deve ter duas linhas]\n\n"); return 0; } int ch_mostra(Array* arr,const char* msg) { if (arr == NULL) return - 1; // sem linhas if (msg != NULL) printf("%s", msg); printf(" Vetor tem %llu linhas\n", arr->N); for (size_t i = 0; i < arr->N; i += 1) printf("#%llu\t\"%s\"\n", i, arr->L[i]); printf("\n******\n\n"); return 0; }  
    E na tela mostra
     
    [array vazio] Vetor tem 0 linhas ****** [array deve ter duas linhas] Vetor tem 2 linhas #0 "outra linha" #1 "uma linha" ******  
    É melhor escrever em torno dos dados e começar assim.
     
    E sobre a última letra da última linha?
     
    // 'len' = tamanho da ultima linha size_t len = strlen(exemplo.L[exemplo.N - 1]); char ultima = exemplo.L[exemplo.N - 1][len - 1]; printf( "\n\n\tUltima letra da ultima linha: '%c'\n", ultima);  
    E colocando isso no programa
     
    #include <stdio.h> #include <stdlib.h> typedef struct { size_t N; // quantas linhas no arquivo? char** L; // o vetor de linhas } Array; int ch_mostra( Array*, const char*); // mostra as linhas na tela int main(int argc, char** argv) { char nome_arquivo[250]; const char arquivo_padrao[] = "entrada.txt"; char* uma = "uma linha"; char* outra = "outra linha"; Array exemplo = {.L = NULL, .N = 0}; ch_mostra(&exemplo, "[array vazio]\n\n"); exemplo.L = (char**)malloc(2 * sizeof(char*)); exemplo.L[1] = uma; exemplo.L[0] = outra; exemplo.N = 2; ch_mostra(&exemplo, "[array deve ter duas linhas]\n\n"); // 'len' = tamanho da ultima linha size_t len = strlen(exemplo.L[exemplo.N - 1]); char ultima = exemplo.L[exemplo.N - 1][len - 1]; printf( "\n\n\tUltima letra da ultima linha: '%c'\n", ultima); free(exemplo.L); return 0; } int ch_mostra(Array* arr, const char* msg) { if (arr == NULL) return -1; // sem linhas if (msg != NULL) printf("%s", msg); printf(" Vetor tem %llu linhas\n", arr->N); for (size_t i = 0; i < arr->N; i += 1) printf("#%llu\t\"%s\"\n", i, arr->L[i]); printf("\n******\n\n"); return 0; }  
    Que mostra
     
    [array vazio] Vetor tem 0 linhas ****** [array deve ter duas linhas] Vetor tem 2 linhas #0 "outra linha" #1 "uma linha" ****** Ultima letra da ultima linha: 'a'  
    Para que isso? 
     
    Só para mostrar como acessar as letras dentro da estrutura.
  17. O post de arfneto em Acess point intelbras oscilando foi marcado como solução   
    @Veronica Sales Sim, podem ser apenas um dos conectores. Troque os dois. Troque antes a porta no switch onde está conectado. 
     
    O que eu disse sobre um cabo curto e testar na mesa é em resumo colocar o aparelho ligado em uma mesa onde tenha um computador com a pagina de configuração dele aberta, e onde ele possa atrair alguns clientes 🙂  e ver o que acontece. E consultar os logs. Para tentar interceptar uma falha em tempo real.
    Pode usar um script de monitoramento também, que alerte quando ele se desconecta. E pode ver se não coincide por exemplo com o fim do lease do DHCP se usa isso para ele
  18. O post de arfneto em somaxconn não existe? não consigo criar foi marcado como solução   
    siga o exemplo que tem lá na documentação. 
  19. O post de arfneto em Roteador ou Repetidor - Qual a melhor opção foi marcado como solução   
    Cabos Ca5 não são vistos há anos e se sua casa é nova dificilmente alguém usaria esses cabos nos últimos 10 ou 15 anos. Pode ser que simplesmente não usaram as 8 vias para atingir todos os pontos, e com 4 vias apenas não vai conseguir uma conexão a 1000 gbps.
     
    Por outro lado, em distâncias curtas mesmo um cabo cat5 conectaria a 1gigabit se tivesse as 8 vias do cabo conectadas corretamente.
     
     
    Pois é. Não é preciso um cabo CAT6 para essa modesta velocidade de meio gbps. E entenda que a velocidade da conexão na LAN NADA tem a ver com a velocidade contratada para acesso a internet. Você pode ter e precisar de uma rede a 10 ou 40 giga e não ter sequer acesso a internet na rede por questões de segurança, por exemplo.
     
    Para distâncias curtas e não tendo uma grande  fonte de  interferência no caminho dos cabos, um cabo CAT5e vai até 2.5 ou mesmo 5 gbps. 
     
     
    5GHz é uma frequência de wifi. Nada tem a ver com a internet. Como o alcance das antenas nessa frequência é bem modesto um sinal de 5GHZ não é bom candidato a um repetidor. Seria o caso de uma rede mesh mas para isso rodar bem o ideal é usar vários POD que possam ser conectados via cabo e você volta ao mesmo problema.
     
    Sugiro rever os conectores de sua rede e verificar se tem todos os sinais conectados nos terminais.
  20. O post de arfneto em como compilar um C com libmbp.h e imghelpers.h foi marcado como solução   
    salvaImagem("saida.bmp", R, G, B, c, l);  
     
    Com seis ou tres parâmetros, não parece bom. O que eu tentava dizer nos outros posts é que é muito mais conveniente usar encapsulamento e escrever em torno dos dados. O simples.
     
    O header não existe sem o bitmap. Os RBG lá são os pixels. nenhum deles existe sózinho. E os dados são só o bitmap. Então só se usa o bitmap.
     
     
    Foi o que eu tentei dizer 🙂 
     
    Uma outra solução
     
    Vou deixar uma quarta opção, algo que já postei aqui.  
     
    Porque outra solução? Para ter exemplo do que estou tentando explicar.
     
    Isso é um bitmap:
     
    typedef struct { BitmapFileHeader h_bmp; BitmapInfoHeader h_info; uint8_t* pixel; } Bitmap;  
    É isso que seu programa deve ver. E o usuário de sua biblioteca deve ver. E pode ser você mesmo. Não é esperto expor os aspectos internos, coisas que já estão embutidas, coisas que você pode querer mudar depois e vai ter então que mudar as chamadas em 2 mil lugares.
     
    Se o bitmap é isso, e ele é isso, então pode escrever
     
    typedef struct { char header[2]; int32_t fileSize; int32_t reserved; int32_t dataOffset; } BitmapFileHeader; typedef struct { int32_t headerSize; int32_t width; int32_t height; int16_t planes; int16_t bitsPerPixel; int32_t compression; int32_t dataSize; int32_t horizontalResolution; int32_t verticalResolution; int32_t colors; int32_t importantColors; } BitmapInfoHeader; typedef struct { BitmapFileHeader h_bmp; BitmapInfoHeader h_info; uint8_t* pixel; } Bitmap; Bitmap* bmp_copy(Bitmap*); Bitmap* bmp_create(unsigned w, unsigned h); Bitmap* bmp_destroy(Bitmap* bmp); int bmp_fill(Bitmap*, uint8_t, uint8_t, uint8_t); int bmp_grad(Bitmap* bmp); Bitmap* bmp_read(const char* filename); int bmp_setPixel( Bitmap* bmp, int x, int y, uint8_t red, uint8_t green, uint8_t blue); int bmp_to_bw(Bitmap*); int bmp_write(Bitmap* bmp, const char* filename);  
    Para ter um mínimo para testar.
     
    Bitmaps estão na memória e assim o simples é considerar:
    quer criar um bitmap? de que tamanho? Só isso. quer apagar um bitmap? Qual o endereço? Só isso. quer copiar um bitmap? De qual? Só isso. Bitmap* bmp_copy(Bitmap* origem); Bitmap* bmp_create(unsigned w, unsigned h); Bitmap* bmp_destroy(Bitmap* bmp); quer colocar uma cor em um pixel?  int bmp_setPixel( Bitmap* bmp, int x, int y, uint8_t red, uint8_t green, uint8_t blue);  
    Não é só isso? Então a gente não escreve mais que isso.
     
    int bmp_fill(Bitmap*, uint8_t, uint8_t, uint8_t); int bmp_grad(Bitmap* bmp); int bmp_to_bw(Bitmap*); bmp_fill é o simples para testar e preenche todo o bmp com a cor
    bmp_grad era pra exemplo. Cria esse bitmap:

    Escrevi isso só porque é simples e é legal de testar a transição das cores.
     
    O código está logo abaixo e é trivial.
     
     
     
     
     
     
    bmp_to_bw() é a função aqui do tópico. Então o simples seria o que? Pega o endereço do bitmap vai lá e transforma. inline. O gradiente fica assim
     
    E assim dá para ver os 256 tons de cinza em cada cor e comparar com o de cima...
     
     
     
     
     
     
     
     
    Ler / gravar
     
    Bitmap* bmp_read(const char* filename); int bmp_write(Bitmap* bmp, const char* filename);  
    Isso é mais simples. Quer ler? De onde? Quer gravar? Para onde?
     
    Assim é mais fácil de consumir a API. Veja:
     
    Bitmap* a_test = bmp_create(1024, 768); bmp_fill(a_test, 255, 0, 0); //vermelho bmp_write(a_test, "red.bmp"); bmp_destroy(a_test);  
    Esse trecho cria um bmp 1024x768, pinta de vermelho e grava no disco e apaga o bitmap da memória
     
    EXEMPLO
     
    Esse programa usa todas as funções e gera vários arquivos
     
    #include "bitmap.h" int main(void) { const int W = 1024; const int H = 768; // arquivos de teste const char* red = "red.bmp"; const char* green = "green.bmp"; const char* blue = "blue.bmp"; const char* blue_copy = "blueCopy.bmp"; const char* gradiente = "gradiente.bmp"; const char* gradiente_pb = "gradiente-pb.bmp"; Bitmap* a_test = bmp_create(1024, 768); if (a_test == NULL) { fprintf(stderr, "\tErro ao tentar criar bitmap\n"); return -1; } fprintf(stderr, "\tCriado BMP %dx%d\n", W, H); int res = 0; res = bmp_fill(a_test, 255, 0, 0); // red fprintf(stderr, "\tbmp_fill retornou %d\n", res); res = bmp_write(a_test, red); fprintf( stderr, "\tbmp_write() retornou %d ao criar %s\n", res, red); res = bmp_fill(a_test, 0, 255, 0); // green fprintf(stderr, "\tbmp_fill() retornou %d\n", res); res = bmp_write(a_test, green); fprintf( stderr, "\tbmp_write() retornou %d ao criar %s\n", res, green); res = bmp_fill(a_test, 0, 0, 255); // blue fprintf(stderr, "\tbmp_fill() retornou %d\n", res); res = bmp_write(a_test, blue); fprintf( stderr, "\tbmp_write() retornou %d ao criar %s\n", res,blue); Bitmap* a_copy = bmp_copy(a_test); fprintf( stderr, "\tbmp_copy() %s [%dx%d], size is %d, para %s\n", blue, a_copy->h_info.width, a_copy->h_info.height, a_copy->h_bmp.fileSize, blue_copy); res = bmp_write(a_copy, blue_copy); fprintf( stderr, "\tbmp_write() retornou %d ao gravar %s\n", res, blue_copy); res = bmp_grad(a_copy); fprintf(stderr, "\tbmp_grad() retornou %d\n", res); res = bmp_write(a_copy, gradiente); fprintf( stderr, "\tbmp_write() retornou %d ao criar %s\n", res, gradiente); res = bmp_to_bw(a_copy); fprintf(stderr, "\tbmp_to_bw() retornou %d\n", res); res = bmp_write(a_copy, gradiente_pb); fprintf( stderr, "\tbmp_write() retornou %d ao criar %s\n", res, gradiente_pb); a_test = bmp_destroy(a_test); a_copy = bmp_destroy(a_copy); fprintf(stderr, "\t[ F I M ]\n"); return 0; }  
    Saída
     
    Criado BMP 1024x768 bmp_fill retornou 0 bmp_write() retornou 0 ao criar red.bmp bmp_fill() retornou 0 bmp_write() retornou 0 ao criar green.bmp bmp_fill() retornou 0 bmp_write() retornou 0 ao criar blue.bmp bmp_copy() blue.bmp [1024x768], size is 3145782, para blueCopy.bmp bmp_write() retornou 0 ao gravar blueCopy.bmp bmp_grad() retornou 0 bmp_write() retornou 0 ao criar gradiente.bmp bmp_to_bw() retornou 0 bmp_write() retornou 0 ao criar gradiente-pb.bmp bitmap APAGADO bitmap APAGADO [ F I M ]  
    Uma implementação mínima
     
    #pragma pack(push, 2) #pragma pack(show) #include "bitmap.h" Bitmap* bmp_copy(Bitmap* orig ) { if (orig == NULL) return NULL; // sem origem // cria a copia Bitmap* cp = bmp_create(orig->h_info.width, orig->h_info.height); if ( cp == NULL ) return NULL; // deu pau // copia os headers, claro cp->h_bmp = orig->h_bmp; cp->h_info = orig->h_info; //copia os pixels uint8_t* de = orig->pixel; uint8_t* para = cp->pixel; // nesse exemplo sao 4 bytes por pixel, 32bpp, certo? for (int32_t i = 0; i < orig->h_info.width * orig->h_info.height * 4; i += 1) *para++ = *de++; return cp; // so isso: retorna a copia } Bitmap* bmp_create(unsigned w, unsigned h) { Bitmap* one = (Bitmap*)calloc(1, sizeof(Bitmap)); one->h_bmp.dataOffset = sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader); one->h_bmp.fileSize = one->h_bmp.dataOffset + (w * h * 4); one->h_bmp.header[0] = 'B'; one->h_bmp.header[1] = 'M'; one->h_info.bitsPerPixel = 32; one->h_info.headerSize = 40; one->h_info.height = h; one->h_info.horizontalResolution = 2400; one->h_info.planes = 1; one->h_info.verticalResolution = 2400; one->h_info.width = w; one->pixel = (uint8_t*)calloc( 1, (size_t)(w * h * 4 * sizeof(uint8_t))); if (one->pixel == NULL) { free(one); return NULL; } return one; }; Bitmap* bmp_destroy(Bitmap* bmp) { if (bmp == NULL) return NULL; if (bmp->pixel != NULL) free(bmp->pixel); free(bmp); fprintf(stderr, "\tbitmap APAGADO\n"); return NULL; } int bmp_fill( Bitmap* bmp, uint8_t red, uint8_t green, uint8_t blue) { if (bmp == NULL) return -1; uint8_t* p = bmp->pixel; for (int32_t i = 0; i < bmp->h_info.width * bmp->h_info.height; i += 1) { // 32bpp *p++ = blue; *p++ = green; *p++ = red; *p++ = 0xFF; // alpha } return 0; } int bmp_grad(Bitmap* bmp) { // preenche a imagem com 3 faixas verticais // em vermelho verde e azul, mas mudando a intensidade // da cor de 0 a 255 a cada linha if (bmp == NULL) return -1; uint8_t red = 0; uint8_t green = 0; uint8_t blue = 0; uint8_t* p = bmp->pixel; for (int y = 0; y < bmp->h_info.height; y++) { uint8_t color_value = (uint8_t)(255 * (double)y / bmp->h_info.height); for (int x = 0; x < bmp->h_info.width; x++) { switch (x / (bmp->h_info.width / 3)) { case 0: red = color_value; green = 0; blue = 0; break; case 1: red = 0; green = color_value; blue = 0; break; default: red = 0; green = 0; blue = color_value; break; } *p++ = blue; *p++ = green; *p++ = red; *p++ = 0XFF; } }; return 0; } Bitmap* bmp_read(const char* filename) { FILE* in = fopen(filename, "rb"); if (in == NULL) return NULL; Bitmap* one = bmp_create(800, 600); if (one == NULL) { fclose(in); return NULL; } size_t size = sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader); size_t res = fread((void*)one, (size_t)(1), size, in); if (res != size) return NULL; // agora calcula o que falta ler size = one->h_info.height * one->h_info.width * 4; // 32bpp uint8_t* area = (uint8_t*)realloc(one->pixel, size); if (area == NULL) { fclose(in); bmp_destroy(one); return (NULL); }; one->pixel = area; res = fread((void*)one->pixel, (size_t)(1), size, in); return one; } int bmp_setPixel( Bitmap* bmp, int x, int y, uint8_t red, uint8_t green, uint8_t blue) { if (bmp == NULL) return -1; uint8_t* pPixel = bmp->pixel; // get address of coordinates of x,y pPixel += (y * 4) * bmp->h_info.width + (x * 4); pPixel[0] = blue; pPixel[1] = green; pPixel[2] = red; pPixel[3] = 0xFF; return 0; } int bmp_to_bw(Bitmap* bmp) { if (bmp == NULL) return -1; uint8_t* p = bmp->pixel; for (int32_t i = 0; i < bmp->h_info.width * bmp->h_info.height; i += 1) { // 32bpp double value = (*p * 0.114) + *(p + 1) * 0.587 + *(p + 2) * 0.299; // isso e antigo // não e ideia minha, mas e uma mistura das cores // e fica ok como branco e preto *p++ = (int)(value); // r *p++ = (int)(value); // g *p++ = (int)(value); // b p++; // alfa não vai mexer, ja que e transparencia } return 0; } int bmp_write(Bitmap* bmp, const char* filename) { FILE* out = fopen(filename, "wb"); if (out == NULL) return -1; size_t res = 0; res = fwrite( &bmp->h_bmp, (size_t)1, sizeof(BitmapFileHeader), out); res = fwrite( &bmp->h_info, (size_t)1, sizeof(BitmapInfoHeader), out); size_t size = (bmp->h_info.width * bmp->h_info.height * 4); res = fwrite( (const void*)bmp->pixel, (size_t)(1), size, out); if (size != res) { fclose(out); fprintf( stderr, "\tbmp_write() write %zd. %zd expected\n", res, size); fclose(out); return -2; } res = fclose(out); return 0; } #pragma pack(pop)  
    Sugiro comparar e entender a razão de escrever em torno dos dados, usar encapsulamento e manter apenas ponteiros como argumentos e retorno. É muito mais simples de ler e de usar. E não expõe coisas internas. Não é vantagem usar 3 ponteiros para cada cor. Mas se usar e colocar como argumento e depois mudar de ideia vai ter que mexer em todas as chamadas em todos os programas que usam isso. 
     
     
     
    Entenda que ao ler precisa de DOIS fread só. E para gravar UM. E não de 2,4 milhões para um bmp de 1024x768....
     
    Um bitmap é um mapa. Vem um pixel atrás do outro.
     
    Veja o exemplo que deixei acima
    O header "bitmap.h" no exemplo seria 
     
    #pragma once #pragma pack(push, 2) #pragma pack(show) #include <stdint.h> #include <stdio.h> #include <stdlib.h> typedef struct { char header[2]; int32_t fileSize; int32_t reserved; int32_t dataOffset; } BitmapFileHeader; typedef struct { int32_t headerSize; int32_t width; int32_t height; int16_t planes; int16_t bitsPerPixel; int32_t compression; int32_t dataSize; int32_t horizontalResolution; int32_t verticalResolution; int32_t colors; int32_t importantColors; } BitmapInfoHeader; typedef struct { BitmapFileHeader h_bmp; BitmapInfoHeader h_info; uint8_t* pixel; } Bitmap; Bitmap* bmp_copy(Bitmap* origem); Bitmap* bmp_create(unsigned w, unsigned h); Bitmap* bmp_destroy(Bitmap* bmp); int bmp_fill(Bitmap*, uint8_t, uint8_t, uint8_t); int bmp_grad(Bitmap* bmp); Bitmap* bmp_read(const char* filename); int bmp_setPixel( Bitmap* bmp, int x, int y, uint8_t red, uint8_t green, uint8_t blue); int bmp_to_bw(Bitmap*); int bmp_write(Bitmap* bmp, const char* filename); #pragma pack(pop)  
  21. O post de arfneto em Estou conectado na Internet, mas não consigo acessar nada foi marcado como solução   
    @Maurício Rockembach Nesses problemas de conectividade tem que ser metódico, quase paranóico, para isolar o problema. E não seriam esses comandos --- flush de cache de DNS ou ProcessIdleTasks ---
    que iriam ajudar.
     
    Reinstalar o sistema pode também não resolver nada. A causa mais comum disso está em roteadores ligados errado, coisas como servidores DHCP perdidos na rede. Há casos em que na ânsia de resolver usuários copiam e rodam listas de uma dúzia de comandos e alguns interferem mesmo na rede. Outro caso é digitar valores errados no formulário de configuração de DNS. Rotas inválidas, gateways inoperantes, uma longa lista.
     
     
    Bom que funcionou. Em muitos casos é só perda de tempo. 
     
     Tem que procurar em sua própria máquina. São comandos simples. Mas tem que ser metódico e saber o que procurar. É um porre isso --- minha opinião.
     
    EXEMPLO
     
    O último que eu vi, numa casa com 4 roteadores, 2 servidores DHCP e uns 30 pontos de rede: uma marcenaria chegou para instalar 2 painéis desses que se usa para colocar TV na parede. Uma das TV tinha um roteador colado nela, um desses AX73 ou similar da TP-Link. Desligaram e desmontaram tudo. Ao final da instalação o dono da casa não viu que o roteador estava desligado. Uma parte dos dispositivos não se conectava com a internet. Às vezes. Redes wifi sumiram e tal. 
    Para resolver ele pesquisou na internet e tal. Aí ligou o aparelho na mesa e usou o aplicativo da fábrica e reiniciou o infeliz para a configuração de fábrica e conectou tudo de volta. E tudo ficou maluco na rede toda.
    Passou a ter um servidor DHCP novo, com gateway inválido e endereços válidos acho que por um dia. Claro que tudo que se conectasse através dele não ia para lugar algum. 
    Só que nem sempre. Pela natureza dos protocolos e pela natureza do rádio a cada vez que reconectava um aparelho ele podia receber endereço de outro servidor e funcionar ok até vencer o intervalo de validade, que é de 5 minutos naquela rede. E aí nova loteria.
  22. O post de arfneto em Soma de valores usando Lista Duplamente Encadeada em C. foi marcado como solução   
    Uma vez resolvida a parte da lista, a soma usa o algoritmo do ensino fundamental (primário): alinha os valores pela direita e soma. Passou de 10 "vai um" e tal. Nada mais.
     
    Como o simples é somar a partir das unidades use os ponteiros a partir do fim da lista. E seja esperto e GUARDE na lista esses ponteiros....
     
    Veja esse exemplo
     
    typedef struct no_ { void* item; struct no_* proxima; struct no_* anterior; } Node; // um no typedef struct { char* nome; unsigned quantos; unsigned maximo; Node* inicio; Node* fim; } Lista;  
    A lista é uma lista de Node, mas tem um total de nós e um ponteiro para o início e para o fim. É disso que você precisa. A menos que queira ficar guardando ponteiros pra todo lado na hora de somar. Em item estariam os dígitos dos números, claro. E pode trocar o void* item por char digito
     
    Há muitos exemplos de lista aqui no forum. Eu por exemplo já postei muitos e pode pesquisar no conteúdo
  23. O post de arfneto em Conexão local sem acesso a rede. foi marcado como solução   
    É muito raro precisar de um cabo crossover hoje em dia. Há décadas os aparelhos detectam isso automaticamente. De todo modo um cabo crossover apenas inverte os pares 1-2 3-6.
     
    O que precisa fazer para usar isso, uma ligação ponto a ponto entre duas máquinas, é configurar manualmente as duas na mesma rede ou ativar um serviço DHCP em uma das pontas.
    Note que ativar o compartiilhamento de conexão a internet de um lado vai implicitamente fazer isso...
  24. O post de arfneto em Telefonia na Nuvem VIVO caindo foi marcado como solução   
    Uma ligação VOIP consome perto de 60/100 kbps. Não é algo assim muito exigente. Telefones VOIP tem interface de 100mbps e sempre dá conta. Muitos tem até uma saída LAN para ligar o computador usando um ponto só. E funcionam.
     
    Esses Grandstream GXP1615 são compatíveis com Poe então basta o cabo de rede.
     
     
    Imagino que tenha um switch PoE ou dois. 
     
    E --- se não fez isso ainda --- separe sua rede local da rede dos telefones. 
     
    O tráfego na LAN pode muito bem congestionar tudo, mesmo sem qualquer relação com a internet ou VOIP. 
     
     
  25. O post de arfneto em Programa de Cadastro de Empresas em C foi marcado como solução   
    Ainda no tópico #3 te disse que não pode escrever assim. Esse valor tam deve ser conhecido em tempo de compilação. Não pode ser um valor lido na hora em que o programa está rodando porque o compilador precisa reservar essa área ao gerar o código.
     
    Se precisa criar na hora deve alocar a memória necessária usando malloc() de stdlib.h. Existe uma extensão para C que admite isso, um troço chamado VLA, mas nunca foi adiante e não irá agora, depois de 50 anos.
      
    // 200, fixo Empresa cadastro[200]; // variavel, tam Empresa* cad = malloc(tam* sizeof(Empresa));  
    Assim é.
     
    Da minha lista de problemas comuns:
    não use comentários com acentos. Podem não sair na tela em algumas maquinas ou pode sair tudo errado na tela ou na eventual impressão. evite comentários óbvios como // FUNCAO P/ LIMPAR A TELA void limpar() { printf("\n\n\n"); system("clear"); printf("\n\n\n"); }  
    Ainda sobre essa função, qual o propósito de escrever 3 linhas em branco, que ninguém vai ver, e depois limpar a tela?
     
    Veja esse comentário em seu programa:
     
    // INICIO DA MAIN int main(void)  
    Acha que acrescentou algo dizer que ali é o ínicio da função?
     
    Sobre system: é apenas uma função que pega uma string, um texto, e tenta rodar usando o interpretador de comandos do sistema. É proibida em toda parte, escolas e empresas. Como te disse, não vai aprender nada com isso. E system foi escrita em C. O sistema foi escrito em C. E deve imaginar que tem uma função para limpar a tela, em C, para o seu sistema operacional.
     
    Sobre pause: é uma coisa simples: você roda um programa para fazer algo e terminar. Não para fazer algo e ficar esperando um infeliz ficar em frente a tela para teclar ENTER depois que o programa fizer o que se espera que ele faça.
     
    EXEMPLO: 
     
    Você escreveu o programa soma.exe para rodar no windows. Você usa assim: 
     
    C:\Clube do Hardware>soma 42 17 42 + 17 = 59 C:\Clube do Hardware>soma 1700 4200 1700 + 4200 = 5900  
    E está ok. Mas se você fizer como "recomendado" e usar um pause imagine o que vai acontecer:
     
    C:]Clube do Hardware>soma 3 4 3 + 4 = 7 Press any key to continue . . . C:\Clube do Hardware>soma 5 6 5 + 6 = 11 Press any key to continue . . .  
    E você tem que digitar um ENTER. Ou chamar alguém pra ficar lá esperando. Mas imagine que você tenha uma lista de programas
     
    soma 2 3 soma 17 42 soma 2300 1 soma 0 0  
    Então você poderia por num arquivo e rodar todos de uma vez e esperar pelo resultado... basta digitar por exemplo .
     
    soma 2 3 & soma 17 42 & soma 2300 1 & soma 0 0  
    SEM o infeliz PAUSE:
     
    O sistema sabe que é pra rodar os programas um depois do outro e pronto
     
    C:\Clube do Hardware>soma 2 3 & soma 17 42 & soma 2300 1 & soma 0 0 2 + 3 = 5 17 + 42 = 59 2300 + 1 = 2301 0 + 0 = 0  
    Mas se fizer o recomendado....
     
    C:\Clube do Hardware>soma 2 3 & soma 3 4 2 + 3 = 5 Press any key to continue . . .  
    Genial., Tem que  teclar ENTER para rodar a próxima soma. Tem que ter alguém lá em frente ao teclado. Tosco. Não se escrevem programas para isso.
     
    Sobre void: Retornar void é ingênuo. Veja sua função
     
    void cadastrarEmpresa(int tam, Empresa cadastro[])...  
     
    O que se quer aqui? Simples: inserir uma empresa em um cadastro. Só que não é o que está escrito.
     
    Considere a alternativa
     
    int cadastrar(Empresa emp, Cadastro cad) { return 0; };  
    Você quer cadastrar uma empresa em um cadastro de empresas. Então você passa pra função uma empresa e um cadastro. E a função faz o serviço dela. Retorna 0 se deu certo, retorna -1, -2 ou qualquer coisa negativa para o caso de erro. Não acha mais esperto? Novidade não é. Sempre é feito assim.
     
    Sobre ler dados do teclado
     
    Entenda que seu programa tem um monte de funções e tem um monte de coisas pra testar. Não é nada esperto ficar digitando coisas a cada teste. 
     
    Sua empresa tem 6 campos. Um deles é o endereço e pode ter mais de um por empresa. Se for testar o programa com 3 empresas vai ter que digitar 18 campos. Só que endereco tem 6 campos também. Se usar 2 enderecos por empresa para 5 empresas imagina quanto tempo vai demorar cada simples teste que for fazer? 
     
    E você está aprendendo então é boa a chance do programa cancelar na sua cara logo depois de ficar 5 minutos inventando dados.
     
    sobre "NULL"
     
    NULL é um texto, um valor objetivo. NULL é o que se usa quando não tem nada no campo.
     
    Se você escrever 
     
    Empresa cadastro[20] = {0};  
    por exemplo, o sistema vai colocar esse valor em cada lugar do vetor inteiro.
     
    Sobre constantes e inicialização
     
    typedef struct { char pais[80]; char estado[80]; char municipio[80]; char logradouro[80]; int numero; int cep; } Endereco;  
    Pois é. Então pode usar
     
    Endereco teste = { .cep = 222, .estado = "SP", .logradouro = "Av. Antiga", .municipio = "Vila Nova", .numero = 42, .pais = "Terra Nova"};  
    E colocar valores na estrutura toda.
     
    Sobre um menu
     
    Imagine essa função:
     
    int menu1();  
    Ela mostra um menu e retorna o valor da opção que o cara escolheu. Não é conveniente????
     
    Sobre fflush
     
    fflush só está definido para saída. Não está no padrão fflush da entrada como está fazendo. Isso não existe exceto em um ou outro compilador e não é certo que vá funcionar. 
     
    Sobre o uso de arquivos
     
    Em C é trivial criar arquivos. Essa linguagem foi criada para ajudar a escrever um sistema, o Unix, que virou Linux, MacOS, Android e outros nessas décadas todas. No Unix tudo é arquivo então dá pra imaginar que é fácil usar arquivos em C.
     
    EXEMPLO
     
    int cria_arquivo(const char* nome, const char* texto) { FILE* arq = fopen(nome, "w"); if (arq == NULL) return -1; fprintf(arq, "arquivo: \"%s\"\n", nome); for (int i = 0; i < 5; i += 1) fprintf(arq,"%06d \"%20s\"\n", 1 + i, texto); fclose(arq); return 0; }  
    Essa função trivial chamada assim
     
    cria_arquivo("teste.txt", "valor");  
    cria o arquivo teste.txt com isso dentro
     
    arquivo: "teste.txt" 000001 " valor" 000002 " valor" 000003 " valor" 000004 " valor" 000005 " valor"  
    Nada mais
     
    Sobre o código postado
     
    Pouco corrigiu dos problemas que apontei. Uso incorreto de scanf, printf, fflush e tal. Sugiro ir refinando o programa conforme aprende.
     
    typedef struct { char pais[80]; char estado[80]; char municipio[80]; char logradouro[80]; int numero; int cep; } Endereco; typedef struct { int id; char nome[80]; char cnpj[80]; char proprietario[80]; int funcionarios; int qtd_endereco; Endereco endereco; } Empresa;  
    Criou um campo qtd_endereco mas só tem lugar pra 1. Que diferença faz? E os outros?
     
    Pra que 80 bytes num cnpj? Porque cep é int? vai somar? Porque estado tem 80? Seu compilador não reclamou pelo tamanho da pilha porque declarou errado o vetor.
     
    A noção de container
     
    Todos esses programas de iniciantes giram em torno da noção de container, coleção, algum tipo de cadastro. Se usar isso desde o início sua vida vai ficar muito mais simples
     
    Escreva em torno dos dados
     
    Cade o cadastro? Porque não tem essa estrutura em seu programa? Acha que basta um vetor??
     
    Não basta. Só dá muito mais trabalho se ficar só com o vetorzinho. Considere uma alternativa bobinha:
     
    typedef struct { unsigned tam; // tamanho unsigned lim; // limite Empresa emp[20]; } Cadastro;  
    Não fica claro que o limite é 20 e que  se colocar tam = 0 a estrutura fica marcada como vazia? Não é mais simples?
     
    E a mesma coisa não serviria para os endereços, já que seria um outro container, a mesma coisa? Algo assim não ajudaria:
     
    typedef struct { unsigned tam; // tamanho unsigned lim; // limite Endereco end[5]; } Enderecos;  
    Sim,  a mesma coisa.
     
    Como usar? Trivial: basta colocar isso em cada empresa
     
    typedef struct { int id; char nome[80]; char cnpj[15]; char proprietario[80]; int funcionarios; Enderecos end; } Empresa;  
    E claro que não precisa mais da quantidade de endereços em Empresa porque a estrutura já tem seu contador DENTRO.
     
    Veja como pode ser simples:
     
    int limpar_cadastro(Cadastro* cad,unsigned tam) { if ( cad == NULL ) return -1; cad->lim = tam; cad->tam = 0; // vazio return 0; }  
    O que importa é começar logo a testar o programa. Precisa de uma empresa? Um cadastro? Um endereco? Use C, use o computador.
     
    int cadastra(Empresa emp, Cadastro* cad) { if (cad == NULL) return -1; if (cad->tam >= cad->lim) return -2; // não cabe cad->emp[cad->tam] = emp; // copia a empresa cad->tam += 1; // conta essa return 0; }  
    cadastrar uma empresa pode ser só isso. Se voltou zero está ok.
     
    Veja a saida de um exemplo
     
    Cadastro tem 4 [de 20] empresas Amazonia (CNPJ:123.456.78-45) Amazon (CNPJ:123.456.78-03) Google (CNPJ:123.456.78-02) Microsoft (CNPJ:123.456.78-04)  
    Só digitando os dados. Sem entrada, sem pausa, sem esperar. Em 5 minutos estamos testando e já rodou da primeira vez
     
    #include <stdio.h> #include <stdlib.h> typedef struct { char pais[80]; char estado[3]; char municipio[80]; char logradouro[80]; int numero; char cep[10]; // 01234-012 } Endereco; typedef struct { unsigned tam; // tamanho unsigned lim; // limite Endereco end[5]; } Enderecos; typedef struct { int id; char nome[80]; char cnpj[15]; char proprietario[80]; int funcionarios; Enderecos end; } Empresa; typedef struct { unsigned tam; // tamanho unsigned lim; // limite Empresa emp[20]; // max 20 } Cadastro; int limpar_cadastro(Cadastro*); int cadastra(Empresa, Cadastro*); int lista(Cadastro*); int cria_arquivo(const char*, const char*); int main(void) { Endereco teste = { .cep = "123450678", .estado = "TN", .logradouro = "Rua Antiga", .municipio = "Vila Nova", .numero = 42, .pais = "Terra Nova"}; Empresa emp_1 = { .cnpj = "123.456.78-45", .nome = "Amazonia"}; int res = 0; Cadastro um; limpar_cadastro(&um, 20); // cadastra umas empresas res = cadastra(emp_1, &um); res = cadastra( (Empresa){ .cnpj = "123.456.78-03", .nome = "Amazon"}, &um); res = cadastra( (Empresa){ .cnpj = "123.456.78-02", .nome = "Google"}, &um); res = cadastra( (Empresa){ .cnpj = "123.456.78-04", .nome = "Microsoft"}, &um); // lista lista(&um); return 0; } // https://www.clubedohardware.com.br/forums/topic/1654426-programa-de-cadastro-de-empresas-em-c/#comment-8620688 int cadastra(Empresa emp, Cadastro* cad) { if (cad == NULL) return -1; if (cad->tam >= cad->lim) return -2; // não cabe cad->emp[cad->tam] = emp; // copia a empresa cad->tam += 1; // conta essa return 0; } int lista(Cadastro* cad) { printf( "Cadastro tem %u [de %u] empresas\n\n", cad->tam, cad->lim); for (int i = 0; i < cad->tam; i += 1) { printf( " %s (CNPJ:%s)\n", cad->emp[i].nome, cad->emp[i].cnpj); } printf("\n"); return 0; } int limpar_cadastro(Cadastro* cad, unsigned tam) { if (cad == NULL) return -1; cad->lim = tam; cad->tam = 0; // vazio return 0; } int cria_arquivo(const char* nome, const char* texto) { FILE* arq = fopen(nome, "w"); if (arq == NULL) return -1; fprintf(arq, "arquivo: \"%s\"\n", nome); for (int i = 0; i < 5; i += 1) fprintf(arq, "%06d \"%20s\"\n", 1 + i, texto); fclose(arq); return 0; }  
    Agora pode inserir os enderecos e continuar testando, mas o que importa é entender como deve escrever em torno dos dados. E NUNCA escrever um programa interativo.

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