Uma dor de cabeça para um novato. - C++ - Portugal-a-Programar
Uma dor de cabeça para um novato.
Por xerxes, 18 de Setembro de 2007 em C++
Viva a toda a gente do forum, sou novato tanto aqui no forum como na programção, sei um pouco de c++ e por isso venho vos pedir ajuda com este meu programa. o programa é muito simples, mas eu tou a desatinar com isto. Trata-se do seguinte, é um prog que le dia, mes, ano e hora, min e seg, e cria o seu timestamp, o meu problema é que quando tento a parti do timestamp voltar a hora k inseri, é.me retornado sempre datas e horas identicas mas sempre com alguns dias e horas a mais ou menos, n percebo o k está a passar. :hmm: Valente abraço ao pessoal
Agradecia um pouquinho de atenção para este prob prog :wallbash: (lol)
O meu codigo fonte é este:
time_t data;
struct tm dadosData;
unsigned int val1, val2, val3;
printf("Introduza a data nno seguinte formato (dd/mm/aaaa):");
scanf("%i%i%i", &val1, &val2, &val3);
dadosData.tm_mday=val1;
dadosData.tm_mon=val2;
dadosData.tm_year=val3-1900;
printf("\n\nIntruduza a hora no seguinte formato(hh:mm:ss):");
dadosData.tm_hour=val1;
dadosData.tm_min=val2;
dadosData.tm_sec=val3;
data=mktime(&dadosData);
printf("O timestamp dessa data e: %li\n", data);
printf ( "A data k inseris t getdate(: %s", asctime (&dadosData) );
%i não é nenhum tipo para usar com scanf....
Tens %d para números decimais inteiros, %u para positivos inteiros... %hd ou %hu para shorts, %ld ou %lu para longs..... etc.... %i não conheço...
Afinal %i existe, e eu não sabia, disse-me o triton, agora....
http://www.cppreference.com/stdio/printf.html
Vou voltar a olhar para o código.........
Mas tenta mudar, assim o prob mantem-se.
já que especificas assim:
podes definir para ler assim:
scanf("%u/%u/%u", ...);
Uma vez que declaraste unsigned, lê unsigned, também....
//#include dos.h  // não serve para nada....
scanf("%u/%u/%u", &val1, &val2, &val3);
scanf("%i:%i:%i", &val1, &val2, &val3);
[ndray@nDesktop ~]$ ./a.out
Introduza a data nno seguinte formato (dd/mm/aaaa):20/02/1988
Intruduza a hora no seguinte formato(hh:mm:ss):06:45:27
O timestamp dessa data e: 574843527
A data k inseris t getdate(: Sun Mar 20 06:45:27 1988
N tou a conseguir, agora modifiquei o que m disses t e agora dá m erro do windows (enviar ou n enviar).
O fim deste programa é k ele peça a data e hora, faça o timestamp da mesma, e grave o timestamp num ficheiro de texto, depois mais tarde ele ira ler do ficheiro o timestamp para o poder converter de novo em data. Ahh outro prob, eu queria k aparecex a data final no formato dd/mm/aaaa, para poder ser comparda com outras datas.
Deste já agradeço a ajuda, é k estudar sozinho c++ n é facil
Por que guardas o timestamp e não a string?
Eu acho que isso funciona, comigo funcionou, em linux.... Esse erro por vezes ocorre por causa de scanf's mal construidos....
Confere o teu código, deve haver aí um problema com casts ou assim...
BTW, o meu segundo scanf está mal... Era para ter %u:%u:%u.......................
Pois, eu tou a programar no winXP, :dontgetit: tou com o RELO da borland.
Conheçes algum compilador gratuito que me recomendes, é que já reparei que as vezes o meu compilador tem BUGS.
E nao queria gravar uma string pq depois o resto do meu programa fica a espera de um int para tratar... :-[
Eu uso GCC, mesmo em windows.... Instalas MinGW, e depois podes usar Code::Blocks para programar.... Eu uso gVim, que é só um editor de texto, mas não creio que te safes com ele, para já... Code::Blocks é muito bom, mesmo....
E agora reparo que o output do programa ficou mal.... 02 é suposto ser Fevereiro, mas no output está Março..... Isso é porque tm_mday vai de 0 a 11 e não de 1 a 12.... Seria esse o teu problema?
Exacto, é mmo esse o prob k mencionei no meu primeiro topico... :biggrin:
Ele acrescenta ou diminui horas, dias ou meses.
E o RELO é so editor de de texto, se n tou em erro, é assim k programo. :ipool:
Continuo a precisar de ajuda!
Confere a documentação da struct tm e vê se estás a trabalhar como devias..... O caso dos meses é um que está mal, quem sabe os outros não estarão também...
Sim eu sei. mas pareçe-me estar tudo ok com a estrutura. simplesment n consigo converter direito...
Tou farto de m derreter com isto :bored:
Coloca aqui novamente o código que estás a utilizar e o output de um caso de erro.
O código é exactamente o do meu primeiro post, uma vez k fiz as modificações k m disses t mas n consegui nada. N dá erro de compilação, mas cria o famoso erro de windows qd o scanf le para umas das variavais. (o erro de envio de reltoro para diagnostico da micrososft).
Oh pah, isto para mim funciona... Não sei o que pode estar mal....
Com especial atenção que eu estou a compilar em C, e não em C++, mas isso não devia fazer diferença..... Tu próprio não usas bibliotecas de C++.....
unsigned short int val1, val2, val3;
printf("Insert date (dd/mm/yyyy): ");
scanf("%hu%*[^0123456789]%hu%*[^0123456789]%hu", &val1, &val2, &val3);
date.tm_mday = val1;
date.tm_mon  = val2 - 1;
date.tm_year = val3 - 1900;
printf("Insert time (hh:mm:ss): ");
date.tm_hour = val1;
date.tm_min  = val2;
date.tm_sec  = val3;
printf("timestamp: %lu\n", mktime(&date));
printf("ascii time: %s", asctime(&date));
O teu programa tinha alguns erros que convém esclarecer para não os cometeres mais (ou não tantas vezes ).
Para começar, não vejo onde é que este teu programa é especificamente escrito em C++, basicamente não usas nenhuma sintaxe de C++ mas antes de C. O que não tem mal, apenas não é um código-fonte exclusivamente de C++ (podes compilá-lo com um compilador de C ou de C++).
Depois acho que é preciso tomar cuidado com o uso de funções como o scanf que considero que é uma função bastante particular e delicada. Se não passares uma string com o formato correcto no scanf está tudo estragado e pode dar origem a sérios problemas na execução do teu programa.
Quando declaras variáveis deves inicializá-las a um valor por defeito, como para um int dar-lhe o valor 0 (por exemplo) e para uma estrutura como a tm deves colocar todos os seus membros a zero. Uma forma de fazer isto é com a função memset definida em strings.h. Isto impede que as tuas variáveis fiquem com valores que porventura já estejam em memória e assim sabes que as tuas variáveis não contêm valores incorrectos, aka lixo.
Por fim, e como bom programador que deves aspirar a ser (não resisti a dizer isto :smoke:), deves ler documentação sobre as funções que vais usar para atingir os objectivos do teu programa. Quando recebes os dados para o valor do mês, tens que decrementar o valor do membro tm_mon pois este membro toma valores apenas no intervalo 0 a 11. Daí que possas estar a obter valores errados para o mês.
Vê esta página sobre esta mesma estrutura: http://www.cplusplus.com/reference/clibrary/ctime/tm.html
Segue abaixo o teu código que alterei e que funciona com o gcc 3.4.4 em ambiente Windows (Eclipse CDT + Cygwin).
Abraço! Qualquer dúvida que tenhas vai postando que prometo ajudar se arranjar tempo!
//para usar o memset
time_t data=0;
struct tm * dadosData;
int val1=0, val2=0, val3=0;
char valstr1=0, valstr2=0;
//inicializar os membros de dadosData a 0
memset(dadosData,0,sizeof(struct tm));
printf("Introduza a data no seguinte formato (dd/mm/aaaa):");
scanf("%2d%1c%2d%1c%4d", &val1, &valstr1, &val2, &valstr2, &val3);
//obter a informacao do tempo actual e modifica-la de acordo
//com o que o utilizador introduziu
time(&data);
dadosData = localtime(&data);
dadosData->tm_mday=val1;
//decrementar o mes
dadosData->tm_mon=val2-1;
dadosData->tm_year=val3-1900;
printf("\n\nIntroduza a hora no seguinte formato(hh:mm:ss):");
scanf("%d:%d:%d", &val1, &val2, &val3);
dadosData->tm_hour=val1;
dadosData->tm_min=val2;
dadosData->tm_sec=val3;
//ao chamar mktime vamos settar o membro dadosData->tm_wday
data=mktime(dadosData);
printf("O timestamp dessa data e: %ld\n", data);
printf ( "A data que inseriste e' getdate: %s", asctime (dadosData) );
O header que pretendes incluir é o string.h
Não podes inicializar nada porque só tens um apontador, não criaste a estrutura em memória. Admiro-me como não te deu erro ao tentares escrever em memória não alocada...
As inicializações são desnecessárias neste caso, e podem degradar a performance. Neste caso não, mas se fosse numa função que fosse chamada repetidamente, colocar os valores a 0 ou não pode fazer uma grande diferença.
também não faz sentido ler os caracteres separadores da data para variáveis; só serve para perder mais tempo... Aliás, no caso das horas procedeste bem:
Não faz sentido utilizar uma linguagem cuja principal vantagem é a performance se esta não é aproveitada. De outro modo mais valia utilizar Java, ou C#, ou Python ou algo assim, em que provavelmente é muito mais fácil escrever um programa deste género.
Tens razão, é o string.h e não o strings.h.
SIm, o que eu queria ter feito era criar a variável dadosData como estrutura e não como apontador. Aí sim deveria ter settado os membros a zero.
Como esta função não é chamada em ciclo não há problema nenhum em colocar valores a 0, não se introduz nenhum bug ao fazer isso e acho que é uma prática recomendável.
É uma das maneiras possíveis de resolver o problema. É certo que não é preciso ler os caracteres separadores mas também não há problema em o fazer...
Não me parece que a performance seja sequer considerada aqui para um problema tão simples como este. Só quis fazer código que realmente funcionasse sem me preocupar com a performance e no pouco tempo que estive a ver este post. A ideia era ajudar o xerxes a perceber o código e o que estava mal, e não a fazer o código com a melhor performance.
As inicializações a zero são indiferentes, se logo a seguir vais definir os valores... talvez na struct faça algum sentido porque não vamos definir todos mas, de resto, não é isso que altera a segurança do programa....
Ler caracteres para varíaveis só porque não os vais usar, isso é falta de conhecimento das potencialidades do scanf.... fazes %*c e pronto, está descartado, não precisas de alocar......
Definir valores para zero em ciclos não dá problema, antes pelo contrário... Não o fazer, quando se deveria, é que dá..... Nesse caso é que não há problema....
Uma coisa é menosprezar a performance para resolver um problema de forma mais simples, outra é desprezá-la para fazer código desnecessário.
Eu sei disso, simplesmente postei uma possível solução que na altura não tive tempo para melhorar.
Mais uma vez digo que a questão que aqui se coloca não é a de obter a melhor performance. Fiz rapidamente um código que funcionava. Ponto. Não tive tempo de olhar melhor para o código que fiz, só isso. Se tivesse mais tempo era outro o código que fazia. Mas sinceramente achas que é por fazer um %c em vez de um %*c que vais perder assim tanta performance num problema deste?
Eu não fazia aquilo de forma imediata.... A forma mais imediata era mesmo nem ler.... Mas pronto, cada um processa os problemas a seu gosto....
Não estou a falar de performance, estou a falar de práticas...
Mas sinceramente achas que é por fazer um %c em vez de um %*c que vais perder assim tanta performance num problema deste?
Como eu disse, o problema não é este caso, mas sim outros em que a performance conte. Os piores hábitos ganham-se ao início.
Ok, n sei como fazer.
Vcs falam em GCC eu n sei o k é isso.
Só sei k no RELO qd compilo o prog k m dest, n consigo abrir a library sys/cdefs.h da strings.h.
nunca usei outro prog para programar sem ser o RELO, como faço para ter um de jeito?
Pah, já que estás a programar em C e não em C++, experimenta LCC-Win32... És capaz de ter de pesquisar por links de download, mas é simples e funciona muito bem....
Quando já estiveres desenrascado, instala MinGW (vai à secção de downloads, Sourceforge, e saca o MinGW-5.1.3 Automated Installer). Corres isso, escolhes, pelo menos, GCC e G++ para C e C++, respectivamente. Aconselho a escolha dos pacotes "candidate", e que instales na directoria predefinida.
Depois convém adicionares os binários às variáveis de ambiente, para poderes usar os programas como em linux. Executas, na consola, este comando: "set path=%path%;C:\MinGW\bin", assumindo que foi essa a pasta onde instalaste...
Depois disso sacas uma nightly build do Code::Blocks, lê bem de que ficheiros precisas de sacar mais, está tudo documentado.
Quando correres o Code::Blocks pela primeira vez, escolhes o MinGW GCC como compilador, e pronto, está feito...
Estes programas encontram-se bem no google pesquisando simplesmente pelo seu nome...
ok, pessoal, agora tou a usar o dev-C++, ja consigo compilar o codigo, ja consigo k seja criado o ficheiro executavel, o problema agora é k quando executo o programa, n chega a fazer nada pq dá o famosos erro do windows de enviar ou n enviar, ja tentei noutros pcs e o problema mantem-se.
Deste já um imenso obrigado a todos k m ajudam.
Este é o codigo k estou a usar:
#include <time.h>//para usar o memset
Esse problema dá quando tentas executar o binário dentro do Dev-C++? Ou tentas correr o programa a partir da pasta onde está o binário com um duplo-clique em cima do binário? Strange...