-
Posts
6.526 -
Cadastrado em
-
Última visita
Tipo de conteúdo
Artigos
Selos
Livros
Cursos
Análises
Fórum
Tudo que arfneto postou
-
Sim. E na versão inicial o quie estaa errado era a falta do asterisco: estava alocando unidades de Fork e não de Fork*. Eu te mostrei um exemplo. E Em geral ao ler algo assim você espera as unidades primeiro. Te expliquei isso também. Veja uma nota fiscal... Escreva o simples. E declarar uma variável solta com esse nome i fora do loop e só para controlar o loop é bem tosco. Sua professora por certo não vota no comitê ISO que mantem essas linguagens. Como te disse, em java e C++ por exemplo você pode colocar { } em qualquer bloco no meio do programa apenas para reduzir o escopo e sumir com essas possíveis coisas. E em C++ se pode declarar variáveis no switch() no do() e no while() com o mesmo propósito
-
Eu te expliquei a razão de não 3 tipos para a mesma coisa. E te mostrei um exemplo. O único dado é Fork, a estrutura. Pode chamar o ponteiro de Azul e o ponteiro para o ponteiro de PAzul. Só não é esperto. Apenas Fork existe. Se a estrutura é Grafo o ponteiro é Grafo* e o ponteiro para ele é Grafo**. Se tiver 12 estruturas vai andar com uma tabela de prefixos par ler o código? Sem necessidade? E se errar em um typedef vai arrastar isso pelo programa a toa...
-
Não acho que faça diferença. O tratamento é o mesmo. Eu não postei um exemplo completo? Ao ter a console signaled você de todo modo tem que ler e testar umas estruturas para saber o que houve. E lá está a origem do sinal. E isso é lido no programa. O programa não para a menos que você queira e se você quer você testa. O atraso é mínimo, de ms adicionado 9 minutos depois O que eu postei aqui não é o exemplo que eu pensava. A discussão aqui ficou muito tosca e eu não postei o programa que eu achava que tinha postado. No caso de substituir _getche() o WAIT é INFINITE e isso não é comum. Em geral você quer exatamente o contrário: 0. adicionado 17 minutos depois @Lucca Rodrigues Acho que eu te mostrei um programa que trata menus, baseado em curses, semanas atrás. Deve ler aquele programa e vai entender a diferença. Eu te mandei um link pra isso acho. De todo modo esse é o tratamento para ler APENAS ESCAPE ENTER SETAS para cima e para baixo 0 para voltar o menu para a seleção padrão + e menos no teclado comum e numérico SEM PARAR o PROGRAMA e sem read() ou qualquer parada para ler, como gets() ou scanf(). O menu "sólido" como te falei na ocasião. Não mexe na tela, não para, não lê e só aceita o previsto. E apaga. Nesse trecho abaixo tem sua resposta: trata apenas o teclado. do { FlushConsoleInputBuffer(Console); if ( WaitForSingleObject(Console, tempo) != tem_tecla) continue; int n = PeekConsoleInput(Console, buffer, 32, (LPDWORD)&total); if (total == 0) break; for (DWORD i = 0; i < total; i += 1) { if (buffer[i].Event.KeyEvent.bKeyDown) continue; v = buffer[i].Event.KeyEvent.wVirtualKeyCode; c = buffer[i].Event.KeyEvent.uChar.AsciiChar; // todos os testes sao definitivos entao so retorna if (v == VK_ADD) return _SOBE_; if (v == VK_SUBTRACT) return _DESCE_; if (v == VK_DOWN) return _SOBE_; if (v == VK_UP) return _DESCE_; if (v == VK_OEM_PLUS) return _SOBE_; if (v == '0') return _DEFAULT_; if (v == '+') return _SOBE_; if (v == VK_ESCAPE) return _ESCAPE_; if (v == VK_RETURN) return _ENTER_; if (c == '+') return _SOBE_; if (c == '-') return _DESCE_; if (c == '0') return _DEFAULT_; } } while (sem_escolha);
-
Sim, single quer dizer único, solteiro, desacompanhado Ela tem uma irmã, DWORD WaitForMultipleObjects( DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds ); Que você pode usar para, digamos, múltiplos objetos. Como deve imaginar são funções muito importantes. No caso da versão single, recebendo o handle de uma console, é o que faz. Se for o STD_INPUT_HANDLE é o teclado.
-
sim, é verdade. Mas veja a fórmula: e entenda que não precisa nem de um nem de outro. É apenas uma progressão acumulando A / B que começa com A = 1 e B = 1 e a cada loop X você calcula A = X * X e B = B * X Veja o início X | A | B 1 1 1 2 2*2 1*2 3 3*3 1*2*3 4 4*4 1*2*3*4 Então basta um loop. Não precisa de fatorial porque é implícito, não precisa de pow() porque a potência é quadrado, no popular A*A
-
typedef struct FORK *PFork; typedef struct FORK **PPFork; struct FORK { int value; PFork next; }; Acho que esse tipo de construção é mais difícil. Em geral eu diria que se NUNCA usar um tipo ponteiro NUNCA vai ter dúvidas ou depender de prefixos . Ou ficar indo e voltando nos headers para saber o que é o que. Compare: #include <stdlib.h> #include <stdio.h> typedef struct st_fork { int value; struct st_fork* next; } Fork; Fork** clearRoot(Fork**,int,int); Fork** createRoot(int,int); Fork* getNode(); int insertInRoot(Fork**, int, int); Fork* insertNode(int); Esse header serviria para seu programa. Qual a diferença? Simples: só existe Fork. O dado é Fork. Fork* e Fork** e Fork**** todos só existem a partir de Fork. Então ao ler o código você e outros economizam transições tipo começa com PP ou PP ou chama pont_struct... Os asteriscos estão lá para contar a história. E é muito mais fácil achar um erro assim do que um prefixo faltando, porque * é algo operante em C E main() deve ser a primeira função de seu programa, se possível em um arquivo separado. Porque? porque é onde alguém começa a ler o código. Todo alguém. E nem sempre você precisa compilar tudo... Por isso existe CMake, Make e projetos. E como você insere as funções uma a uma, use ordem. Alfabética por exemplo. Aí pode fazer busca binária no próprio IDE. Veja, com o seu código: O próprio IDE lista as funções que estão no arquivo aberto, na ordem em que elas estão no arquivo. Um único click e o cursor vai direto para a função. Então se estiverem em ordem alfabética seu trabalho é mínimo. Sobre o código Era o caso de ter uma descrição do algoritmo para entender o que quer fazer. Fork** createRoot(int nodes, int maxConnections) { int i; Fork** root = (Fork**)malloc(sizeof(Fork) * nodes); for (i = 0; i < nodes; i++) { root[i] = NULL; } return root; } Isso está errado. O que se quer aqui em geral é um array de Fork*. Não de Fork. Trata-se do mesmo paradigma de main(). cujo protótipo é int main ( int argc, char** argv); Você quer que createRoot() devolva o endereço de um vetor de ponteiros para estruturas, para poder iterar no vetor, como em argv[0], argv[1], argv[argc-1] em C. Pense nisso createRoot(30, maxConnections); deve retornar um ponteiro para uma área onde tem o que? 30 Fork? Não, Não, Não. 30 Fork* ! É muito importante entender isso se programa para sistemas ou estruturas de dados. E nunca se vê isso bem descrito na literatura. Ao menos eu nunca tive a sorte de ler algo assim. Então Fork** grafo = createRoot( 30, 45 ); // 30 vertices Grafo é Fork** Então *Grafo é Fork* E **Grafo é Fork. Assim é. Se definiu tipos apenas para as variáveis já entendeu como fica mais transparente a expressão do algoritmo e a leitura do programa. Os asteriscos mostram CLARAMENTE o nível de redirecionamento Então existe Grafo[0], Grafo[1], Grafo[2], e todos são Fork*, um ponteiro para Fork. É isso que você quer, e por isso Dennis e Bryan escreveram C : para escrever sistemas operacionais. E um game na verdade Claro que em geral se escreve *Grafo, *(Grafo + 1), *(Grafo + 2). Raramente se usa essa notação de [ ] colchetes. Então Fork** grafo = (Fork**)malloc(nodes * sizeof(Fork*)); Isso é mais expressivo inclusive na ordem. Pense numa nota fiscal: você instintivamente espera ler primeiro a quantidade, depois o produto e depois o preço. Usar o cast (Fork**) antes de malloc() é opcional e muitos autores condenam e muita gente replica sem qualquer explicação. Eu recomendo usar como um seguro contra você mesmo, para deixar claro que está alocando o que pretende. Nesse caso por exemplo mostra que você está usando um ponteiro para um ponteiro para Fork, mas na verdade serão vários ponteiros. O código é autoexplicativo ou vai ser logo mais na sua carreira em C porque essa construção é muito frequente. Todo programa em C começa por uma, na verdade. Só que aí você reservou a área apenas. Não tem nada lá. Precisa montar isso com cuidado. for (i = 0; i < nodes; i++) *(root + i) = NULL; Essa construção que usou int i; Fork** root = (Fork**)malloc(sizeof(Fork) * nodes); for (i = 0; i < nodes; i++) { É perigosa. Evite a todo custo. Em geral você quer o menor escopo, a menor vida para todas as variáveis. Em especial uma chamada i ou aux... Eis o que acontece: essa variável só é usada como controle do loop mas se você declara fora ela continua viva depois do loop e pode gerar um erro do 1nf3rn0 para char depois. Por isso desde 1989 é possível em C declarar essas variáveis como eu mostrei acima. Faça isso. Em C++ você pode declarar variáveis num switch ou while também, de tanta pressão para que isso fosse implementado para diminuir o scope de variáveis. Esse exemplo abaixo é perfeitamente legal: char opt = 2; switch (int i = 0, j = 12, char c = 'x'; opt) { default: std::cout << i << j << c << endl; };
-
fim -> prox = NULL; fim = ini; while (fim != NULL){ printf ("\nProduto: %s", fim->nome); printf ("\nPreço no atacado: %.2f", fim->preco_atacado); printf ("\nPreço no varejo: %.2f\n\n", fim -> preco_varejo); fim = fim -> prox; } Se na primeira linha aqui você escreve fim->prox = NULL e na última do loop escreve fim = fim->prox Não parece estranho que entre só uma vez no loop.... Ao terminar o tal loop fim vale fim->prox que ao iniciar vale... NULL E a condicão de sair seria qual? Essa mesmo. Aí ele sai.
-
Bom que conseguiu! Vi o programa agora. Se tiver alguma dúvida sobre isso abra um novo tópico. O programa está aqui e pode baixar pronto para compilar e com o grid de exemplo aqui E poste seu código se tem um problema com ele
-
O tópico está lá e é esse mesmo aqui acima e o programa também está lá completo. Vi agora. É de abril de 2019. Tem umas explicações, tem telas, uma discussão sobre o programa e os links para ler ou baixar o tal programa lá
-
É um exemplo acho que de abril de '19 mas está no mesmo lugar. Como fez para acessar? Não acho que tenha nada errado
-
C Ler e escrever vetor dinamico de struct em arquivo
arfneto respondeu ao tópico de Oceans of mind em C/C#/C++
Pois é: dinâmico de tamanho desconhecido sugere que não. Mas você vai ler o que você mesmo escreveu então pode usar algum marcador para indicar o fim e usar algum valor limite para o vetor, ou simplesmente ler e gravar um por um -
Isso não tem a ver com Lista e sim o fato de lista ser um ponteiro. LISTA* lista = NULL; int* umInt = NULL; CADASTRO* cad = NULL; char** argv = NULL; Um ponteiro para qualquer coisa é só um container: pode apontar para algo de um certo tipo, como um outro ponteiro. Quando você coloca NULL lá é como um seguro de que não vai apontar para algo a olho na memória. Ele nunca está "vazio", já que ele próprio tem um endereço e lá tem alguma coisa. E como tem alguma coisa você pode escrever *umInt e ver o valor do int que está naquele endereço. Só que se ele não se referir a algo alocado em seu programa e você ler vai ler algo que não tem nenhum sentido prático. E se tentar gravar lá vai cancelar seu programa. A diferença entre a gíria "mostrar lixo de memória" e o erro de segmentação Em relação a LISTA, é critério do programa achar que uma lista não iniciada está vazia. Vazia está. Bem... Não exatamente. Uma lista não é um nó. Se usar como tal só vai ter mais trabalho. Essas estruturas tipo containers, como eu disse no outro post, tem dados dentro. E tem um suporte. Vamos chamar de metadados e payload: Exemplo struct no { void* item; struct no* next; struct no* prev; }; // no typedef struct no Node; struct a_propria_lista { char* nome; unsigned quantos; unsigned maximo; Node* inicio; Node* fim; }; typedef struct a_propria_lista Lista; payload aqui é o item, um ponteiro para void. Assim a lista pode conter qualquer coisa e para usar em um novo programa não precisa nem compilar, dependendo do modo como construiu: basta o #include para compilar e um arquivo tipo lib ou DLL com o código compilado na última versão, Como faz em C++ se quer usar list: #include <list> metadados aqui são o resto: nome, quantos, máximo e os ponteiros E assim uma lista vazia não tem nenhum nó. Criar uma lista não envolve nós e pode ser algo como Lista* criar(const char* nome) { Lista* nova = (Lista*)malloc(sizeof(Lista)); nova->nome = (char*)malloc(1 + strlen(nome)); strcpy(nova->nome, nome); nova->quantos = 0; nova->maximo = 0; nova->inicio = NULL; nova->fim = NULL; return nova; }; // criar() E você cria uma chamando apenas Lista* teste = criar("Primeira Lista");
-
Sim. Para um particular NO. Como poderia ter um NO* fim. Em geral você quer inserir no início, no fim ou em alguma ordem. E usa ponteiros para frente e para trás em cada nó. Mas pode salvar também "favoritos", como uma lista dentro da lista, como numa lista de volumes para despachar e ter uma lista de produtos de pequeno volume, ou com prioridade
-
C Impressão de variáveis em struct não ocorre como esperado
arfneto respondeu ao tópico de Oceans of mind em C/C#/C++
Não funciona deste modo Esse ponteiro vec_pacote é o único que existe em main(). Quando passa esse ponteiro para cadastrarPacote() ele vai mas não volta. Só que lá você usa realloc() para alocar mais Pacote. E isso pode e muitas vezes vai mudar o endereço dele. Como você não retorna o valor ele se perde lá dentro, bem como toda a memória que você alocou... Nesse caso aqui declare Pacote* cadastrarPacote(Pacote*, int* n) E escreva vec_pacote = cadastrarPacote(vec_pacote, &a); Você queria escrever algo assim: typedef struct { int idPacote; char nomePacote[50]; } Pacote; typedef struct { int idCadastro; int quantos; int maximo; Pacote** pac; } Cadastro; int _cadastrarPacote(Pacote* pacote, Cadastro* sacola) { return 0; }; int _imprimirCadastro(Cadastro* sacola) { return 0; }; int _imprimirPacote(Pacote* pacote) { return 0; }; Compare: Um Cadastro é um conjunto de Pacote. Tem um total atual, uma capacidade e um vetor de ponteiros para pacote. Não por acaso main() é declarada int main( int argc, char**argv); é muito mais prático assim. Um vetor de strings que são os argumentos. Você pode escrever Cadastro Sacola[12]; Sacola[1].maximo = 100; Sacola[1].quantos = 0; Sacola[1].pac = NULL; E veja como é mais expressivo: Tem uma dúzia de sacolas. A segunda delas, já que a primeira é Sacola[0], pode ter um máximo de 100 Pacote. No momento está vazia. O vetor pac vai dar acesso aos pacotes, mas está vazio já que não tem nenhum. E nem começou o programa. Se você escreve em torno dos dados trabalha menos. Outro problema Nunca escreva isso vec_pacote = (Pacote*)realloc(vec_pacote, (i + 1) * (sizeof(Pacote))); Escreva assim //vec_pacote = (Pacote*)realloc(vec_pacote, (i + 1) * (sizeof(Pacote))); Pacote* novo = (Pacote*) realloc( vec_pacote, (i + 1)*(sizeof(Pacote)) ); if (novo != NULL) vec_pacote = novo; else { // algo errado } Se der erro em realloc() o que vai acontecer? Você vai perder tudo. Não tem outra cópia do ponteiro e não há garantia de que ele não tenha se perdido. E não use realloc() item a item. É terrivelmente ineficiente. Aloque um bloco razoável de Pacote e ao final libere o que não usar. Mais um palpite: Nunca use um menu em um programa que não está pronto. Só perde seu tempo. Testar isso é o máximo em monotonia e perda de tempo. Use constantes. Use arquivos de texto com os dados. Esses que você edita no próprio IDE. Sim, IDE é masculino. Assim pode testar com os mesmos dados várias vezes em minutos. Ou com vários dados em minutos... Acha que isso abaixo funciona? Pacote p1 = { 12, "teste" }; Pacote p2 = { .nomePacote = "Outro pacote", .idPacote = 8 }; Pacote sacolinha[3] = { { 1, "produto 1" }, { 2, "produto 2" }, { 3, "produto 3" } }; printf("%d, %s\n", p1.idPacote, p1.nomePacote); printf("%d, %s\n", sacolinha[2].idPacote, sacolinha[2].nomePacote); E cria dois pacotes e um vetor sacolinha com 3 pacotes para testar o programa? Sim, funciona. Veja o p1 e o terceiro produto em sacolinha -
Você está programando os dois lados, a função que chama e a função que usa, então o computador vai "aceitar" qualquer coisa desde que faça a mesma dos dois lados. Se está começando a programar pode ser hora de evitar vícios e entender que quando declara uma variável ela é de um tipo, que pode ser um ponteiro para um tipo, mas está declarando uma variável, um nome. Nesse caso acima está declarando chave, e chave é int*. É melhor você escrever e ler assim, porque é como o compilador vai gravar isso para gerar seu programa: chave é int*, dados é Dados* e assim por diante. E strcmp() compara strings. Não char nem int. E int* não é int mas sim um ponteiro para int poste o programa inteiro, compilável, para ajudar a gente a ajudar você.
-
São estruturas distintas. Entenda que um nó não é uma lista. Uma lista é uma coleção de nós. collection em java, container em C++... Quando você programa uma lista com uma estrutura apenas de nós o resultado em geral é ruim e o trabalho muito maior. Em geral todas essas estruturas de dados tem uma parte de controle, que alguns chamam de metadados, e uma carga, um dado. E o que se busca é usar uma coisa genérica para poder reusar o resto da vida. Um typedef define um alias, como o using de C++. Um nome alternativo. Ajuda muito quando tem nomes enormes por exemplo. E no mínimo em C evita que você tenha que escrever toda hora struct isso ou aquilo. Só que no caminho essa informação de ser uma struct some e por isso todo mundo procura padronizar algo, como no seu exemplo usar o nome em maiúsculas, para diferenciar um tipo definido pelo usuário de uma variável definida pelo usuário. union é um troço que costuma ser chamado de variant record e é um jeito de usar o mesmo espaço para guardar alternadamente várias coisas. Às vezes é só uma frescura mas tem casos em que é muito importante e salvador. Exemplo: Tem umas estruturas, como árvores, que tem em cada nó muitos ponteiros, às vezes dezenas deles. E tem algum dado no nó. Um tipo muito importante de árvore --- trie --- tem um único símbolo em cada nó terminal, as tais folhas. Mas cada nó pode ter dezenas de ponteiros. Então usar uma union como está no seu exemplo, permite que ao final do registro você tenha um valor que é um dado apenas, com digamos 4 bytes, e não tenha os 80 bytes de ponteiros por exemplo... Os registros tem tamanho variável mas compartilham um prefixo. E assim o enorme desperdício de espaço é evitado, porque todos os nós terminais tem a versão curtinha já que não apontam pra ninguém
-
Poste o código completo, de modo que possa ser copiado do formulário e compilado. Se você por exemplo estiver usando um #include errado ou tiver um faltando ninguém vai poder te dizer e ajudar main() deve ser a primeira função de seu programa, e se possível a única no arquivo onde está... use protótipos para as funções e declare tudo no fim ou se possível em outros arquivos não use variáveis globais. Não por acaso são proibidas em muitos ambientes, empresas e escolas,.e condenadas por autores e instrutores em todo o planeta. Isso só dá problema. No seu caso, symbol é parte do deck. Declare como tal. struct e class são a mesma coisa nesse contexto. Apenas em struct tudo é por padrão publico. Está programando em C++. Quando está programando em C++ a partir de 2011 e usa uma função init() quer dizer que tem provavelmente algo errado. não retorne void. Em geral é um desperdício e muitas vezes um erro mesmo. No caso de init_deck() entenda que você devia retornar o endereço do novo deck, como uma função factory. Não retornando quer dizer que tudo o que fizer lá dentro morre lá dentro. A memória que alocou some a toda chamada... não use malloc() em C++. Use new ou melhor ainda use unique_ptr e não precisará se preocupar com free() ou delete porque o sistema libera sózinho a área alocada. C++ tem listas disponíveis. Não precisa programar isso. Pode escrever algo como list<Card> baralho; Não é um bom caminho usar assim essas estruturas. Vai dar muito mais trabalho para muito menos resultado. De todo modo considere o que eu escrevi e veja essa saída Deck com 26 cartas a b c d e f g h i j k l m n o p q r s t u v x y w z Ao final: primeira carta = a Ultima carta = z Apagando o deck: [z w y x v u t s r q p o n m l k j i h g f e d c b a ] Desse programa, que é o seu programa com umas notas int main(void) { Deck* deck1 = init_deck("abcdefghijklmnopqrstuvxywz"); show_deck(deck1); cout << "Ao final: primeira carta = " << deck1->first_card->symbol << " Ultima carta = " << deck1->last_card->symbol << "\n"; deck1 = destroy_deck(deck1); return 0; }; // main() Veja que passar os símbolos como argumento é mais produtivo: tem mais opções: pode usar o tamanho da string para controlar init_deck() e usar qualquer número de símbolos. Escreva em torno dos dados e fica mais fácil de ler. Retorne os endereços. Quando apaga também, assim se assegura de invalidar o ponteiro, uma causa comum de crash --- dangling pointers Apagar o deck é uma operação de dois passos, como no exemplo Deck* destroy_deck(Deck* D) { if (D == NULL) return NULL; cout << "Apagando o deck: ["; Card* p = D->last_card; while (p != NULL) { Card* antes = p->back_card; cout << p->symbol << " "; delete p; p = antes; }; delete D; cout << "]\n"; return NULL; }; Eis o programa todo #include <iostream> #include <list> using namespace std; struct _card { char symbol; struct _card* next_card; struct _card* back_card; }; typedef struct _card Card; struct _deck { Card* first_card; Card* last_card; int num_cards; string symbols; }; typedef struct _deck Deck; Deck* destroy_deck(Deck*); Deck* init_deck(string); int show_deck(Deck*); int main(void) { Deck* deck1 = init_deck("abcdefghijklmnopqrstuvxywz"); show_deck(deck1); cout << "Ao final: primeira carta = " << deck1->first_card->symbol << " Ultima carta = " << deck1->last_card->symbol << "\n"; deck1 = destroy_deck(deck1); return 0; }; // main() Deck* destroy_deck(Deck* D) { if (D == NULL) return NULL; cout << "Apagando o deck: ["; Card* p = D->last_card; while (p != NULL) { Card* antes = p->back_card; cout << p->symbol << " "; delete p; p = antes; }; delete D; cout << "]\n"; return NULL; }; Deck* init_deck(string symbol) { Deck* deck = (Deck*) new Deck; deck->last_card = NULL; deck->num_cards = 0; deck->symbols = symbol; deck->first_card = (Card*) new Card; deck->first_card->back_card = NULL; deck->first_card->next_card = NULL; deck->first_card->symbol = symbol[0]; Card* p = deck->first_card; int n = symbol.length(); for (int i = 1; i < n; i += 1) { Card* nova = (Card*) new Card; nova->back_card = p; p->next_card = nova; nova->next_card = NULL; nova->symbol = symbol[i]; p = nova; // avanca }; deck->last_card = p; // era a ultima afinal deck->num_cards = n; // corrige deck->symbols = symbol; // salva return deck; }; int show_deck(Deck* deck) { if (deck == NULL) return -1; cout << "Deck com " << deck->num_cards << " cartas\n"; Card* p = deck->first_card; int count = 0; while (p != NULL) { cout << p->symbol << " "; p = p->next_card; count += 1; } cout << "\n"; return count; // para conferir } Repito: não vale a pena escrever assim. Resumo curtinho O maior problema do seu código é não retornar o endereço do deck.
-
Essa é uma questão para o forum sobre Python, ou tem dúvidas sobre o que fez em C? quer escrever em C#? quer escrever em C++? Poste algo compilável e uma descrição do problema...
-
Sim, está errado em algumas coisas char str1[5][100]; char str2[5][100]; char str3[5][100]; char str4[5][100]; porque não fazer o simples e usar nomes significativos? Algo copiado do texto como char nome[50][50]; char RG[50][15]; // 234.678.012-4 char CidadeNatal[50][50]; char Endereco[50][50]; Vai ficar associando mentalmente toda vez qual str é a cidade natal? Isso não existe: printf("\nDigite seu nome: "); gets(str1[count]); gets() não existe mais. Foi declarada oficialmente obsoleta há cerca de 20 anos. Se pretendia ler algo em str1 entenda que str1 é char [5][100], foi assim que você declarou. Se que ler um deles deve dizer qual. De certo modo são 5 linhas de 100 colunas. E esse count seria o que? o limite ou o tamanho que leu? printf("\nDigite seu nome: "); fgets(nome[0], 50, stdin); int count = strlen(nome[0]); Veja acima e compare. fgets() vai tentar ler da entrada padrão até 50 letras e colocar em nome[0], o primeiro nome. E o tamanho do que foi lido vai estar em count no retorno da função strlen() que devolve... o tamanho da string. E entenda que fgets() lê a linha toda até o ENTER, inclusive o próprio, porque foi pensada para ser usada com puts() para por na tela e assim lê e mostra a mesma coisa. Mas se você vai gravar isso ou usar printf() para por na tela precisa excluir esse '\n' do valor lido Veja a saída do exemplo Digite seu nome: Clube do Hardware Clube do Hardware Nome lido: 'Clube do Hardware' E entenda que ele pula uma linha no puts() e isso é prático. Mas nem sempre é o que você quer. E entenda que uma linha em branco não dá pra ver então quando está começando é bom envolver as strings em algo como aspas que eu usei no exemplo... O programa #include <stdio.h> #include <string.h> int main(void) { char nome[50][50]; char RG[50][15]; // 234.678.012-4 char CidadeNatal[50][50]; char Endereco[50][50]; printf("\nDigite seu nome: "); fgets(nome[0], 50, stdin); puts(nome[0]); nome[0][strlen(nome[0]) - 1] = 0; // apaga o '\n' int count = strlen(nome[0]); printf("Nome lido: '%s'\n", nome[0]); return(0); }
-
Não necessariamente. Pode seguir ao contrário, como faria o pedreiro. Se tem algum azulejo e ele for quadrado já tem a primeira resposta. Aí vai tentar o próximo quadrado, 2x2. Terá 4 azulejos? Se tiver, argamassa neles. Terá outros 5 para completar as "carreiras"? Acho que já entendeu. Não precisa da raiz quadrada. Precisa dos azulejos, e do lado matemático, de uma multiplicação e uma subtração.
-
Imagino que nesses 8 anos e meio ele deve ter conseguido resolver, afinal esse post é de fevereiro de 2012! De todo modo, @Abe usar void funcao (int n, int matriz[][n]) não vai rolar. A primeira dimensão até poderia ficar assim, [ ] , mas a segunda tem que ser constante. Não pode ser 'n' com n int. A conta a ser feita para achar o endereço de cada elemento da matriz é essa: matriz[x][y] = &matriz + ( sizeof(int) * ( y * COLUNAS + x ) ) e você vê na conta que o número de linhas não aparece. Exemplo 1 2 3 4 5 6 com sizeof(int) = 4 bytes com uma matriz 2 x 3 de int para achar o endereço do último cara, o 6 A matriz int matriz[2][3] O último matriz[1][2]; Então eles vão estar lá na memória, os seis caras, uma linha depois da outra. Pela conta lá em cima deve dar matriz[1][2] = &matriz[0][0] + 4 * (1*3) + 2 = endereço inicial + 4 * 5 = endereço inicial + 20 E na memória os valores vão estar assim, a partir do endereço matriz, ou &matriz[0][0] que dá na mesma | 1 | 2 | 3 | 4 | 5 | 6 | como cada int ocupa 4 bytes nesse exemplo aqui, é claro que o endereço do 6 vai ser o endereço do 1 mais 20. E para confirmar? Um programa de teste para alterar o último valor para 60 usando os índices e depois para 600 usando a conta e depois mostrando o valor usando os índices e depois chamando uma função e mostrado os valores todos Endereco inicial de int matriz[2][3]: 004FF8C4 valor de matriz[1][2] o ultimo elemento: 60 valor de matriz[1][2] pela formula: 60 Alterando o valor para 600 pela formula valor de matriz[1][2]: 600 valor de matriz[1][2] pelos indices: 600 mostra(M[2][3]) M[0,0] = 1 M[0,1] = 2 M[0,2] = 3 M[1,0] = 4 M[1,1] = 5 M[1,2] = 600 A fun #include <iostream> using namespace std; void mostra(int, int, int*); int main(void) { int matriz[2][3] = { {1,2,3}, {4,5,6} }; cout << "Endereco inicial de int matriz[2][3]: " << &matriz << endl; matriz[1][2] = 60; cout << "valor de matriz[1][2] o ultimo elemento: " << matriz[1][2] << endl; int x = 1; int y = 2; int COLUNAS = 3; int* p = &matriz[0][0] + (x * COLUNAS) + y ; cout << "valor de matriz[1][2] pela formula: " << *p << endl; int* inicio = &matriz[0][0]; cout << "Alterando o valor para 600 pela formula" << endl; *(inicio + x * COLUNAS + y) = 600; cout << " valor de matriz[1][2]: " << *p << endl; cout << "valor de matriz[1][2] pelos indices: " << matriz[1][2] << endl; mostra(2, 3, (int*)matriz); }; void mostra(int l, int c, int* M) { cout << "\nmostra(M[" << l << "][" << c << "])\n"; for (int x = 0; x < l; x += 1) for (int y = 0; y < c; y += 1) cout << "M[" << x << "," << y << "] = " << *(M + x*c + y) << endl; return; } A função que importa está logo acima, e a conta está como na fórmula. É o simples.
-
Essa é a saída da versão atual de exibirLog() Que está lá na versão que eu escrevi. Pode usar algo assim. tem a lista dos slots ocupados na fila, o total deles, o ponteiro para o sentinela e todos os ponteiros para os registros na listagem por prioridade, que é a fila propriamente dita
-
C++ Kit de códigos de c++ para iniciantes Dev C++ 5.11
arfneto respondeu ao tópico de luis_r.guerra em C/C#/C++
Acho que já postei isso antes. Veja em https://github.com/microsoft/Windows-classic-samples direto do fornecedor, exemplos antigos de código em C ou C++ para qualquer coisa em Windows do jeito '90 Para tratar imagens na tela sugiro fugir do modelo event loop/mensagens clássico da API do Windows. Não é um modelo produtivo. Vai ter muito mais sucesso com coisas como Allegro, GTK+, Qt, SDL ou wxWidgets. São mais simples e mais produtivas e todas funcionam de modo bem semelhante, ao menos até onde eu já usei. Se não fizer questão de C/C++ .Net é bem fácil, ao menos para usar os controles do Windows. Em geral essas ferramentas tem um "designer", um formulário onde você pode ajustar graficamente os componentes na tela e ele gera os links para as rotinas que tratam os eventos. Coisas como o designer do Delphi, do Office, do .net, o Creator do Qt... Veja o designer do Office, dentro do Outlook: Então não tem muito incentivo para fazer isso em C ou C++ sem usar essas ferramentas, e nem mesmo para usar essas linguagens quando a performance não importa. E no caso de aplicações interativas a performance não importa mesmo. Por isso não há bom suporte a isso dentro de C ou C++ em Windows mesmo. Aplicações desse tipo sã escritas em outras linguagens. Pode ser ruim de compilar inicialmente mas acho que vale a pena. Se quer sossego use vcpkg da Microsoft, que instala qualquer coisa com um único comando e sem intervenção do usuário. Algo como vcpkg install qt5 E você toma um café e volta de pois de uns 5 minutos e está tudo compilado e instalado e todo novo programa pode usar os #include e compilar e tudo funciona. Um passeio. Eis algumas das mais de 900 bibliotecas disponíveis lá: allegro5 5.2.6.0 Allegro is a cross-platform library mainly aimed at video game and multimedia ... cairo 1.16.0#7 Cairo is a 2D graphics library with support for multiple output devices. Curre... gtk 3.22.19-4 Portable library for creating graphical user interfaces. opengl 0.0-7 Open Graphics Library (OpenGL)[3][4][5] is a cross-language, cross-platform ap... qt5 5.15.0#2 Qt5 Application Framework sdl2 2.0.12#4 Simple DirectMedia Layer is a cross-platform development library designed to p... wxwidgets 3.1.4#3 wxWidgets is a widget toolkit and tools library for creating graphical user in... -
exibirLog() não pode cancelar só porque a fila não foi criada ainda. É uma rotina de diagnóstico e em geral é escrita antes mesmo da que cria a fila. Para teste. Uma rotina de teste não deve cancelar só porque o ponteiro não é válido A saída de exibirLog() está um pouco ruim de ler, para uma rotina que serve justamente para certificar que a estrutura está ok e os ponteiros estão certinhos. Talvez deva rever.
-
Parece que o botão de código está de volta ao forum. Teste seu programa com aquelas funções de teste. Como essa int testaCriaUns(FILADEPRIORIDADE* porque) { printf("\n\n\t==> Criando alguns registros\n\n\n"); for (int id = 0; id < 30; id += 3) { int res = inserirElemento(porque, id, (float)(rand() % 2000) / 100.f); if (res < 0) { printf("Erro ao inserir %d\n", id); return 0; }; }; // if() return 0; }; // testaCriaUns() Note que o nome da fila é p q e o forum vem alterando por canta deles Ou essa int testaMudaPrioridade(FILADEPRIORIDADE* f) { printf("\n\n\t==> Teste:\n\ \t\tsoma 1 em todas as prioridades para ID pares\n\ \t\te diminui 1 em todas as impares\n\n\n"); // mostra antes exibirLog(f); int ix = tamanho(f); ELEMENTO* p = f->fila->prox; // primeiro while (ix > 0) { if (p->id % 2 == 0) aumentarPrioridade(f, p->id, (float)(p->prioridade + 1.0f)); else reduzirPrioridade(f, p->id, (float)(p->prioridade - 1.0f)); p = p->prox; ix -= 1; }; // while() // mostra depois exibirLog(f); return 0; }; // testaMudaPrioridade() Não acredito que alguém seriamente especificou essas duas rotina,s aumentar e reduzirPrioridade, mas tudo bem Ou essa que atende todo mundo que está na fila... int testaRemoveTodos(FILADEPRIORIDADE* porque) { // agora remove todos printf("\n\n\t==> Atendendo todo mundo: fila vai ficar vazia\n\n\n"); // mostra antes exibirLog(porque); ELEMENTO* adeus = NULL; while (tamanho(porque) > 0) { adeus = removerElemento(porque); if (adeus != NULL) { printf("Removido elemento com endereco %p\n", adeus); } else { printf("Nao removeu elemento (%d,%6.2f)\n", porque->fila->prox->id, porque->fila->prox->prioridade); }; // if() }; // mostra depois exibirLog(porque); return 0; }; // testaRemoveTodos() adicionado 0 minutos depois Note que o software novo do forum continua fazendo aquela bobagem.... adicionado 10 minutos depois adicionado 27 minutos depois Mudei um pouco exibirLog() exibirLog(): Fila tem 30 lugares. 10 ocupados Listagem por identificador: 1/ 30: [ id: 0 P: 12.21 ] 2/ 30: [ id: 3 P: 4.93 ] 3/ 30: [ id: 6 P: 12.17 ] 4/ 30: [ id: 9 P: 6.74 ] 5/ 30: [ id: 12 P: 18.49 ] 6/ 30: [ id: 15 P: 9.51 ] 7/ 30: [ id: 18 P: 6.06 ] 8/ 30: [ id: 21 P: 5.77 ] 9/ 30: [ id: 24 P: 4.21 ] 10/ 30: [ id: 27 P: -56.00 ] Listagem por prioridade: [ inicio: 0x00A55900 ] 1/ 10: [ id: 12 p: 18.49 ] [ 0x00A58A10, ant:0x00A55900, prox: 0x00A4FE48] 2/ 10: [ id: 0 p: 12.21 ] [ 0x00A4FE48, ant:0x00A58A10, prox: 0x00A53B00] 3/ 10: [ id: 6 p: 12.17 ] [ 0x00A53B00, ant:0x00A4FE48, prox: 0x00A58C50] 4/ 10: [ id: 15 p: 9.51 ] [ 0x00A58C50, ant:0x00A53B00, prox: 0x00A53B40] 5/ 10: [ id: 9 p: 6.74 ] [ 0x00A53B40, ant:0x00A58C50, prox: 0x00A58B50] 6/ 10: [ id: 18 p: 6.06 ] [ 0x00A58B50, ant:0x00A53B40, prox: 0x00A58810] 7/ 10: [ id: 21 p: 5.77 ] [ 0x00A58810, ant:0x00A58B50, prox: 0x00A4F9A0] 8/ 10: [ id: 3 p: 4.93 ] [ 0x00A4F9A0, ant:0x00A58810, prox: 0x00A58E50] 9/ 10: [ id: 24 p: 4.21 ] [ 0x00A58E50, ant:0x00A4F9A0, prox: 0x00A58E10] 10/ 10: [ id: 27 p: -56.00 ] [ 0x00A58E10, ant:0x00A58E50, prox: 0x00A55900] Fim da listagem Assim fica mais obvio para seguir os links: o endereço do registro sentinela está explícito em "inicio:". Claro que ele vem antes do primeiro e depois do último, mas fica mais claro assim. E muda só uma linha de código afinal. Não sei porque não tinha isso desde antes.
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