-
From File To Memory
what i'm trying to basically do is copy a txt file to the memory but it's not working and i aint sure why..pls help me. thanx a lot.
here is my struct:
Code:
typedef char string7[8];
typedef char string15[16];
typedef char string50[51];
typedef struct //structure of the word
{
string7 strWord;
string15 strType;
int nLetters;
int nDefinitions;
string50 strDefinitions[5];
}structWord;
here is the code:
Code:
void loadDictionary(structWord aWords[], int nWordNumber, FILE *pFile)
{
int i, nChoice, j, k;
char *p;
string50 strTemp;
for(i = 0; i < nWordNumber; i++)
{
fgets(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
for(k=0; k<8; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
fgets(aWords[i].strType, sizeof(aWords[i].strType), pFile);
for(k=0; k<15; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
fscanf(pFile, "%d", &aWords[i].nLetters);
fscanf(pFile, "%d", &aWords[i].nDefinitions);
for(j = 0; j < aWords[i].nDefinitions; j++)
{
fgets(aWords[i].strDefinitions[j], sizeof(string50), pFile);
for(k=0; k<50; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
}
}
}
here is a part of the dictionary and the supposed screen ouptut:
Code:
History
Noun
7
2
a telling of events
a written report of past events
Disband
Verb
7
1
to break up and stop being a group
but when i try to print them out, the screen ouput is this!
Code:
//the code
puts(aWords[0].strWord);
puts(aWords[0].strType);
printf("%d", aWords[0].nLetters);
printf("%d", aWords[0].nDefinitions);
puts(aWords[0].strDefinitions[0]);
puts(aWords[0].strDefinitions[1]);
puts(aWords[1].strWord);
puts(aWords[1].strType);
printf("%d", aWords[0].nLetters);
printf("%d", aWords[0].nDefinitions);
puts(aWords[1].strDefinitions[0]);
//the ouput
History
00
Noun
7
00
why is it?!
-
> fscanf(pFile, "%d", &aWords[i].nLetters);
Mixing fscanf and fgets is the problem.
Use something like
char temp[BUFSIZ];
fgets( temp, sizeof temp, pFile );
sscanf( temp, "%d", &aWords[i].nLetters);
> for(k=0; k<8; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
This is awfully specific to each line, as you have a different loop count for each line.
Change the array size, and this becomes very error prone.
char *p = strchr( aWords[i].strWord, '\n' ); // find the newline, if there is one
if ( p != NULL ) *p = '\0'; // erase the one and only newline which fgets can return.
-
thanx a lot! i'll try to understand the code you gave!thanx again!
-
Code:
void loadDictionary(structWord aWords[], int nWordNumber, FILE *pFile)
{
int i, nChoice, j, k;
char *p, temp[BUFSIZ];
string50 strTemp;
for(i = 0; i < nWordNumber; i++)
{
fgets(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
*p = '\0';
fgets(aWords[i].strType, sizeof(aWords[i].strType), pFile);
if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
*p = '\0';
fgets(temp, sizeof(temp), pFile );
sscanf( temp, "%d", &aWords[i].nLetters);
fgets( temp, sizeof(temp), pFile );
sscanf( temp, "%d", &aWords[i].nDefinitions);
for(j = 0; j < aWords[i].nDefinitions; j++)
{
fgets(aWords[i].strDefinitions[j], sizeof(aWords[i].strDefinitions[j]), pFile);
if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
*p = '\0';
}
}
}
here is the code now, but the screen output is still not what i expected!this is much trouble.
i have to mix fscanf, and fgets because i need to copy a string, and then an integer, so you see i have to get into that trouble. i do not know what sscanf does, but from your code, it is still not working..
-
You don't have to mix them.
Read the data in with fgets(), then convert the things you need into numbers. Then you use the "breakpoint", which the converting function (strtol()) gave you and do something with the word that comes after the number.
-
i really think i'm getting close in solving this now..
i really don't know what u meant by breakpoint but anyway, here is the code"
Code:
fgets(cNum, sizeof(cNum), pFile); //line 1005
aWords[i].nLetters = atoi(cNum);
fgets(cNum, sizeof(cNum), pFile); //line 1008
aWords[i].nDefinitions = atoi(cNum);
from what i read, atoi is dangerous but i used anyway because i am not going to ask an input from a user and it is certain that the line from the file it is supposed to read is an integer, so there. cNum is declared as char. but there's an error:
Code:
1005 and 1008 D:\JarvB's Documents\JarvB's Files\DLSU\Compiler\Text Twist\10618384--PHASE2.c [Warning] passing arg 1 of `fgets' makes pointer from integer without a cast
cNum was declared as char so what integer is this error talkin about?
-
Could you show your declaration of cNum? And use strtol(), not atoi().
-
> typedef char string7[8];
But "History\n\0" (as returned by fgets()) is 9 characters, not 8
So my first set of results look like this
Code:
$ cat new.txt && ./a.exe
History
Noun
7
2
a telling of events
a written report of past events
Disband
Verb
7
1
to break up and stop being a group
0
word=History
type=
Num string=Noun, val=0
Num string=7, val=7
1
word=to brea
type=k up and stop b
Num string=eing a group, val=2089872920
Num string=, val=2089878896
It's already gone wrong by the time the first type is read, so after that everything is out of sync.
By allowing an extra space in the strings, I get
Code:
0
word=History
type=Noun
Num string=7, val=7
Num string=2, val=2
1
word=Disband
type=Verb
Num string=7, val=7
Num string=1, val=1
Here's the full code - note that your newline clearing code always used the same array (more copy/paste errors).
Code:
#include <stdio.h>
#include <string.h>
// +1 for the \n fgets() returns, which we eliminate
// +1 for the \0 at the end of every string
typedef char string7[8+1+1];
typedef char string15[16+1+1];
typedef char string50[51+1+1];
typedef struct //structure of the word
{
string7 strWord;
string15 strType;
int nLetters;
int nDefinitions;
string50 strDefinitions[5];
} structWord;
char *fgetsNoNewline(char *buff, size_t bufsiz, FILE * fp)
{
char *result;
result = fgets(buff, bufsiz, fp);
if (result != NULL) {
char *p = strchr(buff, '\n');
if (p != NULL)
*p = '\0';
}
return result;
}
void loadDictionary(structWord aWords[], int nWordNumber, FILE * pFile)
{
int i, j;
char temp[BUFSIZ];
for (i = 0; i < nWordNumber; i++) {
printf("%d\n", i);
fgetsNoNewline(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
printf("word=%s\n", aWords[i].strWord);
fgetsNoNewline(aWords[i].strType, sizeof(aWords[i].strType), pFile);
printf("type=%s\n", aWords[i].strType);
fgetsNoNewline(temp, sizeof(temp), pFile);
sscanf(temp, "%d", &aWords[i].nLetters);
printf("Num string=%s, val=%d\n", temp, aWords[i].nLetters);
fgetsNoNewline(temp, sizeof(temp), pFile);
sscanf(temp, "%d", &aWords[i].nDefinitions);
printf("Num string=%s, val=%d\n", temp, aWords[i].nDefinitions);
for (j = 0; j < aWords[i].nDefinitions; j++) {
fgetsNoNewline(aWords[i].strDefinitions[j], sizeof(aWords[i].strDefinitions[j]), pFile);
}
}
}
int main()
{
structWord arr[2];
FILE *fp = fopen("new.txt", "r");
if (fp != NULL) {
loadDictionary(arr, 2, fp);
fclose(fp);
// print a couple of samples
printf("%s\n", arr[0].strWord);
printf("%s\n", arr[1].strDefinitions[0]);
}
return 0;
}
Actually, because you allocate such small space, your code is very vunerable to minor formatting mistakes in the input file.
So where you have
fgetsNoNewline(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
It should really be
fgetsNoNewline(temp,sizeof temp, pFile);
temp[ sizeof(aWords[i].strWord) - 1] = '\0'; // make sure the string is always short enough
strcpy( aWords[i].strWord, temp ); // and copy it.
This truncate and copy should be done as a separate function as well.
Also, sscanf returns a result as well, which you should check before trying to use the converted answer.
-
i originally declared it as
Code:
char cNum;
//but then i changed it to:
char *cNum;
//then there are no more syntax errors
but then the program suddenly crashes when i call the function
i am quite confused with the parameters with strtol(), i am just trying to learn it now.
this is my code:
Code:
void loadDictionary(structWord aWords[], int nWordNumber, FILE *pFile)
{
int i, nChoice, j;
char *p, *q;
char *cNum;
string50 strTemp;
for(i = 0; i < nWordNumber; i++)
{
fgets(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
*p = '\0';
fgets(aWords[i].strType, sizeof(aWords[i].strType), pFile);
if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
*p = '\0';
fgets(cNum, sizeof(cNum), pFile);
aWords[i].nLetters = strtol(cNum, &q, 10);
fgets(cNum, sizeof(cNum), pFile);
aWords[i].nDefinitions = strtol(cNum, &q, 10);
for(j = 0; j < aWords[i].nDefinitions; j++)
{
fgets(aWords[i].strDefinitions[j], sizeof(aWords[i].strDefinitions[j]), pFile);
if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
*p = '\0';
}
}
the program crashes due to the cNum declaration
-
You do not allocate memory to it!
-
what's that suppose to mean?
-
Go back and start learning the basics if you don't know what that means. Noone is going to explain you the whole thing of pointers and memory here.
-
Tsk. Don't discourage people out of laziness.
char *cNum;
//then there are no more syntax errors
But syntax errors aren't the end of the world. Right now, as you've declared it cNum doesn't point to memory or another object, making it "wild." You cannot dereference a wild pointer because it points to an undefined location.
-
*shrug*
You're not going anwhere until you figure out that 9 bytes won't fit into 8.