Copiar caracter para outra variavel

1. Copiar caracter para outra variavel

William Lima
willdoidao

(usa Ubuntu)

Enviado em 10/09/2013 - 11:51h

Pessoal,
Estou com uma duvida besta mas não estou conseguindo enxergar o meu erro!!
Preciso copiar uma determinada parte de um arquivo que coloquei em um vetor e passar para uma variável, somente o trecho que desejo.
Só que a mesma está voltando vazia, segue o código:


#include <cstdlib>
#include <iostream>
#include <string.h>
#include <stdio.h>


using namespace std;

int main(int argc, char *argv[])
{
FILE * pFile;
char * end;
char string1[100],string2[100],resultado[6];

pFile = fopen("oracle.txt","r");
if(pFile == NULL)
{
perror ("Erro ao abrir o arquivo!");
}
// coloco uma mensagem interessante na segunda string
sprintf(string2,"There is no lines in myfile.txt");

for(;;){ // laço que nunca, mas nunca mesmo, vai terminar.
end = fgets (string1 , 100 , pFile); // leio uma linha do arquivo e jogo em string1
if (end == NULL) { // é a ultima arquivo?
//puts(string2); // mostro o conteudo de string2
break; //fim
}
// ora, la em cima não era o fim da linha, vou ler outra!
end = fgets (string2 , 100 , pFile); // a partir de agora, string2 carrega alguma linha

if (end == NULL) { // é o fim do arquivo?
//puts(string1); // mostro a linha anterior
break; //fim
}



}

fclose (pFile);


for(int i =25;i<=30;i++){
for(int y=0;y<=6;y++){
resultado[y] = string2[i];
}
printf("%c",string2[i]);
}

printf("\n%s\n",resultado);


system("pause");
return 0;
}



  


2. Re: Copiar caracter para outra variavel

Clodoaldo Peres
clodoaldoPeres

(usa Ubuntu)

Enviado em 10/09/2013 - 13:05h

willdoidao escreveu:

Pessoal,
Estou com uma duvida besta mas não estou conseguindo enxergar o meu erro!!
Preciso copiar uma determinada parte de um arquivo que coloquei em um vetor e passar para uma variável, somente o trecho que desejo.
Só que a mesma está voltando vazia, segue o código:


#include <cstdlib>
#include <iostream>
#include <string.h>
#include <stdio.h>


using namespace std;

int main(int argc, char *argv[])
{
FILE * pFile;
char * end;
char string1[100],string2[100],resultado[6];

pFile = fopen("oracle.txt","r");
if(pFile == NULL)
{
perror ("Erro ao abrir o arquivo!");
}
// coloco uma mensagem interessante na segunda string
sprintf(string2,"There is no lines in myfile.txt");

for(;;){ // laço que nunca, mas nunca mesmo, vai terminar.
end = fgets (string1 , 100 , pFile); // leio uma linha do arquivo e jogo em string1
if (end == NULL) { // é a ultima arquivo?
//puts(string2); // mostro o conteudo de string2
break; //fim
}
// ora, la em cima não era o fim da linha, vou ler outra!
end = fgets (string2 , 100 , pFile); // a partir de agora, string2 carrega alguma linha

if (end == NULL) { // é o fim do arquivo?
//puts(string1); // mostro a linha anterior
break; //fim
}



}

fclose (pFile);


for(int i =25;i<=30;i++){
for(int y=0;y<=6;y++){
resultado[y] = string2[i];
}
printf("%c",string2[i]);
}

printf("\n%s\n",resultado);


system("pause");
return 0;
}


Cara este teu código tah bem estranho. Quando se trabalha com arquivo deve se usar algumas funções importantes como fflush() - limpar o buffer pois a cada leitura stdin pode estar sujo comprometendo a veracidade da informação, ferror() - pois as operações com arquivo podem gerar erros a qualquer instante,etc. Sugiro que você abra teu arquivo em modo binário (para mim é muito melhor para trabalhar, se possivel) usando fopen com "rb" e use um ponteiro com o tamanho total do teu arquivo (você consegue ter o tamanho do arquivo com a função ftell(<ponteiro de arquivo>)) e use fread(void *buffer,size_t <qntd de bytes a serem lidos>,1,<ponteiro de arquivo>) passando o um ponteiro de char alocado com malloc ( p = (char*) malloc(<tamanho do arquivo> * char) ) e aí o teu ponteiro de char vai ter todo o teu arquivo então vc pode fechar o arquivo com fclose()/close() e o teu arquivo vai estar em buffer aí é soh navegar nele usando os indices como se fosse um vetor de char's


3. Re: Copiar caracter para outra variavel

Clodoaldo Peres
clodoaldoPeres

(usa Ubuntu)

Enviado em 10/09/2013 - 13:06h

Ah sim, esqueci de comentar para vc conseguir o tamanho do arquivo faça assim:
fseek (pFile , 0 , SEEK_END);
<variavel int>= ftell (pFile);
rewind (pFile);


4. Re: Copiar caracter para outra variavel

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/09/2013 - 00:56h

clodoaldoPeres escreveu:

Cara este teu código tah bem estranho. Quando se trabalha com arquivo deve se usar algumas funções importantes como fflush() - limpar o buffer pois a cada leitura stdin pode estar sujo comprometendo a veracidade da informação, ferror() - pois as operações com arquivo podem gerar erros a qualquer instante,etc. Sugiro que você abra teu arquivo em modo binário (para mim é muito melhor para trabalhar, se possivel) usando fopen com "rb" e use um ponteiro com o tamanho total do teu arquivo (você consegue ter o tamanho do arquivo com a função ftell(<ponteiro de arquivo>)) e use fread(void *buffer,size_t <qntd de bytes a serem lidos>,1,<ponteiro de arquivo>) passando o um ponteiro de char alocado com malloc ( p = (char*) malloc(<tamanho do arquivo> * char) ) e aí o teu ponteiro de char vai ter todo o teu arquivo então vc pode fechar o arquivo com fclose()/close() e o teu arquivo vai estar em buffer aí é soh navegar nele usando os indices como se fosse um vetor de char's


Meu caro,

Cuidado com as coisas que você diz. Observe que:

1) Oficialmente (i.e. de acordo com o padrão do C em suas três revisões: 1989/1990, 1999 e 2011), fflush() nunca se destinou a limpar buffers de leitura, mas tão somente a forçar a gravação imediata (e não o descarte!) de informação em streams de saída. É, portanto, JUSTAMENTE O OPOSTO do que você afirmou. (A invenção estúpida de usar fflush() em buffers de entrada, particularmente stdin, foi uma cretinice implementada antes de existir um padrão para o C nos compiladores voltados para MS-DOS, cujo buffer de teclado se limitava a apenas quinze caracteres, e portanto tinha um funcionamento relativamente bem comportado e definido. Só que essa porcaria sobreviveu, por questões de compatibilidade com implementações passadas, mesmo após a padronização da linguagem C e sua biblioteca. Essa desgraça acabou incorporada nos compiladores para Windows e infelizmente foi importada recentemente também para o Linux, cujos buffers de teclado podem ser arbitrariamente longos e podem, portanto, nunca ser satisfatoriamente ou controladamente esvaziados.)

2) Ele está testando, sim, o sucesso da leitura, ao tomar o valor de retorno de fgets() e verificar se ele é nulo. Se para ele não fizer diferença entre não conseguir ler por se ter chegado ao fim do arquivo ou em decorrência de algum erro (o que, aliás, é uma situação não muito comum em operações de leitura, especialmente num sistema monoprogramado), por que ele deveria testar o que não lhe interessa?

3) A julgar por outra postagem do mesmo autor, ele parece estar usando Windows. No Windows, se ele quiser trabalhar com arquivos de texto, é bom que ele NÃO USE "rb", mas sim somente "r", porque as funções de leitura e escrita de texto fazem conversões entre representações internas de fim de linha e a representação usada pelo sistema operacional. No mundo UNIX, "r" e "rb" são equivalentes, mas nos mundos Microsoft e MacOS, não.

4) É muito perigoso sugerir ler todo o arquivo para a memória. Você sabe o tamanho do arquivo? Sabe quanto de memória o programa tem disponível? Então é mais seguro trabalhar com arquivos, lendo linha a linha (e limitando mesmo o tamanho de cada linha, como ele fez).

5) O programa dele é mesmo voltado a trabalhar linha a linha. Assim sendo, ainda que ele estivesse trabalhando com tudo em memória, seria mais simples ter um array de linhas do que um megabuffer de caracteres individuais.


5. Re: Copiar caracter para outra variavel

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/09/2013 - 01:24h

E, ah!, em tempo:

6) A única coisa "bem estranha" no código dele são aqueles dois loops aninhados, após o final da leitura e perto do final da função main().

6.1) O loop mais interno, que usa y como índice, está excedendo o tamanho máximo do array resultado (seis elementos são contados com índices que vão de 0 a 5; contar de 0 a 6 implica sete elementos).

6.2) Ainda nesse loop e com esse array, não se está deixando um byte a mais para acomodar o byte nulo que marca o final da string, o que será importante no printf() que vem mais abaixo, que manda imprimir a string inteira contida no array (se os dados forem das posições de 0 a 5, o byte nulo fica na posição 6, e o array deve ter, portanto, um tamanho declarado de 7 elementos; se os caracteres estiverem nos índices de 0 a 6, o byte nulo fica na posição 7, e o array tem tamanho 8).

6.3) A cada iteração do loop mais externo (indexado com i), todo o conteúdo do array resultado é sobrescrito com o mesmo caráter (string2[i]), deprezando a atribuição feita na iteração anterior.

6.4) Parece-me que o que ele queria fazer é ter um loop só, variando i de 0 a 5 (ou 0 a 6, sei lá), fazendo resultado[i]=string2[i+25]. Não se deve esquecer de colocar o byte nulo depois em resultado[6] (ou 7).

6.5) Mas mesmo que minha suposição em (6.4) esteja certa, seria bom, antes de efetuar as cópias, garantir que o tamanho da linha lida seja realmente maior que ou igual a 30 (ou 31) caracteres. Caso contrário, ele provavelmente vai colocar um conteúdo indefinido no array resultado.

7) Eu tentaria evitar a mistura de "modo C" e "modo C++" no mesmo programa.

7.1) Se se inclui <cstdlib>, por que não usar <cstring> e <cstdio>?

7.2) Tirando o <cstdlib> e o using namespace std; todo o resto me pareceu C puro. Não seria o caso de fazer todo o programa em C puro, alterando a primeira, e eliminando a segunda?

7.3) Caso se opte por C++, eu recomendo, até para se adquirir experiência, trocar arrays/ponteiros de caracteres, printf(), FILE*/fopen() e fgets(), respectivamente por, respectivaente, std::string, std::cout, std::ifstream e std::getline().


6. Re: Copiar caracter para outra variavel

Clodoaldo Peres
clodoaldoPeres

(usa Ubuntu)

Enviado em 11/09/2013 - 17:53h

Vamos lá. (estranho)
1-Porque uma variavel ponteiro end soh para testar fim de arquivo? Poderia ser colocado dentro do proprio if
2-Porque usar string1 e string2 se no fim soh usa string2? Ficar alternando entre linhas? Uma string pega uma linha e outra a linha subsequente.
3-Uma misturança de C com C++
4-escrever em cima de 'resultado' a mesma sequencia de caracteres e ainda por cima sobrescreve-la depois.

Por isso disse que parecia estranho.
Outra coisa, sugeri o modo binário pois a relação é de 1 para 1, ou seja, eh mais compativel em caso de mudança de arquitetura pois o windows usa alimentação de linha + retorno de carro e Unix soh alimentação de linha, o contrário do que disseram acima.E também por que estava usando um txt por isso recomendei passar tudo para memo, acho dificil alguem ter um txt com 2gb, mas td bem. Trabalhar com arquivo linha a linha...se tiver que fazer acessos aleatorios vai ser barra.


7. Re: Copiar caracter para outra variavel

Clodoaldo Peres
clodoaldoPeres

(usa Ubuntu)

Enviado em 12/09/2013 - 20:48h

Ainda a tempo.
Eu falei sobre o uso do fflush() acima, e apenas fazendo uma errata.
Use o fflush() passando o arquivo como parametro para que caso haja alguma intervenção durante a execução (tipo exception) ele procura garantir que os dados (no caso de arquivo de saida) serão gravados no arquivo.



8. Re: Copiar caracter para outra variavel

Clodoaldo Peres
clodoaldoPeres

(usa Ubuntu)

Enviado em 12/09/2013 - 20:54h

E (willdoidao )se for possível feche os posts que jah foram resolvidos e senão, de um retorno.Procure compartilhar as soluções, pois pelo que percebi existem muitos posts seus abertos e sem retorno. Isto ajudará outros usuários.


9. Re: Copiar caracter para outra variavel

Paulo
paulo1205

(usa Ubuntu)

Enviado em 12/09/2013 - 23:37h

clodoaldoPeres escreveu:

Ainda a tempo.
Eu falei sobre o uso do fflush() acima, e apenas fazendo uma errata.
Use o fflush() passando o arquivo como parametro para que caso haja alguma intervenção durante a execução (tipo exception) ele procura garantir que os dados (no caso de arquivo de saida) serão gravados no arquivo.


O único stream de saída no programa dele é stdout. É o único, portanto, sobre o qual faz sentido chamar fflush(). E como ele não está alterando a configuração de bufferização (i.e. ele não chama setvbuf() e sua congêneres em lugar algum), é razoável supor que o buffer de stdout será automaticamente esvaziado a cada '\n', o que reduz a utilidade desse fflush() apenas após aquele ``printf("%c",string2[i]);´´ (que, aliás, poderia ser muito bem trocada por ``putchar(string2[i])´´, que é mais eficiente).

E que exceção você espera que possa ocorrer, se ele só está usando funcionalidades do C, que não dispara exceções?


10. Re: Copiar caracter para outra variavel

Paulo
paulo1205

(usa Ubuntu)

Enviado em 13/09/2013 - 00:25h

clodoaldoPeres escreveu:

Outra coisa, sugeri o modo binário pois a relação é de 1 para 1, ou seja, eh mais compativel em caso de mudança de arquitetura pois o windows usa alimentação de linha + retorno de carro e Unix soh alimentação de linha, o contrário do que disseram acima.E também por que estava usando um txt por isso recomendei passar tudo para memo, acho dificil alguem ter um txt com 2gb, mas td bem. Trabalhar com arquivo linha a linha...se tiver que fazer acessos aleatorios vai ser barra.


O contrário do que quem disse acima? Não vi ninguém dizer qualquer coisa parecida. O único que falou foi você -- e falou bobagem, pois o Windows não usa LF+CR, mas sim CR+LF.

Você sugere algo parcialmente incorreto quando diz que usar "rb" faria um programa ser "mais compatível em caso de mudança de arquitetura": isso só seria verdade se o programa estivesse gravando (i.e., por exemplo, "wb") um arquivo para ser lido posteriormente noutro lugar por um programa que garantidamente use "rb" ao abrir o arquivo para leitura. Não é o caso do programa dele, que não grava em arquivo. Você não sabe como o arquivo que ele está tentando ler foi gerado -- se tiver sido no Notepad do Windows, por exemplo, lê-lo em modo binário vai fazer com que cada linha lida armazene um '\r' no final, como se fosse um caráter comum. E mais ainda: é razoável que um programa não apenas grave, mas também saiba ler arquivos de texto usando a convenção empregada pelo SO sobre o qual está executando, a fim de que outras ferramentas desse SO possam ser usadas para manipular os mesmos arquivos.

Por que você está supondo 2GB? Quem garante que ele, a exemplo do que volta e meia aparece por aqui, não está usando um velho Turbo C++ ou outro compilador para DOS, que só suporta 640kB (sim: kB!)? E mesmo que não esteja, como fazer suposições sobre a configuração que ele tem ou sobre os arquivos com os quais está trabalhando? É muito fácil, por exemplo, que um arquivo de texto tenha vários GBs: basta ser um arquivo de logs de um firewall rotacionado com pouca frequência, ou o log de um webserver muito movimentado, ou um log de auditoria de um servidor de banco de dados muito utilizado (aliás, olhe o nome do arquivo que ele está abrindo!).

Acesso aleatório em memória soa muito fácil, mas você mais uma vez não tem como saber -- pelo menos não com as informações que foram passadas aqui -- se todas as linhas têm o mesmo tamanho. Não tendo -- o que é muito comum com arquivos de texto --, ler para a memória do modo como você sugeriu (i.e., usando um "bufferzão" para onde se lê o arquivo todo numa tacada só), você despreza totalmente a informação de onde começa ou termina cada linha, e terá de fazer uma forma de varrer a memória para achar cada uma delas. Além do mais, o programa original só tinha interesse nas linhas pares, e a sua maneira de ler acaba gerando um desperdício de memória porque guarda todas as linhas ímpares, e ainda por cima acaba não tendo validade alguma de acesso aleatório, pois a única forma de saber se uma linha lá pelo meio ou pelo final do bufferzão é par ou ímpar é percorrer o buffer todo, desde o início e caráter por caráter, contando os marcadores de fim de linha.

Você faz muitas suposições temerárias e, com elas, acaba criando mais problemas para quem pergunta do que ajudando.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts