-
Problem reading a file
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remover_newline(char *);
struct dados {
char matricula[5];
char nome[40];
char curso[20];
char nota[2];
} aluno;
int main(void)
{
char linha[40];
FILE *dados;
dados = fopen("dados.txt", "r");
if(dados == NULL){
printf("dados.txt - arquivo desconhecido\n");
getchar();
exit(1);
}
while(fgets(linha, sizeof(linha), dados) != NULL){
remover_newline(linha);
strcpy(aluno.matricula, linha);
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strcpy(aluno.nome, linha);
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strcpy(aluno.curso, linha);
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strcpy(aluno.nota, linha);
printf("aluno.matricula: %s\n", aluno.matricula);
printf("aluno.nome: %s\n", aluno.nome);
printf("aluno.curso: %s\n", aluno.curso);
printf("aluno.nota: %s\n\n", aluno.nota);
break;
}
fclose(dados);
return 0;
}
void remover_newline(char *linha)
{
char *ptr;
ptr = strchr(linha, '\n');
if(ptr != NULL)
*ptr = '\0';
}
dados.txt:
Code:
20457
Denis Rocha da Silva
Linguagem de programação
{5} {40} {20} {2}
98364
Tom Hanks
Teatro
{38} {42} {2} {27}
44078
Nicolas Cage
História
{11} {29} {5} {37}
10904
Sabrina da Silva Sauro
Matemática
{3} {43} {11} {18}
12003
Charles Petzold
Programação
{34} {23} {12} {1}
The output:
Code:
aluno.matricula: 20457Denis Rocha da Silva
aluno.nome: Denis Rocha da Silva
aluno.curso: Linguagem de program{5} {40} {20} {2}
aluno.nota: {5} {40} {20} {2}
I've been trying to fix this for a long time and it is driving me crazy. What am I doing wrong? I also have this strange feeling that there is a better way to do this. Help please.
-
I'm not so great at portuguese. What are you expecting from your program that isn't happening?
EDIT: Oh well. One thing I notice is that you're not allocating enough space for your strings:
Code:
char matricula[5];
char curso[20]
char nota[2];
The string you're storing in matricula is 6 characters, but you're only allowing for 5. Don't forget about the '\0' at the end of the string. Same with curso.
And nota, well, that string is definitely a lot longer than 2 characters.
-
Code:
struct dados {
char matricula[5];
char nome[40];
char curso[20];
char nota[2];
} aluno;
Make enough space for the text and trailing null.
Code:
20457
Denis Rocha da Silva
Linguagem de programação
{5} {40} {20} {2}
[edit]Why have a loop that always breaks in the first pass?
-
Geez, Dave. Give a guy enough time to edit his post will ya? ;)
-
That was lame :o
Thanks.
As for the break, I was trying to get it right first, that is why I used it.
-
I'm confused now...
Why does char nota[2] works with let's say numbers 34, 23, 54, 2 and char matricula[5] doesn't work with numbers like 12345, 74957, 35409?
-
> Why does char nota[2] works with let's say numbers 34, 23, 54, 2
That would be down to "luck".
The character arrays inside your struct may (or may not) be padded with spare bytes. So whilst you can apparently use these and have a "working" program, it still doesn't mean that its correct code.
Change your compiler or your struct, and it will just stop "working" for no readily apparent reason.
-
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remover_newline(char *);
struct dados {
char matricula[6]; /* 1 a mais por causa do \0 no final */
char nome[41]; /* mesma coisa... */
char curso[21]; /* mesma coisa... */
char nota[3]; /* mesma coisa... */
} aluno;
int main(void)
{
char linha[40];
FILE *dados;
dados = fopen("dados.txt", "r");
if(dados == NULL){
printf("dados.txt - arquivo desconhecido\n");
getchar();
exit(1);
}
while(fgets(linha, sizeof(linha), dados) != NULL){
remover_newline(linha);
strcpy(aluno.matricula, linha);
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strcpy(aluno.nome, linha);
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strcpy(aluno.curso, linha);
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strcpy(aluno.nota, linha);
printf("aluno.matricula: %s\n", aluno.matricula);
printf("aluno.nome: %s\n", aluno.nome);
printf("aluno.curso: %s\n", aluno.curso);
printf("aluno.nota: %s\n\n", aluno.nota);
/* pula a linha em branco */
fgets(linha, sizeof(linha), dados);
}
fclose(dados);
return 0;
}
void remover_newline(char *linha)
{
char *ptr;
ptr = strchr(linha, '\n');
if(ptr != NULL)
*ptr = '\0';
}
dados.txt:
Code:
20451
Denis Rocha da Silva
Arquitetura Arquiter
5
98364
Tom Hanks
Teatro
38
44076
Nicolas Cage
Futebol
44
10902
Sabrina da Silva Sauro
Basquete
3
12008
Charles Petzold
Tiro ao alvo
12
So, is this correct now?
-
I'm assuming you changed the data line for nota? There's a fundamental flaw in your program and if you fixed it, you wouldn't have to worry about any buffer overflow problems. Look at how you're reading in a line:
Code:
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strcpy(aluno.nome, linha);
The use of linha is problematic because linha is bigger than your smallest struct member. I'd go with one of three options to fix it:
1) Forget linha...get rid of it. Make your struct members 1 element bigger than you're ultimately going to need. Then you can just read in a line like so:
Code:
fgets(aluno.nome, sizeof(aluno.nome), dados);
remover_newline(aluno.nome);
2) Make sure linha is at least one bigger than the largest struct member and then use the size of the struct member as the second argument to fgets(). Something like:
Code:
fgets(linha, sizeof(aluno.nome)+1, dados);
remover_newline(linha);
strcpy(aluno.nome, linha); // If remover_newline() didn't remove a newline it will still overflow.
3) Use strncpy() instead of strcpy():
Code:
fgets(linha, sizeof(linha), dados);
remover_newline(linha);
strncpy(aluno.nome, linha, sizeof(aluno.nome));
aluno.nome[sizeof(aluno.nome)-1] = '\0';
Personally, I'd probably go with option 3.