-
Posts
6.526 -
Cadastrado em
-
Última visita
Tópicos solucionados
-
O post de arfneto em Função para gravar dados formatados em uma string foi marcado como solução
Olá!
Não sei se entendi seu programa ou o seu problema em si. Com os compiladores que tenho aqui sempre mostra a mesma string, mas não entendi o valor de escrever tantos pontinhos. Vou deixar um exemplo mais abaixo.
Code::Blocks ou qualquer outro IDE não va fazer qualquer diferença já que eles não compilam nada. Atente para o compilador que está usando no momento no IDE e para as opções de compilação. Em especial se está usando Release ou Debug mode e as opções de otimização. -O.
um programa pode não rodar em Release mode porque tem em Debug o IDE zera certas partes da memória e aí ele roda. Triste, porque depois que está considerado pronto o cara compila sem debug e tudo otimizado e instala e aí não funciona mais já vi programas ficarem em produção com o códgio de debug por meses porque ninguém conseguia achar o erro e os prazos já tinham acabado e o programa já tinha sido pago... um programa pode não rodar devido a alguma otimização que acabou entendendo errado o código Não acho que seja o seu caso em um programa tão simples.
Mas por outro lado essa linha
if (res < 0) { dados = NULL; } return dados;
que no popular podia ser só
if ( res < 0 ) return NULL; return dados;
seria uma boa explicação para o seu caso no Code::Blocks. Provavelmente deu erro na chamada e só.
Olhando mais pra cima no seu código
if ((res = vsnprintf(dados, aloc, format, args)) >= aloc && res >= 0) { aloc = res + 1; dados = (char*)realloc(dados, aloc); res = vsnprintf(dados, aloc, format, args); }
Se a primeira chamada deu erro res vai ser negativo e vai retornar NULL para o printf(). Só isso. Porque não faz o simples e chama perror() para saber o que houve?
Se está escrevendo dadosf() justamente para testar vsnprintf() pode fazer o programa responder suas perguntas antes...
Considere por exemplo
char* dadosf(const char* format, ...) { size_t aloc = strlen(format) - 10; // pra nao caber mesmo char* dados = (char*)malloc(aloc); va_list args; va_start(args, format); int need = vsnprintf(dados, aloc, format, args); printf("Primeira chamada retornou %d\n", need); if (need < 0) { perror("Erro na 1a chamada"); return NULL; }; if (need > aloc - 1) // nao cabe, vai truncar { printf("Necessarios %d, alocados %d. Realocando...\n", need, aloc); aloc = 1 + need; // ok, tanto quanto precisa + o zero char* p = realloc(dados, aloc); if (p == NULL) { perror("realloc falhou"); return NULL; } printf("Alocados %d. Tentando de novo...\n", aloc); dados = p; need = vsnprintf(dados, aloc, format, args); } if (need < 0) { perror("Erro na 2a chamada"); return NULL; }; va_end(args); return dados; }
E
size_t aloc = strlen(format) - 10; // pra nao caber mesmo char* dados = (char*)malloc(aloc);
Já garante que não vai caber
int need = vsnprintf(dados, aloc, format, args); printf("Primeira chamada retornou %d\n", need); if (need < 0) { perror("Erro na 1a chamada"); va_end(args); return NULL; };
Se deu erro já diga qual foi e quando
if (need > aloc - 1) // nao cabe, vai truncar { printf("Necessarios %d, alocados %d. Realocando...\n", need, aloc); aloc = 1 + need; // ok, tanto quanto precisa + o zero char* p = realloc(dados, aloc); if (p == NULL) { perror("realloc falhou"); va_end(args); return NULL; } printf("Alocados %d. Tentando de novo...\n", aloc); dados = p; need = vsnprintf(dados, aloc, format, args); }
Se não cabe aloca o necessário e tenta de novo.
main()
int main() { printf("<%s>\n", dadosf("Essa string tem 120 caracteres desconsiderando o caractere nulo.........................................................")); return 0; }
Não misture as coisas. É um teste então prepare linha a linha.
Prefira
int main() { const char* o_teste = "\ Essa string tem 120 caracteres desconsiderando o caractere n\ ulo.........................................................\ "; char* o_retorno = dadosf(o_teste); if (o_retorno == NULL) { printf(":( retornou NULL\n"); return -1; } printf("Retorno:\n\"%s\"\n", o_retorno); free(o_retorno); return 0; }
Assim
pode contar 2x60 salva o retorno testa com mais controle libera a memória alocada é mais legível... Pra que tanto pontinho?
Um outro teste
Como seu programa não formata nada vou deixar um teste que mostra a ideia de vsnprintf().
Essa é a string de entrada
char* message = "[10] '%s' [6] '%s' [10] '%s'";
E a ideia é inserir nos 3 "%s" outras strings...
int main() { char* message = "[10] '%s' [6] '%s' [10] '%s'"; char* digito = "0123456789"; char* letra = "ABCDEF"; printf("string original(%zd): \"%s\"\n", strlen(message)-6, message); size_t lim = strlen(message) - 6; testa_vsnprintf(lim + 10 + 6 + 10, message, digito, letra, digito, letra, digito); return 0; }
Essas digito e letra. Mas no teste vão 6 strings. Para isso é um teste afinal. Não pode ter menos, mas pode ter mais que 3 parâmetros...
A saída do programa
string original(22): "[10] '%s' [6] '%s' [10] '%s'" String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123456789' ] Disponivel: 49 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123456789 ] Disponivel: 48 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '012345678 ] Disponivel: 47 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '01234567 ] Disponivel: 46 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123456 ] Disponivel: 45 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '012345 ] Disponivel: 44 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '01234 ] Disponivel: 43 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123 ] Disponivel: 42 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '012 ] Disponivel: 41 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '01 ] Disponivel: 40 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0 ] Disponivel: 39 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] ' ] Disponivel: 38 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] ] Disponivel: 37 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] ] Disponivel: 36 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10 ] Disponivel: 35 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [1 ] Disponivel: 34 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [ ] Disponivel: 33 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' ] Disponivel: 32 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' ] Disponivel: 31 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF ] Disponivel: 30 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDE ] Disponivel: 29 Necessario: 48 String: [[10] '0123456789' [6] 'ABCD ] Disponivel: 28 Necessario: 48 String: [[10] '0123456789' [6] 'ABC ] Disponivel: 27 Necessario: 48 String: [[10] '0123456789' [6] 'AB ] Disponivel: 26 Necessario: 48 String: [[10] '0123456789' [6] 'A ] Disponivel: 25 Necessario: 48 String: [[10] '0123456789' [6] ' ] Disponivel: 24 Necessario: 48 String: [[10] '0123456789' [6] ] Disponivel: 23 Necessario: 48 String: [[10] '0123456789' [6] ] Disponivel: 22 Necessario: 48 String: [[10] '0123456789' [6 ] Disponivel: 21 Necessario: 48 String: [[10] '0123456789' [ ] Disponivel: 20 Necessario: 48 String: [[10] '0123456789' ] Disponivel: 19 Necessario: 48
Conforme o espaço encolhe vsprinf() corta a saída, como esperado.
void testa_vsnprintf(size_t lim, const char* msg, ... ) { char* buffer = (char*)malloc(1+lim); va_list args; va_start(args, msg); for (size_t aloc = 1+lim; aloc > lim - 30; aloc -= 1) { int res = vsnprintf(buffer, aloc, msg, args); printf("String: [%-50s] Disponivel: %zd Necessario: %d\n", buffer, aloc, res); } va_end(args); free(buffer); return; }
Sim, b0b1nh0 meu programa
-
O post de arfneto em Função para gravar dados formatados em uma string foi marcado como solução
Olá!
Não sei se entendi seu programa ou o seu problema em si. Com os compiladores que tenho aqui sempre mostra a mesma string, mas não entendi o valor de escrever tantos pontinhos. Vou deixar um exemplo mais abaixo.
Code::Blocks ou qualquer outro IDE não va fazer qualquer diferença já que eles não compilam nada. Atente para o compilador que está usando no momento no IDE e para as opções de compilação. Em especial se está usando Release ou Debug mode e as opções de otimização. -O.
um programa pode não rodar em Release mode porque tem em Debug o IDE zera certas partes da memória e aí ele roda. Triste, porque depois que está considerado pronto o cara compila sem debug e tudo otimizado e instala e aí não funciona mais já vi programas ficarem em produção com o códgio de debug por meses porque ninguém conseguia achar o erro e os prazos já tinham acabado e o programa já tinha sido pago... um programa pode não rodar devido a alguma otimização que acabou entendendo errado o código Não acho que seja o seu caso em um programa tão simples.
Mas por outro lado essa linha
if (res < 0) { dados = NULL; } return dados;
que no popular podia ser só
if ( res < 0 ) return NULL; return dados;
seria uma boa explicação para o seu caso no Code::Blocks. Provavelmente deu erro na chamada e só.
Olhando mais pra cima no seu código
if ((res = vsnprintf(dados, aloc, format, args)) >= aloc && res >= 0) { aloc = res + 1; dados = (char*)realloc(dados, aloc); res = vsnprintf(dados, aloc, format, args); }
Se a primeira chamada deu erro res vai ser negativo e vai retornar NULL para o printf(). Só isso. Porque não faz o simples e chama perror() para saber o que houve?
Se está escrevendo dadosf() justamente para testar vsnprintf() pode fazer o programa responder suas perguntas antes...
Considere por exemplo
char* dadosf(const char* format, ...) { size_t aloc = strlen(format) - 10; // pra nao caber mesmo char* dados = (char*)malloc(aloc); va_list args; va_start(args, format); int need = vsnprintf(dados, aloc, format, args); printf("Primeira chamada retornou %d\n", need); if (need < 0) { perror("Erro na 1a chamada"); return NULL; }; if (need > aloc - 1) // nao cabe, vai truncar { printf("Necessarios %d, alocados %d. Realocando...\n", need, aloc); aloc = 1 + need; // ok, tanto quanto precisa + o zero char* p = realloc(dados, aloc); if (p == NULL) { perror("realloc falhou"); return NULL; } printf("Alocados %d. Tentando de novo...\n", aloc); dados = p; need = vsnprintf(dados, aloc, format, args); } if (need < 0) { perror("Erro na 2a chamada"); return NULL; }; va_end(args); return dados; }
E
size_t aloc = strlen(format) - 10; // pra nao caber mesmo char* dados = (char*)malloc(aloc);
Já garante que não vai caber
int need = vsnprintf(dados, aloc, format, args); printf("Primeira chamada retornou %d\n", need); if (need < 0) { perror("Erro na 1a chamada"); va_end(args); return NULL; };
Se deu erro já diga qual foi e quando
if (need > aloc - 1) // nao cabe, vai truncar { printf("Necessarios %d, alocados %d. Realocando...\n", need, aloc); aloc = 1 + need; // ok, tanto quanto precisa + o zero char* p = realloc(dados, aloc); if (p == NULL) { perror("realloc falhou"); va_end(args); return NULL; } printf("Alocados %d. Tentando de novo...\n", aloc); dados = p; need = vsnprintf(dados, aloc, format, args); }
Se não cabe aloca o necessário e tenta de novo.
main()
int main() { printf("<%s>\n", dadosf("Essa string tem 120 caracteres desconsiderando o caractere nulo.........................................................")); return 0; }
Não misture as coisas. É um teste então prepare linha a linha.
Prefira
int main() { const char* o_teste = "\ Essa string tem 120 caracteres desconsiderando o caractere n\ ulo.........................................................\ "; char* o_retorno = dadosf(o_teste); if (o_retorno == NULL) { printf(":( retornou NULL\n"); return -1; } printf("Retorno:\n\"%s\"\n", o_retorno); free(o_retorno); return 0; }
Assim
pode contar 2x60 salva o retorno testa com mais controle libera a memória alocada é mais legível... Pra que tanto pontinho?
Um outro teste
Como seu programa não formata nada vou deixar um teste que mostra a ideia de vsnprintf().
Essa é a string de entrada
char* message = "[10] '%s' [6] '%s' [10] '%s'";
E a ideia é inserir nos 3 "%s" outras strings...
int main() { char* message = "[10] '%s' [6] '%s' [10] '%s'"; char* digito = "0123456789"; char* letra = "ABCDEF"; printf("string original(%zd): \"%s\"\n", strlen(message)-6, message); size_t lim = strlen(message) - 6; testa_vsnprintf(lim + 10 + 6 + 10, message, digito, letra, digito, letra, digito); return 0; }
Essas digito e letra. Mas no teste vão 6 strings. Para isso é um teste afinal. Não pode ter menos, mas pode ter mais que 3 parâmetros...
A saída do programa
string original(22): "[10] '%s' [6] '%s' [10] '%s'" String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123456789' ] Disponivel: 49 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123456789 ] Disponivel: 48 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '012345678 ] Disponivel: 47 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '01234567 ] Disponivel: 46 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123456 ] Disponivel: 45 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '012345 ] Disponivel: 44 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '01234 ] Disponivel: 43 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0123 ] Disponivel: 42 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '012 ] Disponivel: 41 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '01 ] Disponivel: 40 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] '0 ] Disponivel: 39 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] ' ] Disponivel: 38 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] ] Disponivel: 37 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10] ] Disponivel: 36 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [10 ] Disponivel: 35 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [1 ] Disponivel: 34 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' [ ] Disponivel: 33 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' ] Disponivel: 32 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF' ] Disponivel: 31 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDEF ] Disponivel: 30 Necessario: 48 String: [[10] '0123456789' [6] 'ABCDE ] Disponivel: 29 Necessario: 48 String: [[10] '0123456789' [6] 'ABCD ] Disponivel: 28 Necessario: 48 String: [[10] '0123456789' [6] 'ABC ] Disponivel: 27 Necessario: 48 String: [[10] '0123456789' [6] 'AB ] Disponivel: 26 Necessario: 48 String: [[10] '0123456789' [6] 'A ] Disponivel: 25 Necessario: 48 String: [[10] '0123456789' [6] ' ] Disponivel: 24 Necessario: 48 String: [[10] '0123456789' [6] ] Disponivel: 23 Necessario: 48 String: [[10] '0123456789' [6] ] Disponivel: 22 Necessario: 48 String: [[10] '0123456789' [6 ] Disponivel: 21 Necessario: 48 String: [[10] '0123456789' [ ] Disponivel: 20 Necessario: 48 String: [[10] '0123456789' ] Disponivel: 19 Necessario: 48
Conforme o espaço encolhe vsprinf() corta a saída, como esperado.
void testa_vsnprintf(size_t lim, const char* msg, ... ) { char* buffer = (char*)malloc(1+lim); va_list args; va_start(args, msg); for (size_t aloc = 1+lim; aloc > lim - 30; aloc -= 1) { int res = vsnprintf(buffer, aloc, msg, args); printf("String: [%-50s] Disponivel: %zd Necessario: %d\n", buffer, aloc, res); } va_end(args); free(buffer); return; }
Sim, b0b1nh0 meu programa
-
O post de arfneto em Função recursiva em C foi marcado como solução
Recursão é um loop. Considere o simples. Ao invés do seu loop while você, a cada vez que o dividendo for maior que o divisor você soma um no quociente e divide o resto, como no papel. Só isso.
Ex: 5/2:
É claro que o quociente inicialmente é zero. 5 é maior que 2 então o quociente fica 1 e divide (5 - 2) por 2 3 é maior que 2 então o quociente fica 2 e divide (3 - 2) por 2 1 é menor 1ue 2 então acabou a divisão: o resultado é 2, popularmente chamado de quociente e o que sobrou, popularmente chamado de resto, é 1. Em C fica igualzinho -
O post de arfneto em Ponteiros com string em C foi marcado como solução
Olá!
Você deve explicar o que pretende fazer, de modo que alguém possa entender se o programa faz isso e te ajudar
Uma maneira simples é explicar o que quer fazer com TAB espaços e newlines, mostrar algumas strings antes e depois se tudo fosse como você gostaria.
Entenda que é trivial ler arquivos em C, muito mais simples que ler do teclado por exemplo, e um programa assim só faz sentido afinal se puder alinhar um texto em C, nem que seja de uma linha só.
Usando seu exemplo
char codigo[1000] = "main() {int a = 10;while(true){printf('ok');}}";
podia gerar
\tmain() { \tint a = 10; \twhile(true) \t{ \t\tprintf('ok'); \t} }
num arquivo de saida ou na tela e seria talvez mais gratificante
De volta ao programa
Use nomes mais expressivos. É difícil ter sucesso com aux e aix1 e aux2 ou codigon...
Note que C só tem uma dimensão de vetores, mas podem ser vetores de vetores....
char codigo2[1000], codigo3[1000], codigo4[1000], codigo5[1000], codigo6[1000], codigo7[1000], codigo8[1000], codigo9[1000], codigo10[1000], codigo11[1000]; char aux[1000], aux2[1000], aux3[1000], aux4[1000], aux5[1000];
podia ser
char codigo[1000][10]; char auxiliar[1000][5];
Entenda que
char indentar(char* codigo[1000]);
declara indentar() como uma função que recebe um vetor codigo com 1000 ponteiros para char, e provavelmente não é isso o que você quer. Aumentei a distância entre o tipo e o nome para ajudar a entender.
E quando chama aqui
char codigo[1000] = "main() {int a = 10;while(true){printf('ok');}}"; char codigofinal[1000]; printf("STRING ORIGINAL!\n\n"); printf("%s", &codigo); indentar(codigo);
codigo é um vetor de 1000 char. Então um dos dois está errado e o compilador vai claro reclamar
-
O post de arfneto em O que é formatted data? foi marcado como solução
Considere a diferença entre puts() e printf() e vai te ajudar a entender...
puts("Luccas");
é algo perfeitamente definido. Não há como formatar, controlar. Só vai escrever. Não por acaso é MUITO mais rápido que printf() (ou cout ou cerr em C++).
Agora considere
printf("Luccas");
É outro mundo. O sistema não sabe o que tem na string. printf() poderia ter vários argumentos. Para que? para formatar a saída.
Podia ser assim:
printf("Luccas %d\n", 42);
E acho que entendeu o que é formatado: o sistema vai ler o primeiro parâmetro de printf() e tratar de acordo. O parâmetro é uma string mas qualquer % que não seja seguido de outro vai ser tratado até esgotar a string. E vai modificar a saída.
EXEMPLO
Considere esse programa, que eu postei ontem aqui
int main(void) { printf("\ Usando CONSTANTES e %%15.10f ==> [ 11/3 = %15.10f ] e [ 3.66667 = %15.10f ]\n", 11./3., 3.66667 ); double teste = 11./3.; printf("\nUsando uma variavel para 11./3. ==> %15.10f\n", teste); printf("Usando arredondamento (%%15.5f) ==> %15.5f\n", teste); printf("\nUsando doubleN() para alguns valores\n"); char mascara[80]; for ( unsigned i = 1; i<10; i+=1) { double res = doubleN( teste, i ); printf("\nValor original usando %%15.10f ==>\t%15.10f\n", teste); printf("Usando doubleN(,%d) %%15.10f ==>\t%15.10f\n", i, res); sprintf( mascara, "Usando doubleN() %%%%15.%df ==>\t%%15.%df\n", i,i ); printf( (const char*) mascara, res); printf("Valor residual = %15.10f\n", teste - res); } return 0; }
E considere essas linhas em particular
char mascara[80]; sprintf( mascara, "Usando doubleN() %%%%15.%df ==>\t%%15.%df\n", i,i ); printf( (const char*) mascara, res);
Dentro de um loop, o valor de 'i' é usado para chamar printf() com o especificar igual `a precisão desejada, tipo %15.4f para i = 4.
E o sistema só vai saber como tratar em tempo de execução.
Note que printf() retorna um int com o total de bytes gerados na saída e esse total pode ser usado para controlar um fflush() em certas situações. Associe isso com uma outra pergunta que fez hoje
E scanf()
Como eu sempre escrevo, o teclado é um péssimo exemplo de entrada formatado porque na hora de digitar as pessoas não são assim precisas, e tem mais de 10 teclas.
Em geral, exceto pelos programas de estudantes, não se usa scanf() em stdin. Exceto.... que a entrada padrão pode ser redirecionada e esse é o ponto de scanf().
Considere a linha
programa < teste.txt
Ou
type teste.txt | programa
E então o arquivo pode ter uns dados bem formatadinhos e scanf() em programa vai tratar stdin, que não vai ser o teclado.
Programas em C raramente leem do teclado
sscanf() vs fgets()
Compare essas funções pensando no que eu escrevi sobre puts() e printf() porque não vou escrever tudo de novo. scanf() vai ler uma string entre aspas procurando por especificadores (os %) e por isso vai retornar um int entre -1 e esse número com o que conseguiu PROCESSAR considerando essa string...
Considere uma planilha como o exemplo clássico. Dados tabulares formatados.
Em C, associe scanf() a um arquivo csv e vai entender perfeitamente. Essa função foi escrita para tratar esse tipo de dados.
-
O post de arfneto em O que é formatted data? foi marcado como solução
Considere a diferença entre puts() e printf() e vai te ajudar a entender...
puts("Luccas");
é algo perfeitamente definido. Não há como formatar, controlar. Só vai escrever. Não por acaso é MUITO mais rápido que printf() (ou cout ou cerr em C++).
Agora considere
printf("Luccas");
É outro mundo. O sistema não sabe o que tem na string. printf() poderia ter vários argumentos. Para que? para formatar a saída.
Podia ser assim:
printf("Luccas %d\n", 42);
E acho que entendeu o que é formatado: o sistema vai ler o primeiro parâmetro de printf() e tratar de acordo. O parâmetro é uma string mas qualquer % que não seja seguido de outro vai ser tratado até esgotar a string. E vai modificar a saída.
EXEMPLO
Considere esse programa, que eu postei ontem aqui
int main(void) { printf("\ Usando CONSTANTES e %%15.10f ==> [ 11/3 = %15.10f ] e [ 3.66667 = %15.10f ]\n", 11./3., 3.66667 ); double teste = 11./3.; printf("\nUsando uma variavel para 11./3. ==> %15.10f\n", teste); printf("Usando arredondamento (%%15.5f) ==> %15.5f\n", teste); printf("\nUsando doubleN() para alguns valores\n"); char mascara[80]; for ( unsigned i = 1; i<10; i+=1) { double res = doubleN( teste, i ); printf("\nValor original usando %%15.10f ==>\t%15.10f\n", teste); printf("Usando doubleN(,%d) %%15.10f ==>\t%15.10f\n", i, res); sprintf( mascara, "Usando doubleN() %%%%15.%df ==>\t%%15.%df\n", i,i ); printf( (const char*) mascara, res); printf("Valor residual = %15.10f\n", teste - res); } return 0; }
E considere essas linhas em particular
char mascara[80]; sprintf( mascara, "Usando doubleN() %%%%15.%df ==>\t%%15.%df\n", i,i ); printf( (const char*) mascara, res);
Dentro de um loop, o valor de 'i' é usado para chamar printf() com o especificar igual `a precisão desejada, tipo %15.4f para i = 4.
E o sistema só vai saber como tratar em tempo de execução.
Note que printf() retorna um int com o total de bytes gerados na saída e esse total pode ser usado para controlar um fflush() em certas situações. Associe isso com uma outra pergunta que fez hoje
E scanf()
Como eu sempre escrevo, o teclado é um péssimo exemplo de entrada formatado porque na hora de digitar as pessoas não são assim precisas, e tem mais de 10 teclas.
Em geral, exceto pelos programas de estudantes, não se usa scanf() em stdin. Exceto.... que a entrada padrão pode ser redirecionada e esse é o ponto de scanf().
Considere a linha
programa < teste.txt
Ou
type teste.txt | programa
E então o arquivo pode ter uns dados bem formatadinhos e scanf() em programa vai tratar stdin, que não vai ser o teclado.
Programas em C raramente leem do teclado
sscanf() vs fgets()
Compare essas funções pensando no que eu escrevi sobre puts() e printf() porque não vou escrever tudo de novo. scanf() vai ler uma string entre aspas procurando por especificadores (os %) e por isso vai retornar um int entre -1 e esse número com o que conseguiu PROCESSAR considerando essa string...
Considere uma planilha como o exemplo clássico. Dados tabulares formatados.
Em C, associe scanf() a um arquivo csv e vai entender perfeitamente. Essa função foi escrita para tratar esse tipo de dados.
-
O post de arfneto em Lista Ligada - Adicionar e Excluir foi marcado como solução
struct no { int dado; struct no *proximo; };
Uma lista não é um nó. Um nó não é uma lista. Escrevendo assim só vai ter mais trabalho. MUITO mais trabalho.
Você esta usando funções que retornam void() e não tem argumentos. É uma ideia ruim. Cada função dessas é um buraco negro.
Nada entra e nada sai. Só usam valores globais e isso é um desastre. Se funcionar. E quando funcionar. E vai demorar.
Use argumentos. Retorne valores.
Sobre a lista
é mais fácil usar dois ponteiros. Tudo fica mais difícil quando os nós só tem ponteiros para um lado. Como você já deve ter descoberto toda hora tem que voltar pro início e se reposicionar.
É conveniente manter na lista o tamanho e um ponteiro para o inicio e para o fim. É o simples.
-
O post de arfneto em Como posso colocar as variaveis que recebo em um scopo Global foi marcado como solução
Não sei se entendi, mas está tentando ler um arquivo csv?
Porque não posta um exemplo da entrada, com umas poucas linhas? Ficaria mais fácil de alguém ajudar.
Se ainda não aprendeu a colocar coisas em um escopo global, nem tente: é péssima ideia. Proibido em guias de boas práticas, empresas, escolas...
O que se procura na verdade é o contrário, diminuir o escopo das coisas. Por essa razão por exemplo desde os anos 80 se pode declarar variáveis em um for em C. C++ sempre teve isso.
E em C++14 eu acho passou a ser possível declarar variáveis dentro de um switch ou while. E lembro que qualquer bloco de chaves serve exatamente para delimitar um novo escopo em C++, mesmo que seja no meio de uma função...
O escopo global inclui tudo que está solto pelo código, como aquelas coisas declaradas fora de main(). Mas escrevo de novo: nunca faça isso. Pode custar sua nota ou seu emprego. E no mínimo via custar seu tempo: é um pesadelo de manutenção. Nem todos seus programas vão ter 30 linhas e 1 função.
O que você quer fazer é passar argumentos. Só isso.
Sua função split() aparentemente deveria retornar um vetor de strings definido a partir do arquivo de entrada. Então o simples é passar para ela o nome do arquivo e receber o vetor.
De volta ao seu programa
Seu programa parece ter sido inspirado em C e não em C++, e está muito complicado sem necessidade. Há maneiras bem mais simples de escrever isso em C++.
Pode postar algum detalhe da entrada?
-
O post de arfneto em Como posso colocar as variaveis que recebo em um scopo Global foi marcado como solução
Não sei se entendi, mas está tentando ler um arquivo csv?
Porque não posta um exemplo da entrada, com umas poucas linhas? Ficaria mais fácil de alguém ajudar.
Se ainda não aprendeu a colocar coisas em um escopo global, nem tente: é péssima ideia. Proibido em guias de boas práticas, empresas, escolas...
O que se procura na verdade é o contrário, diminuir o escopo das coisas. Por essa razão por exemplo desde os anos 80 se pode declarar variáveis em um for em C. C++ sempre teve isso.
E em C++14 eu acho passou a ser possível declarar variáveis dentro de um switch ou while. E lembro que qualquer bloco de chaves serve exatamente para delimitar um novo escopo em C++, mesmo que seja no meio de uma função...
O escopo global inclui tudo que está solto pelo código, como aquelas coisas declaradas fora de main(). Mas escrevo de novo: nunca faça isso. Pode custar sua nota ou seu emprego. E no mínimo via custar seu tempo: é um pesadelo de manutenção. Nem todos seus programas vão ter 30 linhas e 1 função.
O que você quer fazer é passar argumentos. Só isso.
Sua função split() aparentemente deveria retornar um vetor de strings definido a partir do arquivo de entrada. Então o simples é passar para ela o nome do arquivo e receber o vetor.
De volta ao seu programa
Seu programa parece ter sido inspirado em C e não em C++, e está muito complicado sem necessidade. Há maneiras bem mais simples de escrever isso em C++.
Pode postar algum detalhe da entrada?
-
O post de arfneto em ordenação de vetores bucket sort foi marcado como solução
Talvez não tenha afinal levado a sério as coisas que falei no tópico #3, afinal não incorporou muito aos seus programas.
Entre as coisas que continua fazendo e que só vão te atrasar, direto do #3:
nunca use um programa interativo para testar nada. Só coloque menus e leituras do teclado quando a lógica estiver testada. Só vai perder tempo com isso.
teste SEMPRE o retorno de scanf(). Qual o propósito de seguir com o programa se não conseguiu ler algo? Tem um livro? Seu IDE mostra o protótipo das funções? Leu algo sobre scanf()?
não use void. É um desperdício. Retorne algo.
nunca use variáveis de controle de um loop fora dele a menos que tenha uma razão séria para isso. E se tem uma razão séria, não chame essa variável de 'i' por exemplo. Isso é uma bomba relógio. Essa variável fica viva na função toda. Levou uns anos para corrigirem isso na linguagem, mas foi feito. Nos anos 80.
não misture lógica com formatação e leitura. Só vai atrasar tudo.
main() deve ser a primeira função de seu programa. Sempre. Se possível em um arquivo separado. É mais produtivo para você e para quem vá ler seu programa.
Deixe os #define SEMPRE antes dos #include
Eu já te perguntei isso antes e você não respondeu. Que significa esse lance de vetores aleatórios ou decrescentes?
O que significa?
Os vetores NADA tem a ver com seu programa. Nada. O sort vai ordenar os vetores. Só isso. Tanto faz se já está em ordem, ou se a ordem é aleatória ou se tem 100 ou 100 mil números. Nada tem a ver com o bucket sort. Ou com qualquer sort.
Entendeu o que eu quiz dizer sobre isso:
typedef struct { int capacidade; int em_uso; // quando esgotar aloca uma igual quantia Bloco** V; } Controle;
Nada perguntou mas também não usou.
A questão dos vetores:
Inicialmente você estava lendo os dados com fscanf() e não há razão para não funcionar assim:
int v[n]; for(i=0;i<n;i++) { fscanf(f,"%d ",&v[i]); }
Mas como eu te expliquei não pode declarar v[n]. Como estamos falando de programas para iniciantes acho que não seria o fim do mundo declarar um vetor do maior tamanho afinal, e usar
v[ 100 * 1000 ]; int tamanho = 0; // ... for(i=0;i<tamanho;i++) { fscanf(f,"%d ",&v[i]); }
E acho que agora dá pra entender o porque da estrutura Controle que eu te mostrei acima... em_uso seria o tamanho, capacidade seria 100.000. Sobre os 100 * 1000 entenda que é muito mais fácil de ler assim e o compilador sabe multiplicar direitinho, de modo que isso não irá para seu código assim. Usando a estrutura você cria o valor dinâmicamente do tamanho certo, e eu expliquei como
É muito mais fácil ler de um arquivo que ler do teclado. No entanto saber a ordem interna dos dados no vetor nada significa. Não entendo sequer porque tem isso no enunciado.
Bucket sort e fazer duas vezes a mesma coisa
Acho que eu já falei disso duas vezes: os dados estão em um arquivo e você quer usar esse bucket sort. Se você ler os valores e colocar todos em um vetor e DEPOIS ler o vetor e colocar os MESMOS dados em buckets de novo não será algo assim inteligente: vai estar usando o dobro de memória, por exemplo., E quase a toa. Para 1.000 caras vai ler os 1.000 do arquivo e gravar nesse vetor v e aí vai alocar digamos 15 buckets de um certo tamanho e colocar OS MESMOS dados nesses buckets e então classificar. E DEPOIS classificar os buckets e juntar os dados de volta no vetor original? E nem vai gravar o arquivo no disco, e assim perder todo o trabalho?
Bucket sort e o número de buckets
No caso de vetores decrescentes parece que você usa o calculo do número de buckets dividindo o total pelo tamanho e é, claro, ingênuo, Mas está certo. Só que não há sentido em prever o conteúdo dos dados em um vetor que você nem leu ainda, e o algoritmo não pode se basear nessa fé. Se o cara editar lá e trocar um valor vai reclamar de quem?
No caso de valores aleatórios, como calcular o tamanho dos buckets? você parece ter usado a mesma constante TAM. E o número deles variando por uma proporção entre o maior e o menor valor... Só que isso é pouco.
Pense nesse vetor
1 2 3 4 5 5000 6000 7000 7001 90000 90100 90200
Tem uma dúzia de valores. Quantos baldes vai usar? 90200-1/TAM daria 9000..
O que posso dizer? Use um programa para isso. Não vai ter 20 linhas. E claro escreva um outro para ler os valores, recortar e colar. Afinal vai querer fazer isso logo em seguida, certo?
Como criar um vetor de números decrescentes?
Não. Algo conveniente seria um programa assim, digamos cria, que se você chama
cria
ele assume 100 registros e cria "vetor.txt" com 100 registro de 100 a 1.
Mas se você usa
cria outro.txt
Ele cria "outro.txt" no diretório corrente e com 100 registros.
Mas se você usa
cria vetor_novo.txt 234
ele faz o esperado e cria "vetor_novo.txt" no diretório corrente e com 234 números.
Assim pode criar todos seus arquivos de teste.
Seria complicado escrever um programa desses?
Não. Veja um abaixo, onde boa parte é comentário e só não é bem menor porque tem a frescura de mostrar um certo número de itens em cada linha e tem a parada de aceitar os argumentos para não ter que ficar renomeando arquivos para os testes
# include <stdio.h> # include <stdlib.h> # include <string.h> // // sem argumentos gera vetor.txt com 100 registros // com 1 argumento e o nome do arquivo: ex: cria vetor199.txt // com 2 argumentos o segundo e o tamanho: // ex: cria coisa.txt 27 cria "coisa.txt" com 27 itens, // em ordem decrescente, de 27 a 1 // int main( int argc, char** argv ) { const char* nome_padrao = "vetor.txt"; const int tamanho_padrao = 100; char arquivo[80]; // o nome do arquivo de saida int tamanho = 0; if ( argc > 1 ) strcpy( arquivo, argv[1] ); else strcpy( arquivo, nome_padrao ); if ( argc > 2 ) tamanho = atoi(argv[2] ); else tamanho = tamanho_padrao; // resolvido nome e tamanho do arquivo, mostra printf( "Vai criar \"%s\" com %d registros\n", arquivo, tamanho ); // cria o arquivo FILE* F = fopen( arquivo, "w" ); int nc = 5; // numeros por linha no arquivo int col = 1; // vai gravar nc por coluna for( int i = tamanho; i>0; i-=1 ) { if ( col < nc ) col += 1, fprintf( F, "%d ", i ); else col = 1, fprintf( F, "%d\n", i ); }; // for // se nao era multiplo de nc termina a linha pra ficar bonitinho if ( tamanho % nc != 0 ) fprintf( F, "\n"); return 0; }
Como ficaria rodando?
Exemplo: "cria outro.txt 23" mostra
dsp$ ./cria outro.txt 23 Vai criar "outro.txt" com 23 registros dsp$
E em "outro.txt" tem
23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
E se fosse para criar com valores aleatórios?
Seria igualzinho, já que a lógica é a mesma. No entanto tem uma pegadinha: o retorno de rand(), a função que em geral se usa para obter os tais números aleatórios, retorna um valor entre 0 e RAND_MAX, como está no manual.
Da documentação da Microsoft, em Português:
Só que queremos um vetor de int. Isso quer dizer que podem ser 4 ou 8 bytes e COM SINAL. A única garantia em C é que RAND_MAX é no mínimo 32767. Dois bytes. Então precisa de alguma jogada para montar o número.
E daí?
Se pode usar algo assim pra resolver, afinal esse é um programa de sort e isso é secundário:
int valor = ( (short)rand()<<16 ) + (short) rand(); // pra preencher o int
Um exemplo assim em C
E se usasse "criardm aleatorio.txt 35" veria
dsp$ ./criardm aleatorio.txt 35 Vai criar "aleatorio.txt" com 35 registros dsp$
E no arquivo teria os 35 valores
581546329 -277800741 847322731 -2057878319 1977984709 1224861824 -648456269 -658964460 -1351813603 2045275211 543477221 -2010931532 -1384290036 -683515769 -1304649299 -1012017945 1392882464 -306018936 -779390182 -900118671 434115419 804320057 1796147370 -212985220 -20484810 -2033770708 991629035 -1109399400 2012648739 1226779188 919604430 -14972458 -1074926369 257790329 1610144184
E como ler um trem desses?
Claro, abre o arquivo e usa um loop. Recortar e colar desse programa acima é simples, porque é quase a mesma coisa
Eis uma versão
# include <limits.h> # include <stdio.h> # include <stdlib.h> # include <string.h> // // sem argumentos tenta ler vetor.txt // com 1 argumento e o nome do arquivo // int main( int argc, char** argv ) { const char* nome_padrao = "vetor.txt"; char arquivo[80]; // o nome do arquivo de saida int tamanho = 0; if ( argc > 1 ) strcpy( arquivo, argv[1] ); else strcpy( arquivo, nome_padrao ); printf( "Vai ler \"%s\"\n", arquivo ); FILE* F = fopen( arquivo, "r" ); if ( F == NULL ) return -1; int nc = 5; // numeros por linha na saida int col = 1; // vai gravar nc por coluna int valor = 0; int menor = INT_MAX; int maior = INT_MIN; int res = fscanf( F, "%d", &valor ); while ( res == 1 ) { tamanho += 1; if (valor > maior) maior = valor; if (valor < menor) menor = valor; if ( col < nc ) col += 1, printf( "%13d", valor ); else col = 1, printf( "%13d\n", valor ); res = fscanf( F, "%d", &valor ); }; // for printf("\nLidos %d valores, nenor = %d, maior = %d\n", tamanho, menor, maior ); fclose(F); return 0; }
Como a gente não sabe quantos tem o while() pode ser melhor que o for. E já que estamos lendo não custa nada contar quantos tem e mostrar o maior e o menor, porque certamente vai querer saber isso para o bucket sort, certo?
Eis o resultado para a leitura do arquivo acima, aleatorio.txt
dsp$ ./lev aleatorio.txt Vai ler "aleatorio.txt" 581546329 -277800741 847322731 -2057878319 1977984709 1224861824 -648456269 -658964460 -1351813603 2045275211 543477221 -2010931532 -1384290036 -683515769 -1304649299 -1012017945 1392882464 -306018936 -779390182 -900118671 434115419 804320057 1796147370 -212985220 -20484810 -2033770708 991629035 -1109399400 2012648739 1226779188 919604430 -14972458 -1074926369 257790329 1610144184 Lidos 35 valores, nenor = -2057878319, maior = 2045275211 dsp$
-
O post de arfneto em ordenação de vetores bucket sort foi marcado como solução
Talvez não tenha afinal levado a sério as coisas que falei no tópico #3, afinal não incorporou muito aos seus programas.
Entre as coisas que continua fazendo e que só vão te atrasar, direto do #3:
nunca use um programa interativo para testar nada. Só coloque menus e leituras do teclado quando a lógica estiver testada. Só vai perder tempo com isso.
teste SEMPRE o retorno de scanf(). Qual o propósito de seguir com o programa se não conseguiu ler algo? Tem um livro? Seu IDE mostra o protótipo das funções? Leu algo sobre scanf()?
não use void. É um desperdício. Retorne algo.
nunca use variáveis de controle de um loop fora dele a menos que tenha uma razão séria para isso. E se tem uma razão séria, não chame essa variável de 'i' por exemplo. Isso é uma bomba relógio. Essa variável fica viva na função toda. Levou uns anos para corrigirem isso na linguagem, mas foi feito. Nos anos 80.
não misture lógica com formatação e leitura. Só vai atrasar tudo.
main() deve ser a primeira função de seu programa. Sempre. Se possível em um arquivo separado. É mais produtivo para você e para quem vá ler seu programa.
Deixe os #define SEMPRE antes dos #include
Eu já te perguntei isso antes e você não respondeu. Que significa esse lance de vetores aleatórios ou decrescentes?
O que significa?
Os vetores NADA tem a ver com seu programa. Nada. O sort vai ordenar os vetores. Só isso. Tanto faz se já está em ordem, ou se a ordem é aleatória ou se tem 100 ou 100 mil números. Nada tem a ver com o bucket sort. Ou com qualquer sort.
Entendeu o que eu quiz dizer sobre isso:
typedef struct { int capacidade; int em_uso; // quando esgotar aloca uma igual quantia Bloco** V; } Controle;
Nada perguntou mas também não usou.
A questão dos vetores:
Inicialmente você estava lendo os dados com fscanf() e não há razão para não funcionar assim:
int v[n]; for(i=0;i<n;i++) { fscanf(f,"%d ",&v[i]); }
Mas como eu te expliquei não pode declarar v[n]. Como estamos falando de programas para iniciantes acho que não seria o fim do mundo declarar um vetor do maior tamanho afinal, e usar
v[ 100 * 1000 ]; int tamanho = 0; // ... for(i=0;i<tamanho;i++) { fscanf(f,"%d ",&v[i]); }
E acho que agora dá pra entender o porque da estrutura Controle que eu te mostrei acima... em_uso seria o tamanho, capacidade seria 100.000. Sobre os 100 * 1000 entenda que é muito mais fácil de ler assim e o compilador sabe multiplicar direitinho, de modo que isso não irá para seu código assim. Usando a estrutura você cria o valor dinâmicamente do tamanho certo, e eu expliquei como
É muito mais fácil ler de um arquivo que ler do teclado. No entanto saber a ordem interna dos dados no vetor nada significa. Não entendo sequer porque tem isso no enunciado.
Bucket sort e fazer duas vezes a mesma coisa
Acho que eu já falei disso duas vezes: os dados estão em um arquivo e você quer usar esse bucket sort. Se você ler os valores e colocar todos em um vetor e DEPOIS ler o vetor e colocar os MESMOS dados em buckets de novo não será algo assim inteligente: vai estar usando o dobro de memória, por exemplo., E quase a toa. Para 1.000 caras vai ler os 1.000 do arquivo e gravar nesse vetor v e aí vai alocar digamos 15 buckets de um certo tamanho e colocar OS MESMOS dados nesses buckets e então classificar. E DEPOIS classificar os buckets e juntar os dados de volta no vetor original? E nem vai gravar o arquivo no disco, e assim perder todo o trabalho?
Bucket sort e o número de buckets
No caso de vetores decrescentes parece que você usa o calculo do número de buckets dividindo o total pelo tamanho e é, claro, ingênuo, Mas está certo. Só que não há sentido em prever o conteúdo dos dados em um vetor que você nem leu ainda, e o algoritmo não pode se basear nessa fé. Se o cara editar lá e trocar um valor vai reclamar de quem?
No caso de valores aleatórios, como calcular o tamanho dos buckets? você parece ter usado a mesma constante TAM. E o número deles variando por uma proporção entre o maior e o menor valor... Só que isso é pouco.
Pense nesse vetor
1 2 3 4 5 5000 6000 7000 7001 90000 90100 90200
Tem uma dúzia de valores. Quantos baldes vai usar? 90200-1/TAM daria 9000..
O que posso dizer? Use um programa para isso. Não vai ter 20 linhas. E claro escreva um outro para ler os valores, recortar e colar. Afinal vai querer fazer isso logo em seguida, certo?
Como criar um vetor de números decrescentes?
Não. Algo conveniente seria um programa assim, digamos cria, que se você chama
cria
ele assume 100 registros e cria "vetor.txt" com 100 registro de 100 a 1.
Mas se você usa
cria outro.txt
Ele cria "outro.txt" no diretório corrente e com 100 registros.
Mas se você usa
cria vetor_novo.txt 234
ele faz o esperado e cria "vetor_novo.txt" no diretório corrente e com 234 números.
Assim pode criar todos seus arquivos de teste.
Seria complicado escrever um programa desses?
Não. Veja um abaixo, onde boa parte é comentário e só não é bem menor porque tem a frescura de mostrar um certo número de itens em cada linha e tem a parada de aceitar os argumentos para não ter que ficar renomeando arquivos para os testes
# include <stdio.h> # include <stdlib.h> # include <string.h> // // sem argumentos gera vetor.txt com 100 registros // com 1 argumento e o nome do arquivo: ex: cria vetor199.txt // com 2 argumentos o segundo e o tamanho: // ex: cria coisa.txt 27 cria "coisa.txt" com 27 itens, // em ordem decrescente, de 27 a 1 // int main( int argc, char** argv ) { const char* nome_padrao = "vetor.txt"; const int tamanho_padrao = 100; char arquivo[80]; // o nome do arquivo de saida int tamanho = 0; if ( argc > 1 ) strcpy( arquivo, argv[1] ); else strcpy( arquivo, nome_padrao ); if ( argc > 2 ) tamanho = atoi(argv[2] ); else tamanho = tamanho_padrao; // resolvido nome e tamanho do arquivo, mostra printf( "Vai criar \"%s\" com %d registros\n", arquivo, tamanho ); // cria o arquivo FILE* F = fopen( arquivo, "w" ); int nc = 5; // numeros por linha no arquivo int col = 1; // vai gravar nc por coluna for( int i = tamanho; i>0; i-=1 ) { if ( col < nc ) col += 1, fprintf( F, "%d ", i ); else col = 1, fprintf( F, "%d\n", i ); }; // for // se nao era multiplo de nc termina a linha pra ficar bonitinho if ( tamanho % nc != 0 ) fprintf( F, "\n"); return 0; }
Como ficaria rodando?
Exemplo: "cria outro.txt 23" mostra
dsp$ ./cria outro.txt 23 Vai criar "outro.txt" com 23 registros dsp$
E em "outro.txt" tem
23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
E se fosse para criar com valores aleatórios?
Seria igualzinho, já que a lógica é a mesma. No entanto tem uma pegadinha: o retorno de rand(), a função que em geral se usa para obter os tais números aleatórios, retorna um valor entre 0 e RAND_MAX, como está no manual.
Da documentação da Microsoft, em Português:
Só que queremos um vetor de int. Isso quer dizer que podem ser 4 ou 8 bytes e COM SINAL. A única garantia em C é que RAND_MAX é no mínimo 32767. Dois bytes. Então precisa de alguma jogada para montar o número.
E daí?
Se pode usar algo assim pra resolver, afinal esse é um programa de sort e isso é secundário:
int valor = ( (short)rand()<<16 ) + (short) rand(); // pra preencher o int
Um exemplo assim em C
E se usasse "criardm aleatorio.txt 35" veria
dsp$ ./criardm aleatorio.txt 35 Vai criar "aleatorio.txt" com 35 registros dsp$
E no arquivo teria os 35 valores
581546329 -277800741 847322731 -2057878319 1977984709 1224861824 -648456269 -658964460 -1351813603 2045275211 543477221 -2010931532 -1384290036 -683515769 -1304649299 -1012017945 1392882464 -306018936 -779390182 -900118671 434115419 804320057 1796147370 -212985220 -20484810 -2033770708 991629035 -1109399400 2012648739 1226779188 919604430 -14972458 -1074926369 257790329 1610144184
E como ler um trem desses?
Claro, abre o arquivo e usa um loop. Recortar e colar desse programa acima é simples, porque é quase a mesma coisa
Eis uma versão
# include <limits.h> # include <stdio.h> # include <stdlib.h> # include <string.h> // // sem argumentos tenta ler vetor.txt // com 1 argumento e o nome do arquivo // int main( int argc, char** argv ) { const char* nome_padrao = "vetor.txt"; char arquivo[80]; // o nome do arquivo de saida int tamanho = 0; if ( argc > 1 ) strcpy( arquivo, argv[1] ); else strcpy( arquivo, nome_padrao ); printf( "Vai ler \"%s\"\n", arquivo ); FILE* F = fopen( arquivo, "r" ); if ( F == NULL ) return -1; int nc = 5; // numeros por linha na saida int col = 1; // vai gravar nc por coluna int valor = 0; int menor = INT_MAX; int maior = INT_MIN; int res = fscanf( F, "%d", &valor ); while ( res == 1 ) { tamanho += 1; if (valor > maior) maior = valor; if (valor < menor) menor = valor; if ( col < nc ) col += 1, printf( "%13d", valor ); else col = 1, printf( "%13d\n", valor ); res = fscanf( F, "%d", &valor ); }; // for printf("\nLidos %d valores, nenor = %d, maior = %d\n", tamanho, menor, maior ); fclose(F); return 0; }
Como a gente não sabe quantos tem o while() pode ser melhor que o for. E já que estamos lendo não custa nada contar quantos tem e mostrar o maior e o menor, porque certamente vai querer saber isso para o bucket sort, certo?
Eis o resultado para a leitura do arquivo acima, aleatorio.txt
dsp$ ./lev aleatorio.txt Vai ler "aleatorio.txt" 581546329 -277800741 847322731 -2057878319 1977984709 1224861824 -648456269 -658964460 -1351813603 2045275211 543477221 -2010931532 -1384290036 -683515769 -1304649299 -1012017945 1392882464 -306018936 -779390182 -900118671 434115419 804320057 1796147370 -212985220 -20484810 -2033770708 991629035 -1109399400 2012648739 1226779188 919604430 -14972458 -1074926369 257790329 1610144184 Lidos 35 valores, nenor = -2057878319, maior = 2045275211 dsp$
-
O post de arfneto em Funções fflush, _flushall, _fflush_nolock foi marcado como solução
Antes de tudo considere que fflush() só se aplica a arquivos --- fluxos, streams --- de saída. Pode funcionar na entrada para alguns compiladores mas pela documentação oficial isso gera comportamento indefinido --- UB, undefined behavior --- como aparece nos livros e na documentação padrão
Provavelmente nada de ruim.
Mas um iniciante não tem razão para usar isso num programa, a menos que esteja sendo mal "iniciado". Programas, de iniciantes ou profissionais, devem consumir as entradas e gerar as saídas, conforme o propósito de cada programa. Nada mais. E saber o que está onde e porque.
Os sistemas são muito bons em tratar os buffers. Esses mecanismos como fflush() e setbuf() existem para situações que o sistema não pode prever ou entender. Vou dar uns exemplos depois.
O grande incentivo de fflush() para iniciantes --- assim como de setbuf() com 0 --- é limpar a entrada do teclado porque o iniciante não foi informado de que deve consumir tudo o que está na entrada. O sistema não sabe o que é uma entrada e se limita e ler as teclas e guardar no tal buffer, aquela entidade mágica que zoa os programas dos iniciantes e faz o programa seguir sem ler as coisas ou mesmo ler coisas que "ninguém" digitou.
stdin e stdout sempre usam buffers, e seria 1d10t@ não usar por uma questão de simples eficiência. stderr geralmente não, porque não seria esperto. Se não usassem buffers na entrada você não poderia por exemplo usar backspace e ficar editando a linha de entrada antes de teclar ENTER, certo?
Mas em alguns casos, como quando está digitando uma senha ou em algum jogo, se pode querer desligar isso, e está bem documentado tanto para Linux -- e MacOS e Unix e Android --- ou Windows. Em Windows se desliga LINE_INPUT chamando SetConsoleMode() e no Linux se chama ioctl() e manipula os valores da estrutura termio. Estou escrevendo de memória e se precisar de uma referência escreva de volta.
Mas em geral iniciantes não precisam disso.
E o "lixo" do teclado
Não existe "lixo de teclado", "lixo no buffer" ou coisas assim. Existem talvez livros ruins, instrutores com preguiça ou ruins mesmo, livros ruins e coisas assim.
Não é possível.
Você provavelmente entendeu errado ou talvez leu alguma tradução tosca. Não se trata de somente stdout. E não se trata de limpar e sim de descarregar
Se o argumento for NULL fflush() limpa os buffers de todos os fluxos abertos. TODOS. Inclusive stdout claro. E isso não quer dizer apagar. Quer dizer descarregar. fflush() só está definido para fluxos de saída, e por isso se acaso funcione na entrada em alguma implementação, como a stdio da Microsoft, acaba apagando tudo como se algo tivesse lido tudo o que tinha no buffer, por simples analogia
Mais a seguir.
Não, não seria.
_fflush_nolock() nada tem a ver com os fluxos abertos em seu programa ou com sincronismo. É uma versão de fflush() que, no caso de seu programa ter múltiplos threads --- rodar várias funções ao mesmo tempo --- não bloqueia todas até o flush terminar, que é o que fflush() faz por padrão.
Exemplo
Se
você tiver um programa que emite notas fiscais, e ele emite até 10 notas ao mesmo tempo em 10 threads separados faz cálculos com arquivos de cliente e preços e tal ao terminar de preparar a nota TODOS threads enviam os dados para uma única função de impressão que acessa as impressoras e faz todo o resto, como gravar log e backup só essa função grava em disco e acessa as impressoras Então
Num dado momento pode ser preciso rodar um flush para liberar as impressoras e imprimir o que está pronto, por alguma condição especial, como uma mudança de horário ou de formulário nas impressoras. O desenvolvedor sabe que só esse thread acessa os arquivos não há razão para bloquear todos os outros então é seguro e bem mais rápido usar _fflush_nolock() para esvaziar a saída. Esse é a razão do nolock: thread locking. Só o cara que escreve o programa sabe se pode usar NOLOCK, claro. O sistema não vai saber. Num programa comum, single-threaded, isso não faz a menor diferença, porque não vai travar ninguém mesmo já que só existe um caminho de execução
Provavelmente o termo correto seria, como eu disse, a tradução normal de flush: descarregar. Como eu disse, flush não apaga nada.
Veja o que diz a Microsoft sobre isso:
A função fflush libera o fluxo de fluxo. Se o fluxo foi aberto no modo de gravação ou se ele foi aberto no modo de atualização e a última operação foi uma gravação, o conteúdo do buffer de fluxo é gravado no arquivo subjacente ou o dispositivo e o buffer são descartados. Se o fluxo tiver sido aberto no modo de leitura ou se o fluxo não tiver buffer, a chamada para fflush não terá efeito e qualquer buffer será retido. Uma chamada para fflush nega o efeito de qualquer chamada anterior ao ungetc para o fluxo. O fluxo permanecerá aberto após a chamada. Se o fluxo for nulo, o comportamento será o mesmo que uma chamada para fflush em cada fluxo aberto. Todos os fluxos abertos no modo de gravação e todos os fluxos abertos no modo de atualização em que a última operação foi uma gravação são liberados. A chamada não tem efeito em outros fluxos.
E o gnu
Recomendo muito consultar a documentação, sempre.
Se é assim, pra que serve um flush() afinal?
Imagine que você tem um programa que transmite uma mensagem pela placa de rede, via TCP/IP, e quer enviar no máximo 1500 bytes por vez. O sistema sabe isso, o valor de MAX_MTU. Quando chegar a isso o driver vai automaticamente transmitir a mensagem. Imagine que você tem uma impressora que imprime linhas de até 132 colunas, como nos anos 80. Assim que tiver uma linha no buffer ela imprime e começa a colocar os dados na próxima. Imagine que você tem um painel LCD ligado ao seu micro, e ele tem uma linha de 80 colunas. Você vai colocando as letras no buffer. Quando dá 80 o driver manda as linhas para o LCD e aparece lá na vitrine. Imagine que você tem um furgão e ele aceita 1200KG de carga. O sistema de saída quando chega ao peso libera a emissão do manifesto de carga e libera a carga para expedição. Isso é o normal. O que seria um flush() nesses casos?
Você sabe que só tem 7 letras, mas quer mandar pro LCD aquela linha: "FECHADO". Você quer despachar o furgão com 300 kg porque ele tem prazo pra sair e o cliente contratou a carga expressa Você quer imprimir uma linha em branco na line printer dos anos 80 Para essas coisas você faz um flush() do buffer correspondente e o sistema descarrega tudo pra saída. Para as outras coisas use seu cartão Mastercard . Ok, essa foi pobre
Recomendo ler o que eu postei, e talvez a documentação do Unix/Linux/Mac/Windows.
Não é como está imaginando. _flush_nolock por exemplo não é função Windows, está disponível em UNIX e variantes e Windows para qualquer linguagem. São primitivas de I/O essenciais.
NOLOCK tem a ver com multi-threading e não com falhas de sistema. Leia isso por exemplo em https://www.gnu.org/software/libc/manual/html_node/Buffering-Concepts.html
Um programa em user space pode ser multi-threading e usar lock/nolock em flush, e pode usar flush() em centenas de arquivos. Nada tem a ver com proximidade do kernel.
Não, não são. Citei acima a documentação do GNU, mas pode ver aqui um trecho da documentação do Ubuntu 20 e a referência às versões unlocked de stdio:
UNLOCKED_STDIO(3) Linux Programmer's Manual UNLOCKED_STDIO(3) NAME getc_unlocked, getchar_unlocked, putc_unlocked, putchar_unlocked - nonlocking stdio functions SYNOPSIS #include <stdio.h> int getc_unlocked(FILE *stream); int getchar_unlocked(void); int putc_unlocked(int c, FILE *stream); int putchar_unlocked(int c); void clearerr_unlocked(FILE *stream); int feof_unlocked(FILE *stream); int ferror_unlocked(FILE *stream); int fileno_unlocked(FILE *stream); int fflush_unlocked(FILE *stream); int fgetc_unlocked(FILE *stream); int fputc_unlocked(int c, FILE *stream); size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *stream); size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *stream); char *fgets_unlocked(char *s, int n, FILE *stream); int fputs_unlocked(const char *s, FILE *stream); #include <wchar.h>
-
O post de arfneto em Estou precisando novamente em no auxilio no meu codigo c++ foi marcado como solução
Use o botão code para formatar seu programa. Fica difícil para alguém copiar assim como você fez.
Leia os dois valores de uma vez. É mais seguro e melhor para quem usa o programa.
Porque usou ponteiros em todo lugar? não é preciso: os argumentos são pequenos, mínimos. E em C++ seria melhor usar referências...
-
O post de arfneto em Pilhas dinâmicas - Inverter e verificar elementos foi marcado como solução
Leu a parte que vem depois de "o programa todo"?
Rodou em sua máquina? Trata-se de um programa completo em C. No #4 tem um programa completo em C++. E tem a saída deles e o comando para compilar logo em seguida...
O que falta? Não perguntou nadinha... 🤔
-
O post de arfneto em Pilhas dinâmicas - Inverter e verificar elementos foi marcado como solução
Leu a parte que vem depois de "o programa todo"?
Rodou em sua máquina? Trata-se de um programa completo em C. No #4 tem um programa completo em C++. E tem a saída deles e o comando para compilar logo em seguida...
O que falta? Não perguntou nadinha... 🤔
-
O post de arfneto em exercicio de programacao em C foi marcado como solução
Se não vai usar uma função para calcular a soma --- clássico --- pode ser mais compacto escrever como a fórmula simplesmente:
include <math.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int N = 9; if ( argc > 1 ) { N = atoi(argv[1]); if ( N < 1 ) N = 9; } printf( "Definido o valor de N: %d\n", N ); for( int x = 0, K = 1; x<=N; x = x + 1, K = K + 10) { double PI = 0.; for ( int i = 1; i<=K; i+=1 ) PI += ( 6. / (double)(i * i) ); printf( "Para K = %3d temos pi ~= %18.15f\n", K, sqrt(PI) ); }; };
Note que nessa versão se você digitar simplesmente o nome do programa ele assume nove para ficar igualzinho ao seu exemplo, mas pode digitar o valor que preferir, direto na linha de comando.
EXEMPLOS usando o programa como acima
PS C:\src\CPP\flt> PS C:\src\CPP\flt> gcc -o tst -Wall -std=c17 pi.c PS C:\src\CPP\flt> PS C:\src\CPP\flt> ./tst 1 Definido o valor de N: 1 Para K = 1 temos pi ~= 2.449489742783178 Para K = 11 temos pi ~= 3.057481506707563 PS C:\src\CPP\flt>
tst 1 roda duas vezes, como previsto
PS C:\src\CPP\flt> ./tst Definido o valor de N: 9 Para K = 1 temos pi ~= 2.449489742783178 Para K = 11 temos pi ~= 3.057481506707563 Para K = 21 temos pi ~= 3.096866949943929 Para K = 31 temos pi ~= 3.111132302228169 Para K = 41 temos pi ~= 3.118498530066566 Para K = 51 temos pi ~= 3.122995870443019 Para K = 61 temos pi ~= 3.126027123173503 Para K = 71 temos pi ~= 3.128208702272254 Para K = 81 temos pi ~= 3.129853941123618 Para K = 91 temos pi ~= 3.131138975398556 PS C:\src\CPP\flt>
Sem parâmetros assume 9 para ficar igual ao exemplo
PS C:\src\CPP\flt> ./tst 5000 ... ... Para K = 49971 temos pi ~= 3.141570286351500 Para K = 49981 temos pi ~= 3.141570281038376 Para K = 49991 temos pi ~= 3.141570275722297 Para K = 50001 temos pi ~= 3.141570270403256 PS C:\src\CPP\flt>
Para 5000 escreve um monte mas termina mais perto de PI. O valor para 15 dígitos é com 3.141592653589793 e essa série converge bem devagar
Se quiser ir um pouco mais longe com a série use double para o cálculo do quadrado de i e veja até onde 6/(i*i) é um valor válido...
-
O post de arfneto em Definição do elemento MINMAX. foi marcado como solução
@Alastor145 em C++ isso provavelmente acabaria escrito de outro modo, porque é mais fácil usar uma classe e criar um método que devolve o tal MINMAX direto, para qualquer tamanho da matriz.
E a matriz seria criada no construtor provavelmente a partir dos parâmetros óbvios. linha e coluna. E destruída na saída.
Eis um exemplo do que quer fazer, mais do lado C do que do lado C++, e usando o modo mais eficiente, avaliando o minmax enquanto preenche a matriz
#include <iomanip> #include <iostream> using namespace std; int mostra(int[][7], int,int); int main (void) { int matriz[4][7]; int maximo = INT_MIN; int minimo = INT_MAX; srand (210306); for(int i=0; i<4; i++) { int maximo_l = INT_MIN; // maior na linha int minimo_l = INT_MAX; // menor na linha for(int j=0; j<7; j++) { matriz[i][j] = rand()%101; if ( matriz[i][j] < minimo_l ) minimo_l = matriz[i][j]; else if ( matriz[i][j] > maximo_l ) maximo_l = matriz[i][j]; }; // for() if ( minimo_l < minimo ) minimo = minimo_l, maximo = maximo_l; } // for(); mostra( matriz,4,7 ); cout << "MinMax = " << maximo << endl; return 0; }; int mostra(int matriz[][7], int L, int C) { for(int i=0; i<L; i++) { for(int j=0; j<C; j++) { cout << setw(5) << matriz[i][j]; } cout << endl; } return 0; }
Que deve mostrar
PS C:\src\CPP> g++ -o tst -Wall -std=c++17 mm.cpp PS C:\src\CPP> ./tst 38 61 38 99 43 40 100 19 98 77 1 52 93 72 19 2 73 82 94 35 43 39 84 100 40 97 98 61 MinMax = 98 PS C:\src\CPP>
-
O post de arfneto em Como por uma macro em segundo plano? foi marcado como solução
meses atrás eu mostrei duas maneiras de fazer em C e em C++ com fontes e tal. O código está aqui no forum e tem uma discussão que explica a lógica. Eu estava mostrando como escrever menus mas a ideia é claro a mesma.
A discussão está nesse artigo
Eis o botão code...
E tem esses artigos...
bem no início do forum...
De volta ao programa
Pode nem considerar o que eu expliquei. A lógica do que você quer fazer é simplesmente não usar o buffer da entrada.
Não daquele modo ingênuo que habita este forum por exemplo, tentando usar fflush() ou setbuf() que foram escritas para algo muito diferente.
LINE INPUT MODE, Cooked Mode, Raw MODE
O Windows chama o modo de leitura do teclado de LINE INPUT MODE e está claro associado ao ECHO MODE. Unix e derivados usam a noção de Cooked/raw mode. Eu devo ter explicado isso na discussão que postei e não vou fazer isso de novo aqui.
Eis o resumo:
A entrada via teclado em geral espera um ENTER. É uma questão de eficiência e inteligência: se retornar antes do ENTER em geral é uma m3rd@ porque por exemplo você não pode corrigir um erro usando backspace e as setas e reescrevendo o que errou. Então seu programa para e fica esperando o resultado da leitura, mesmo que seja uma letra só. Mas você pode ir digitando, voltando e corrigindo até o ENTER.
No entanto por exemplo em um jogo onde você usa ASWZ para mover o cursor ou as setas e fazer um bloco andar na ela, você não pode imaginar um prompt dizendo "digite a direção para onde quer ir e tecle ENTER" ...
É o que acontece com seu programa.
Em Windows uma maneira de fazer isso é ler o buffer de teclado e não o teclado, como eu mostrei nos programas. Usando PeekConsoleInputBuffer(). É bem simples.
Mas entenda que se desligar o lance de LINE INPUT funções como fgetc() e read() e scanf() e tudo que ler de stdin vão ler sempre o que tiver para ser lido e o programa não para. E se desligar também o ECHO pode escolher se vai mostrar o que foi digitado, porque as vezes não se quer e às vezes precisa esperar pra ver se tem um backspace depois
Isso se faz chamando SetConsoleMode() no Windows e ioctl() no Linux. No Linux se manipula os valores de VMIN e VTIME, em geral para ZERO mesmo. No Windows é só um shor int se bem me lembro
-
O post de arfneto em criar código c associando letras a-z e num 1-26 e somar a palavra no final foi marcado como solução
a bem da verdade, se sabe que s
ó vai usar essas 26 letras e em sequência não precisa de nada. Para cada letra em
char letra; o valor será
int valor = letra - 'a' + 1; para a entre 'a' e 'z' inclusive, e 0 para qualquer outro valor. Quando letra for 'a' a conta vai dar 'a' - 'a' + 1 que é o esperado 1
Mas na prática como tem que testar todas as letras para ver se estão no intervalo pode ser mais simples e MUITO mais rápido simplesmente usar a tabela.
E uma conta simples. Matemática, uma planilha apenas. y = f(x). Expliquei algo similar aqui hoje: como tem que testar todas as letras pode somar sempre e assim não precisa testar NUNCA.
Vou até postar um exemplo ao final, não como a solução para seu caso mas como uma solução usando uma técnica comum em C e Assembler, porque é muito rápido e não tem contas ou comparações.
De volta ao seu programa
quase nada do que escreveu faz sentido desde esses <code> no meio do código. Não é assim que funciona...
const char numero[]="abcdefghijklmnopqrstuvwxyz"; int main (){ int i=0; int valorfinal[140]; char a,b,c,d,e,f,g,h; int soma; while(++i) { if(numero[i-1]==0) break; valorfinal[i+96] = numero[i-1]-('a'-1); }
Muito bom ter usado const char[] para o vetor numero: é esperto declarar como tal tudo que sabe que deve ser constante. Mas como vai usar todas as letras em seguida os códigos também estarão em seguida, de 97 a 126 inclusive. Não precisa deles todos, de 'a' = 97 em diante...
Mas
se quer apenas a soma, que d1@b0 pretende com um vetor de 140 int chamado valorfinal? porque declarou esses 8 char se vai usar apenas um por vez? porque razão não deu um valor inicial a soma? Tipo 0? Coo vai saber se está certo se não sabe de onde começou? que pretende com while(i++) se i começa com zero? claro que não vai parar nunca e essa conta? numero[i-1] é a letra do vetor constante. Se está subtraindo depois de somar porque não comecóu com i igual a 1 e somou depois? que pretende com scanf() lendo 4 letras por vez? Porque não duas? ou 5? ou 12? porque não testa o retorno de scanf()? não faz sentido seguir sem ler p0rr@ nenhuma. scanf(%c%c%c%c.....) pode retornar o que? -1, 0, 1, 2 3 ou 4. E aí? Não faz diferença? e depois soma 4 valores sem saber se leu ao menos 1 e o infeliz que vai ler "meu caro amigo diga o que queres"... Como ele vai adivinhar que ode digitar 4 letras? Percepção extrasensorial? São muitas coisas para você considerar...
Um exemplo:
Claro que para "a111z" o valor deve ser 27 então esse programa
#include <stdio.h> char parcela[256]= {0}; // tudo zerado int main( void ) { int soma = 0; // arruma o vetor antes de tudo for( int i='a'; i <='z';i+=1) parcela[i] = i - 'a' + 1; const char* linha_de_teste = "a111z"; char* p = (char*) linha_de_teste; // a primeira letra, 'a' while ( *p != 0 ) { // soma o valor correspondente a letra, como esta na tabela soma = soma + parcela[ (int) *p ]; p = p+1; // avanca para a letra seguinte }; // while() printf(" Para '%s' a soma calculada foi %d\n", linha_de_teste, soma ); return 0; }
Deve mostrar
toninho@DSK-2009:~/projects/um$ gcc -o tst -Wall -std=c17 f.c toninho@DSK-2009:~/projects/um$ ./tst Para 'a111z' a soma calculada foi 27 toninho@DSK-2009:~/projects/um$
Assim é.
Teste seu programa sempre com constantes e valores conhecidos antes de perder tempo lendo valores e escrevendo coisas na tela. Depois de ter alguma esperança do resultado pode colocar a leitura...
Outro exemplo:
Já que funcionou agora pode usar recortar e colar e criar outro programa que lê a string e mostra a soma... Sem destruir o programa anterior. É de graça. Não precisa fazer um programa só. Ninguem vai saber.
#include <stdio.h> #include <stdlib.h> char parcela[256]= {0}; // tudo zerado int main( void ) { int soma = 0; // arruma o vetor antes de tudo for( int i='a'; i <='z';i+=1) parcela[i] = i - 'a' + 1; // desta vez vai ler da console ate vir uma linha em branco char linha[80]; printf("Entre com a linha para ver a soma: "); fgets(linha,80,stdin); char* p = linha; // p aponta prara a primeira letra while ( *p != 0 ) // 0 marca o fim da string { soma = soma + parcela[ (int) *p ]; p = p + 1; } printf("\nA soma calculada foi %d\n", soma ); return 0; }
O loop é o mesmo mas usa fgets() para ler a linha toda...
toninho@DSK-2009:~/projects/um$ gcc -o tst -Wall -std=c17 f2.c toninho@DSK-2009:~/projects/um$ ./tst Entre com a linha para ver a soma: a A soma calculada foi 1 toninho@DSK-2009:~/projects/um$ ./tst Entre com a linha para ver a soma: a z A soma calculada foi 27 toninho@DSK-2009:~/projects/um$ ./tst Entre com a linha para ver a soma: a1111a111a3z A soma calculada foi 29 toninho@DSK-2009:~/projects/um$ toninho@DSK-2009:~/projects/um$
Exemplo 3:
Mais recortar e colar guardando f.c e f2.c
Esse é mais prático, como se espera de um programa em 😄 apenas passa o valor na linha de comando, usando aspas se ele tiver espaços, claro:
#include <stdio.h> #include <stdlib.h> char parcela[256]= {0}; // tudo zerado int main( int argc, char** argv ) { if ( argc < 2 ) { printf( "passe o valor na linha do programa!!\n"); return -1; }; // if() int soma = 0; // arruma o vetor antes de tudo for( int i='a'; i <='z';i+=1) parcela[i] = i - 'a' + 1; char* p = &argv[1][0]; // p aponta para a primeira letra do argumento while ( *p != 0 ) // 0 marca o fim da string { soma = soma + parcela[ (int) *p ]; p = p + 1; } printf("\nA soma calculada foi %d\n", soma ); return 0; }
E mostra
toninho@DSK-2009:~/projects/um$ gcc -o tst -Wall -std=c17 f3.c toninho@DSK-2009:~/projects/um$ ./tst passe o valor na linha do programa!! toninho@DSK-2009:~/projects/um$ ./tst abab A soma calculada foi 6 toninho@DSK-2009:~/projects/um$ ./tst "a a a a 1 1 1 1" A soma calculada foi 4
-
O post de arfneto em Como obter data e hora do sistema na linguagem C++ ? foi marcado como solução
o que fez você escrever essa linha?
Sabe o que é time()? É exatamente o que perguntou...
strftime() formata como preferir. Leu alguma documentação, por exemplo do header ctime que incluiu em seu programa?
Eis um exemplo, direto de CPlusPlus.com, que é um site que você deveria frequentar. Todo mundo faz isso, de iniciantes a especialistas
/* strftime example */ #include <stdio.h> /* puts */ #include <time.h> /* time_t, struct tm, time, localtime, strftime */ int main () { time_t rawtime; struct tm * timeinfo; char buffer [80]; time (&rawtime); timeinfo = localtime (&rawtime); strftime (buffer,80,"Now it's %I:%M%p.",timeinfo); puts (buffer); return 0; }
Isso compila em C e C++ mas não use como argumento para achar que essas linguagens são a mesma coisa. São absolutamente diferentes animais. Se trocar time.h for ctime vai ter as mesmas funções...
-
O post de arfneto em SetCurrentConsoleFontEx() "parece" não funcionar foi marcado como solução
A janela do IDE é um ambiente infeliz pra você mudar qualquer coisa que afete o ambiente.
Não precisa do Terminal, mas considere que vale a pena: programas de console escritos para o terminal rodam igual no Windows e no MAC. Linux, Unix e nas olimpíadas. Ok, talvez não nessa última. E rodam muito mais rápido, já que usam aceleração da placa de vídeo. A Microsoft avisa há anos para que não se use mais a tal console dos anos 80. Mas é uma mudança grande se você usava Windows e a console desde sempre. E um passeio se você usava Unix ou derivados
Se você mudar algo e der erro no meio do caminho vai zoar a configuração da janela do IDE para todos os programas que vem depois desse. E se não der erro e você não voltar para o original pode ter surpresas...
Em resumo: meu palpite: deixe uma janela do terminal aberta na pasta onde está gerando seu programa no IIDE e teste nessa janela. Pode ter várias abertas na mesma janela e se uma dá pau as outras estarão lá... Não demora nada mais. E se vai usar o debugger então use o próprio sistema para ver se alterou a fonte ou não. Eu devo ter escrito isso no exemplo, a menos que eu estivesse com muita pressa
Pois é: estava escrito lá no tópico.... Vi agora...
tem esse fragmento de um programa que salva e restaura essas coisas, é parte de algo que funciona mas de que não me lembro mais. Veja:
_cs_status* guarda(_cs_status* antes) { antes->cp_original = GetConsoleCP(); antes->ocp_original = GetConsoleOutputCP(); strcpy(antes->local_original, setlocale(LC_ALL, NULL)); HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); char buffer[80]; char* pBuffer = buffer; int res = 0; res = GetCurrentConsoleFont(h, 0, &(antes->font_info)); // pois e: mas qual a fonte? Tem que ver na tabela // precisa da versao ex da rotina e eu nao sabia antes->font_infoEx.cbSize = sizeof(CONSOLE_FONT_INFOEX); res = GetCurrentConsoleFontEx(h, 0, &(antes->font_infoEx)); // A fonte em uso fica aqui no registro // Computador\HKEY_LOCAL_MACHINE\SOFTWARE\ // Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont // GetConsoleMode(h, &antes->mode_original); // agora falta SCREEN BUFFER antes->infoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); GetConsoleScreenBufferInfoEx(h, &antes->infoEx); return antes; }; // guarda()
E a irmã
void restaura(_cs_status* antes) { // restaura locale e paginas de codigo SetConsoleCP(antes->cp_original); SetConsoleOutputCP(antes->ocp_original); setlocale(LC_ALL, antes->local_original); // restaura a fonte HANDLE ho = GetStdHandle(STD_OUTPUT_HANDLE); int res = SetCurrentConsoleFontEx(ho, 0, &antes->font_infoEx); if (res == 0) printf("SetCurrentConsoleFontEx() falhou: %d\n", GetLastError()); // console mode SetConsoleMode(ho, antes->mode_original); // cor e fundo SetConsoleTextAttribute(ho, antes->infoEx.wAttributes); }; // restaura();
E a estrutura
typedef struct { int cp_original; int ocp_original; char local_original[40]; int mode_original; FILE* log; CONSOLE_FONT_INFO font_info; CONSOLE_FONT_INFOEX font_infoEx; CONSOLE_SCREEN_BUFFER_INFO info; CONSOLE_SCREEN_BUFFER_INFOEX infoEx; } _cs_status;
Use algo assim
-
O post de arfneto em Quantas vezes um número aparece em uma lista encadeada foi marcado como solução
Se escreveu algo então tem imagino que escreveu uma função para listar todos os elementos da lista... Apesar de não ser uma função comum da biblioteca é uma função comum para quem implementa, porque é a maneira trivial de testar o programa.
Se não escreveu essa função, escreva. Se escreveu perceba que pode copiar essa função para a função que precisa, essa que conta, porque é a mesma coisa: percorre a lista e, ao invés de mostrar, compara e conta... É o mesmo caso de apagar...
Poste o código
-
O post de arfneto em Média ponderada em matrizes foi marcado como solução
use um vetor para as medias e ao final de cada leitura das notas de cada materia calcule a armazene a media no vetor...
-
O post de arfneto em Windows API - função Sleep() congela o aplicativo foi marcado como solução
... Sugiro muito que esqueça esse modo de programar. Ninguém usa isso desde o final dos '80 e deve ter uma boa razão.
Não via aprender nada exceto sobre o message loop do Windows, e vai gastar um tempo enorme para um resultado em geral não tão bom.
Use .Net e outra linguagem, ou Allegro5, ou SDL2 ou Qt5 ou GTK+ ou wswidgets para usar esses controles. É muito simples, tudo pareido e o resultado é bom e portável.
Se quer mesmo aprender algo básico e poderoso e complicado, mas útil depois de 1986 , tente OpenGL ou DirectX.
Li agora melhor o que você quer fazer e pra isso não precisa de multithreading. Basta usar um slideshow e criar um timeframe. A menos que precise de fato processar algo durante a exibição
Pode usar o comum: uma taxa de atualização e a cada digamos .5s verifica uma fila de eventos, o seu "message loop". Assim pode inserir outras atividades, como um menu. E executa o que estiver na fila. Nada original
-
O post de arfneto em Como gerar um .exe com configurações definidas usando um programa principal foi marcado como solução
Não precisa de um novo executável. Apenas de parâmetros. Use a linha de comando ou um arquivo de configuração.
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