arquivos em C

1. arquivos em C

Daniel
danielcrvg

(usa Slackware)

Enviado em 09/12/2012 - 21:53h

Boa noite galera do VOL,

Estou encontrando dificuldades em relacao manipulacao de arquivos em C. Estou com duvida na hora de "procurar" por uma string dentro de um arquivo "teste.txt".

O que esta ocorrendo é o seguinte:

Dentro do meu arquivo "teste.txt" tem a seguinte lista:

10 jao
12 maria
22 haha
22 kokoko
23 36
22 bobmarley


Quando eu faco a procura, se eu digitar:
jaO
Ele nao acha, ate ai esta certo...

Se eu digitar: jao
Ele acha, continua certo..

Mas, se eu digitar apenas: j

Ele acha, por que "j" existe dentro da linha referente ao "jao"...


Eu nao to conseguindo fazer a implementacao para que ele compare caracter por caracter, entre a string digitada pelo usuario, com a string que existe dentro do arquivo "teste.txt"..

Tambem estou com dificuldades em cadastrar nomes com " " (espaco) entre os nomes, ex: Jesus Cristo..


Se alguem souber algo para me ajudar, eu agradeco...


Codigo da funcao de procurar string: http://codepad.org/o4FH9aGe



int VerificarCurso () {

int conf=69;
char nomeCurso[50];
char linha[50];
FILE *arquivo;


arquivo = fopen("teste.txt","r");
if (!arquivo) {
exit(1);
} else {
printf("\nDigite o NomeDoCurso: \n");
scanf("%s",&nomeCurso);

while (fgets(linha,sizeof(linha),arquivo)!=NULL) //lê linha a linha do arquivo

if (strstr(linha,nomeCurso)!=NULL) { //Verifica se uma string existe dentro de outra

fclose(arquivo);
return conf; //Retorna a confirmacao do curso;
}

}
}



Codigo da funcao de cadastro:


int TesteCadastro(void) {

char nomeCadastro[50];
int codCadastro = 0;
int conf = 1;
FILE *arquivo;
int result=0;

printf("\nDigite o Nome do cadastro: \n");
scanf("%s",&nomeCadastro);

printf("\nDigite o codigo de cadastro: [10 a 99] \n");
scanf("%d",&codCadastro);

if (codCadastro < 10 || codCadastro > 99) {
printf("\nCODIGO INVALIDO!! - CODIGO DEVE SER ENTRE 10 e 99\n");
getch();
} else {


arquivo = fopen("teste.txt","a+t");

if(arquivo != NULL) {

fprintf(arquivo, "%d %s\n",codCadastro,nomeCadastro);

fclose (arquivo);

return (conf);
}

}

}









  


2. Re: arquivos em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 09/12/2012 - 23:22h

A função strstr() realmente procura uma string contida dentro de outra. Desse modo, procurar "j" em "jao" vai retornar um valor positivo, pois de fato existe 'j' dentro de 'jao'.

Se você quiser uma comparação exata, possivelmente deverá usar strcmp().


3. Re: arquivos em C

Daniel
danielcrvg

(usa Slackware)

Enviado em 10/12/2012 - 12:22h

entendi...

e por exemplo, meu arquivo esta assim:

10 joao
20 maria
40 jose

Eu to querendo copiar a linha do meu arquivo para uma outra string, a partir do 3 elemento da linha, no caso so copiar o nome: joao




while (fgets(linha,sizeof(linha),arquivo)!=NULL) //lê linha a linha do arquivo

for (i=3; i<strlen(linha); i++) {

strcpy(nomeLinha, linha[i]);

}







Como ficaria??


4. Re: arquivos em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/12/2012 - 13:05h

Para copiar pulando os três primeiros caracteres da string original, você poderia usar o seguinte.

strncpy(destino, origem+3, tamanho_destino-1);
destino[tamanho_destino-1]=0;


Contudo, você tem certeza de que pode assumir que o número tem sempre dois acrateres de comprimento e que apenas um espaço existe entre o número e o nome? Se não quiser correr riscos, você pode fazer algo como o seguinte.

char linha[100], nome[100];
int codigo;

while(fgets(linha, sizeof linha, arquivo)!=NULL){
if(sscanf(linha, "%d %99[^\n]", &codigo, nome)==2){
/*
Aqui a linha foi convertida com sucesso, tanto o
código quanto o nome estão nos seus lugares.

Cole seu código abaixo.
*/
}
else{
/*
A linha está com um formato inesperado.
provavelmente você vai querer indicar erro.
*/
}
}



5. Re: arquivos em C

Daniel
danielcrvg

(usa Slackware)

Enviado em 11/12/2012 - 13:28h

Opa, eu tenho certeza de que sempre sera 2 algarismos + o espaco pq no momento que eu cadastro, eu sempre valido este numero, se esta entre 10 e 99, desta forma, so serao feitos cadastros usando 2 algarismos..

Segue abaixo a funcao do cadastro:


int TesteCadastro(void) {

char nomeCadastro[50];
int codCadastro = 0;
int conf = 1;
FILE *arquivo;
int result=0;


printf("\nDigite o Nome do cadastro: \n");
scanf("%s",&nomeCadastro);

printf("\nDigite o codigo de cadastro: [10 a 99] \n");
scanf("%d",&codCadastro);

if (codCadastro < 10 || codCadastro > 99) {
printf("\nCODIGO INVALIDO!! - CODIGO DEVE SER ENTRE 10 e 99\n");
getch();
} else {


arquivo = fopen("teste.txt","a+t");

if(arquivo != NULL) {

fprintf(arquivo, "%d %s\n",codCadastro,nomeCadastro);

fclose (arquivo);

return (conf);
}

}

}

Contudo, eu nao consegui entender seu codigo:

strncpy(destino, origem+3, tamanho_destino-1);
destino[tamanho_destino-1]=0;


- strncpy é a funcao que copia uma string de origem para uma string destino, certo??

- A syntaxe nao é assim: strncpy(destino, origem) ??? O que é este tamanho_destino-1??

- O '+3' eu acho q entendi, ele aponta o indice para a 3a 'casa' da string, certo?

- E o que significa esta destino[tamanho_destino-1]=0; ??


6. Re: arquivos em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/12/2012 - 15:21h

1 e 2)
Eu recomendo que você leia a documentação para aprender com detalhes. Resumidamente, a diferença entre strcpy() e strncpy() é que a segunda tem um campo a mais que informa o número máximo de caracteres que serão copiados. A razão pela qual você deve preferir strncpy() a strcpy() é que é muito fácil, com esta última, exceder o tamanho máximo da string destino, e escrever bytes em áreas de memória inválidas, provocando falhas impredizíveis no programa, ou áreas ocupadas por outras variáveis, corrompendo-as. Por exemplo, o código abaixo demonstra uma corrpução desse tipo.

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

int main(void){
int a=0xAAAAAAAA, b=0xBBBBBBBB;
char str[4]="str";
int c=0xCCCCCCCC, d=0xDDDDDDDD;

printf("Antes: a=%X, b=%X, str=\"%s\", c=%X, d=%X\n", a, b, str, c, d);
strcpy(str, "Este aqui e um texto mais longo do que o tamanho do destino.");
printf("Depois: a=%X, b=%X, str=\"%s\", c=%X, d=%X\n", a, b, str, c, d);
return 0;
}


Ao compilar e executar o programa, eu recebo o seguinte.

$ gcc lixo.c 
$ ./a.out
Antes: a=AAAAAAAA, b=BBBBBBBB, str="str", c=CCCCCCCC, d=DDDDDDDD
Depois: a=AAAAAAAA, b=BBBBBBBB, str="Este aqui e um texto mais longo do que o tamanho do destino.", c=CCCCCCCC, d=DDDDDDDD
*** stack smashing detected ***: ./a.out terminated
Segmentation fault (core dumped)


Se eu transformar as variáveis em globais, movendo as três primeiras linhas de main() para fora do corpo da função, eu recebo o seguinte.

$ gcc lixo.c 
$ ./a.out
Antes: a=AAAAAAAA, b=BBBBBBBB, str="str", c=CCCCCCCC, d=DDDDDDDD
Depois: a=AAAAAAAA, b=BBBBBBBB, str="Este aqui e um texto mais longo do que o tamanho do destino.", c=75716120, d=20652069


Em ambos os casos, se eu tivesse usando strncpy() com o tamanho máximo apropriado para a string destino, conforme mostrei na mensagem anterior, o conteúdo de str ficaria apenas como "Est", não provocando stack smashing nem corrompendo os valores de outras variáveis.


3) Não. O origem+3 significa pular os três primeiros elementos de origem, começando, portanto, a contar do quarto elemento.


4) Por convenção, toda string em C termina obrigatoriamente com um byte nulo (valor zero). No programa acima, você vê que eu faço str[4]="str" porque ela de fato tem quatro elementos, que são os bytes 's', 't', 'r' e nulo (em C, o byte nulo pode ser escrito como o caráter de barra invertida ("\") seguido de zero, mas o fórum do VoL engasga quando se escrevem esses dois caracteres aqui). Assim, forçar o n-ésimo elemento (geralmente o último) de um array de caracteres a ter o byte nulo é uma forma de garantir que todas as funções do sistema conseguirão determinar o fim da string com sucesso.

Para você ver o problema de esquecer-se de garantir isso, veja o seguinte código, que deliberadamente cria um array que não tem o byte nulo na última posição de memória alocada, e, logo em seguida, a saída correspondente quando eu o compilei e executei na minha máquina (note que o tamanho e os bytes adicionais que aparecem são meio que por acaso; é imprevisível o que vai sair se você fizer o mesmo na sua máquina, podendo até dar erro fatal no programa).

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

int main(void){
/* Note que o array abaixo nao atende as convencoes de uma string. */
char array[4]={'a', 'b', 'c', 'd'};

printf("Comprimento de array: %zd bytes.\nConteudo: \"%s\"\n", strlen(array), array);

return 0;
}


$ gcc lixo.c
$ ./a.out
Comprimento de array: 6 bytes.
Conteudo: "abcdÿ~"



7. Re: arquivos em C

Daniel
danielcrvg

(usa Slackware)

Enviado em 12/12/2012 - 22:21h

Muito obrigado pela explicacao, foi muito util.

Porem eu nao consegui implementar meu codigo, com as linhas que vc passou, nao funcionou..

Aquele lance e colocar o '+3' para a funcao strncpy copiar a partir do 3 caracter funcionou, porem quando eu comparo com a linha, nao da certo..

Tipo eu nao consigo definir o tamanho do numeros de caracteres que eu vou copiar. Pois eu nao estou copiando string para string, estou copiando uma string de dentro de um arquivo para dentro de uma outra string, e essa nova string eu comparo com a string digitada pelo usuario, porem eu tentei com todoas as funcoes fazer a comparacao e nao deu certo, strcmp, strstr, nenhuma delas eu consegui fazer a comparacao acontecer...


Se puder me ajudar a inserir essas linhas no codigo eu agradeco, mas de qualquer forma, ja foi uma grande ajuda estas explicacoes sobre lixo, etc...


8. Re: arquivos em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 14/12/2012 - 11:22h

danielcrvg escreveu:

Muito obrigado pela explicacao, foi muito util.

Porem eu nao consegui implementar meu codigo, com as linhas que vc passou, nao funcionou..


Implementar o quê e onde? Mostre o bloco de código, para que eu possa ver o que pode estar errado, e então ajudar a resolver ou mostrar a forma certa de fazer.

Aquele lance e colocar o '+3' para a funcao strncpy copiar a partir do 3 caracter funcionou, porem quando eu comparo com a linha, nao da certo..


De novo, mostre como você tentou usar, tanto na cópia quanto na comparação.

Tipo eu nao consigo definir o tamanho do numeros de caracteres que eu vou copiar. Pois eu nao estou copiando string para string, estou copiando uma string de dentro de um arquivo para dentro de uma outra string, e essa nova string eu comparo com a string digitada pelo usuario, porem eu tentei com todoas as funcoes fazer a comparacao e nao deu certo, strcmp, strstr, nenhuma delas eu consegui fazer a comparacao acontecer...


Mostre também o código dessa leitura e seu encaminhamento para as strings que você vai manipular.

Note que strncpy() não diz a quantidade a ser copiada, mas um limite máximo de caracteres que a string destino consegue suportar durante essa cópia. Por exemplo, se a string destino suportar 20 caracteres, você deveria dizer que o número máximo de caracteres que ela suporta é 19 (lembrando que o 20º elemento deve ser um byte nulo), independentemente de qual seja o tamanho da string original a ser copiada: se for menor que 19, ótimo, a cópia vai parar no tamanho da string original mais o byte nulo que marca seu final; se for 19 ou mais, a cópia vai parar após o 19º caráter, e será sua obrigação garantir que o 20º caráter da string destino seja o byte nulo.


9. Re: arquivos em C

Daniel
danielcrvg

(usa Slackware)

Enviado em 18/12/2012 - 15:45h

Opa mil desculpas a demora, eu tava semana de prova, mas agora ja acabou..



Entao segue abaixo o codigo da funcao que estou tentando implementar:


int VerificarCurso () {

int conf=69;
char nomeCurso[50];
char linha[50];
FILE *arquivo;
char nomeCadastro[50];


arquivo = fopen("teste.txt","r");

if (!arquivo) {
exit(1);
} else {

printf("\nDigite o NomeDoCurso: \n");
scanf("%s",&nomeCurso);

while (fgets(linha,sizeof(linha),arquivo)!=NULL) //lê linha a linha do arquivo

strncpy(nomeCadastro, linha+3, 50); //Aqui eestou tentando copiar para dentro de nomeCadastro a partir da posicao '3' da linha

if (strcmp(nomeCadastro, nomeCurso)) {

//if (strstr(linha,nomeCurso)!=NULL) { //Verifica se uma string existe dentro de outra

fclose(arquivo);
return conf; //Retorna a confirmacao do curso;

}

}
}



10. Re: arquivos em C

euteste da silva
foxbit3r

(usa Solaris)

Enviado em 20/12/2012 - 10:52h

Segue ai o que você precisa.



#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {


char linha[50],*ptr;
FILE *arquivo;
char nome[50];

arquivo = fopen("teste.txt","r");
if (!arquivo) {
exit(1);
} else {
printf("Nome do curso: ");
gets(nome);

while (fgets(linha,sizeof(linha)-1,arquivo)!=NULL){
ptr = strtok(linha," ");
ptr = strtok(NULL," ");
if(strncmp(ptr,nome,strlen(nome))==0)
printf("Encontrado: %s\n",ptr);

}
fclose(arquivo);
}

}


Marque como resolvido se isso resolver o seu problema.

Obs.: strcmp after strtok que utilizei como pesquisa.


11. Re: arquivos em C

Daniel
danielcrvg

(usa Slackware)

Enviado em 20/12/2012 - 11:43h

Opa, blz? entao testei, ela esta fazendo a mesma coisa que a minha funcao...

Se dentro do arquivo 'teste.txt' esta assim:

10 joao
20 maria


Se pesquisar assim: jOao
ela(funcao) nao acha, tudo certo.....

se pesquisar assim: jao
ela nao acha novamente, tudo certo....

Porem, se eu pesquisar somente: j
ela ta achando, e na realidade ela esta ate certa, pq j esta dentro da "palavra" 'joao' dentro do arquivo...

Eu queria implementar para isto nao ocorrer, ou seja, alem da "palavra" digitada pelo usuario estar "dentro" da linha, ela deve ter o mesmo tamanho. Desta forma, eu espero, que seja possivel fazer esta implementacao...





12. Tenta isso aqui

Enzo de Brito Ferber
EnzoFerber

(usa FreeBSD)

Enviado em 20/12/2012 - 17:51h

Pelo que eu entendi, você quer comparar apenas as palavras inteiras, mas tem que reconhecer espaços né?

Vê se isso aqui ajuda, a função stripnumber() retira o número inicial da frase, e retira também o NEWLINE no final da linha.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* stripnumber ( char *str )
{
// isso tira o \n do final da string
// o \n que o fgets colocou lá....
// isso faz o strcmp funcionar...
str[strlen(str)-1] = 0x0;

// encontra o primeiro espaço
// isso retira o número inicial da linha
while ( (*str != ' ')) *str++ ;

// como ele foi só até o espaço
return (str + 1); // tira espaço
}

int main ( void )
{
FILE *fp;
char search[50];

char *line = (char*)malloc(100*sizeof(char));
char *ln;

fp = fopen ( "data.txt", "r" );

printf ( "Search: "); scanf("%[^\n]", search );

while ( (fgets(line, 100, fp )) != NULL )
{
ln = stripnumber(line);

if ( !(strcmp ( ln, search)))
printf ( "%s\n", line );

}

return 0;
}


Qualquer coisa posta denovo,
Enzo Ferber



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts