Parse file into struct - c

I'm working on this C project (I'm fairly new to C), where I have to parse data from a file into a 2D array which is an element of a structure defined as follows:
typedef struct {
int x;
int y;
char ** result;
} gameF;
The file contains two integers at the top and these integers dictate the size of the 2D array result, while the data to be entered into this array is in a newline below them. Thus far, I have written the following code, but keep getting a segmentation error. I know that the problem lies somewhere between lines 11 and 16, since I have tried the rest of the code after commenting out these lines and it works fine.
gameF * Parsefile(char * fp){
FILE * ResData;
ResData = fopen(fp, "r");
gameF * MyF = malloc(sizeof(gameF));
char line[52];
while(fgets(line, 52, ResData) !=NULL){
int num = 0;
if(sscanf(line, "%d %d", &(*MyF).x, &(*MyF).y) != 0){
continue;
}
int i; // L11
for(i=0; i<52; i++){
if(line[i]==' '){
break;
}
(*MyF).result = line [i]; // L16
}
num ++;
}
return MyF;
}
Please help!

You are not allocating space (malloc) to (*MyF).result, before the assignment at line 16.
So the pointer is pointing to an invalid location in memory.
Also you are assigning the to member result to a single char (instead of a string) with
(*MyF).result = line [i];

Related

c Struct Array, Storing string and its occurrence and writing it to a file

so I'm having a little problem with my struct array not doing what its supposed to. I get no compiler warnings or errors when building the program.
int Array_Size=0;;
int Array_Index=0;
FILE *Writer;
struct WordElement
{
int Count;
char Word[50];
};
struct WordElement *StructPointer; //just a pointer to a structure
int Create_Array(int Size){
StructPointer = (struct WordElement *) malloc(Size * sizeof(StructPointer));
Array_Size = Size;
return 0;
}
int Add_To_Array(char Word[50]){
int Word_Found=0;
for(int i=0; i <= Array_Size && Word_Found!=1; i++)
{
if(strcmp(StructPointer[i].Word, Word)) // This should only run if the word exists in struct array
{
StructPointer[i].Count++;
Word_Found=1;
}
}
if(Word_Found==0) // if the above if statement doesnt evualate, this should run
{
strcpy(StructPointer[Array_Index].Word, Word); //copying the word passed by the main function to the struct array at a specific index
printf("WORD: %s\n", StructPointer[Array_Index].Word); // printing it just to make sure it got copied correctly
Array_Index++;
}
return 0;
}
int Print_All(char File_Name[50])
{
Writer = fopen(File_Name, "w");
printf("Printing starts now: \n");
for(int i=0; i < Array_Size; i++)
{
fprintf(Writer, "%s\t\t%d\n",StructPointer[i].Word, StructPointer[i].Count);
}
free(StructPointer);
return 0;
}
These functions get called from a different file, The Add_To_Array is called when the program reads a new word form the text file. That function is supposed to check if the word already exists in the struct array and if it does, it should just increment the counter. If it doesn't, then it adds it.
The Print_All function is called after all the words have been stored in the struct array. Its supposed to loop through them and print each word and their occurrence. In the text file, there are 2 of every words but my program outputs:
this 13762753
document -1772785369
contains 1129268256
two 6619253
of 5701679
every 5570645
word 3342389
doccontains 5374021
I don't know what to make of this as im really new to C programming... It's probably worth mentioning the if(Word_Foun==0) doesn't execute
StructPointer = malloc(Size * sizeof(*StructPointer));
This will be the correct allocation. Otherwise you will have erroneous behavior in your code. Also check the return value of malloc.
StructPointer = malloc(Size * sizeof(*StructPointer));
if(NULL == StructPointer){
perror("malloc failure");
exit(EXIT_FAILURE);
}
You are allocating for struct WordElement not a for a pointer to it. You already have a pointer to struct WordElement all that you needed was memory for a struct WordElement.
Also in the loop you are accessing array index out of bound
for(int i=0; i <= Array_Size && Word_Found!=1; i++)
^^^
It will be i < Array_Size.
In case match occurs you want to set the variable Word_found to 1.
if(strcmp(StructPointer[i].Word, Word) == 0){
/* it macthed */
}
Also Writer = fopen(File_Name, "w"); you should check the return value of fopen.
if(Writer == NULL){
fprintf(stderr,"Error in file opening");
exit(EXIT_FAILURE);
}
Also when you are increasing the Array_index place a check whether it might access the array index out of bound.
The more global variable you use for achieving a small task would make it more difficult to track down a bug. It is always problematic because the places from which data might change is scattered - making it difficult to manage.

pass dynamic array of pointers to C function

I want to store each line of the file in an 2D array, and anthor array pointing each line (so I can identify each line), I need to pass this pointers array to a function so I can manipulate my lines, I d'ont know how to do that
I have this code to read and store in the arrays
char ligne[MAX];
//open end test the file
FILE* fichier = fopen("csp.txt","r");
if(fichier == NULL){
printf("can't open the file \n");
return EXIT_FAILURE;
}
//the first line in the file contain number of other lines
fgets(ligne, sizeof(ligne), fichier);
int nbrTaille = strtol(ligne, NULL, 10);
//array of pointers
char (*tab)[nbrTaille] = malloc(nbrTaille * sizeof(ligne));
int i = 0;
//tab array point each line
while(fgets(ligne, sizeof(ligne), fichier)){
if(ligne == NULL) EXIT_FAILURE;
strncpy(tab[i], ligne, strlen(ligne));
printf("line%d : %s\n", i, tab[i]);
i++;
}
//call the funnction by passing array of pointers and the number of lines
allDiff(tab, nbrTaille);
the file I'm reading is
2
1 2
2 3
to receive the array by the function I tried this but it doesn't work
void allDiff(char** T, int taille)
I am always confused with the parenthesies and asterisks. The easier way is to declare a double pointer:
char ** tab;
//you need to take care of errors. I am not doing it for simplicity
//tab = {pointer1, pointer2, pointer3, ...., pointerN} total memory needed N * sizeof(pointer)
tab = malloc(lines* sizeof(tab)); //how many pointers you want
for(i = 0; i < lines; i++){
tab[i] = malloc(MAX); //each string
}
In the end free the memory:
for(i = 0; i < lines; i++){
free(tab[i]);
}
free(tab);
EDIT complete code
char ligne[MAX];
//open end test the file
FILE* fichier = fopen("csp.txt","r");
if(fichier == NULL){
printf("can't open the file \n");
return EXIT_FAILURE;
}
//the first line in the file contain number of other lines
fgets(ligne, sizeof(ligne), fichier);
int nbrTaille = strtol(ligne, NULL, 10);
//array of pointers
//char (*tab)[nbrTaille] = malloc(nbrTaille * sizeof(ligne));
int i = 0;
char **tab;
tab = malloc(nbrTaille * sizeof(tab)); //how many pointers you want
for(i = 0; i < nbrTaille; i++){
//sizeof(ligne) is equal to MAX
tab[i] = malloc(MAX); //each string
}
i = 0;
//tab array point each line
while(fgets(ligne, sizeof(ligne), fichier)){
if(ligne == NULL) EXIT_FAILURE;
strncpy(tab[i], ligne, strlen(ligne));
printf("line%d : %s\n", i, tab[i]);
i++;
}
//call the funnction by passing array of pointers and the number of lines
allDiff(tab, nbrTaille);
void function(char tab[][MAXLEN], ...);
This will do.
For the sake of readbility and sanity, typedef C function pointers before creating arrays or double pointers to them.
/* typedef the function pointer. An ftabptr points to a void function that
takes a char * */
typedef void (*ftabptr)(char *p);
/* create an uninitalised list of twenty of them */
int N = 20;
ftabptr *pointerlist = malloc(N * sizeof(ftabptr));
However I don't think you really want to do this. You can write a
functioning program that does weird things with tables of function
pointers, but normally you use a language other than C if you
want to play that game (Lisp-like languages, etc). The high level
language then often emits C as an intermediate step.

Scanf leads to segfault

I have a text file:
In 0 John 66
In 1 May 77
In 0 Eliz 88
Out 0
Out 0
I'm trying to parse this text file using scanf, and at the moment send the values after "In" to the add function, however I'm getting a seg fault when trying to do this.
I have some code here:
A struct in a seperate header file:
typedef Officer test;
typedef struct {
test tests[6];
int s;
} copList;
And this one:
typedef struct {
char name[25];
int id;
} Officer;
Then I have my main method
int main(void) {
FILE * ptr;
char buffer [500];
char * temp;
int pos;
int grade;
char * name;
copList * L;
ptr = fopen("test.txt","r");
if(ptr == NULL)
exit(1);
temp = malloc(sizeof(char)*10);
name = malloc(sizeof(char)*10);
L = malloc(sizeof(copList));
while(fgets(buffer,500,ptr) != NULL) {
sscanf(buffer,"%s %d %s %d\n",temp,&pos,name,&grade);
add(L->tests[pos],pos,L); //this gives me a seg fault
}
free(name);
free(temp);
free(L);
fclose(ptr);
return 0;
}
In a separate c file I have the add function.(Can't be changed)
void add(Test b, int pos, copList * L) {
//code to be added here later...
}
I've tried allocating different amounts of memory, but that didn't help. Also I noticed if I set a value to pos, in the while loop, before the add function call, I don't get a seg fault, but obviously that's not what I want, because the value wouldn't change. Any help would be much appreciated.
The main problem I see with your code is that it does not check the return value of sscanf -- if sscanf returns something other than 2 or 4, that means your input is something other than what you say it is. In addition, the arrays temp and name might overflow (on inputs other than what you show), which would cause undefined behavior. Finally, the spaces and \n in the sscanf format are wrong and should be removed (though they shouldn't actually cause any problems in this case.)
So you code should be something like:
while(fgets(buffer,500,ptr) != NULL) {
int count = sscanf(buffer,"%9s%d%9s%d",temp,&pos,name,&grade);
if (count != 2 && count != 4) {
fprintf(stderr, "Invalid input line: %s", buffer);
continue; }
... do stuff with temp and pos (only use name and grade if count == 4)
in this line:
add(L->tests[pos],pos,L);
the first parameter is a copy of the 'test' struct.
It is almost always a bad idea to pass a whole struct. Much better to just pass a pointer to the struct:
add( &(L->tests[pos]), pos, L );
Then, this line has a couple of problems:
void add(Test b, int pos, copList * L) {
1) 'Test' is a non-existent type, perhaps you meant: 'test'
2) 'b' is expecting a passed struct. as mentioned above,
it is (almost) always better to pass a pointer to a struct.

Segmentation Fault(core dumped) - Structure;

So I have the following question:
I have this struct ListAut
struct ListAut{
char* biggestn;
int sizeof_biggestn;
int total_len;
struct node* avl;
};
Its typedef is as it follows:
typedef struct ListAut *IndexOfAuts;
IndexOfAuts *newIndexOfAuts()
{
int i;
IndexOfAuts *ioa = malloc(27 * sizeof(struct ListAut));
for (i = 0; i < 27; i++)
{
ioa[i]->biggestn = "";
ioa[i]->sizeof_biggestn = 0;
ioa[i]->total_len = 0;
ioa[i]->avl = NULL;
}
return ioa;
}
void insertName(IndexOfAuts * ioa, char *nome)
{
char *aux = malloc(sizeof(nome));
aux = trim(nome);
int index = getIndexOfLetter(aux);
if (nameLen(aux) > getSizeOfLongName(ioa[index]))
{
strcpy(ioa[index]->biggestn, aux);
ioa[index]->sizeof_biggestn = nameLen(aux);
}
ioa[index]->total_len += nameLen(aux);
insert(ioa[index]->avl, aux);
}
This is an important part of a module I need for a project, and on its main it's Seg Faulting. I suspect it's on the creation of an "object" newIndexOfAuts(),
The idea of this module is to have an array of 27 pointers to those structures, one to each letter and another to the special characters;
Now I'm just confused because it might be from the problem above or from a module loader I made:
void loadModules(char *filename, IndexOfAuts * ioa, StatTable st)
{
char *nameofile = malloc(20);
strcpy(nameofile, filename);
FILE *file = fopen(nameofile, "r");
if (file != NULL)
{
int counter, ano;
char *buff, *field, *auxil;
buff = malloc(1024);
field = malloc(200);
auxil = malloc(200);
while (fgets(buff, 1024, file))
{
counter = 0;
field = strtok(buff, ",");
printf("inserting 1st name\n");
insertName(ioa, field);
counter++;
while (!atoi(field))
{
if ((auxil = strtok(NULL, ",")) != NULL)
{
counter++;
field = auxil;
insertName(ioa, field);
}
}
ano = atoi(field);
incPub(st, ano, counter - 1);
}
fclose(file);
}
}
When i run this in main that has the following lines:
printf("Creating Stat Table");
StatTable st=newStatTable();\\This Line is correct, i checked it,i hope
printf("Creating index");
IndexOfAuts* ioa=newIndexOfAuts();
printf("Loading Modules");
loadModules(filename,ioa,st);
Those prints were for me to see where was the cause of the seg fault, but the last line printed was the "Creating Index".
There are several cases of undefined behavior and one memory leak (and a possible case of undefined behavior too):
You have this initialization ioa[i]->biggestn=""; It make the biggestn member point to a constant array of one character (the '\0' character). You then do strcpy(ioa[index]->biggestn,aux); which will write over a constant character, and then go outside of the array writing into unknown memory.
You have this: char* aux=malloc(sizeof(nome)); That allocates only 4 or 8 bytes, which the size of the pointer and not what the pointer points to. Use strlen to get the length of a string.
For the above allocation you also need to allocate a byte extra, as strlen only returns the length of the string without the terminator.
You have aux=trim(nome); This overwrites the pointer you just allocated, leading to a memory leak.
The above call might also lead to undefined behavior if you return a pointer to a local variable or array.
There are probably other problematic lines, these were just the ones I found on a quick glance.
And a general tip: Learn to use a debugger! The debugger is a programmers best tool next to the compiler. If you run your program in a debugger, the debugger will stop at the location of the crash, and let you examine (and also walk up) the function call stack, as well as let you examine values of variables.

Adding a struct to an array using a pointer

I am fairly new to the C language and allocating memory/using pointers in general. Anyway, I was experimenting with reading a file, putting those values in a struct, etc. I know exactly what I want to do and of course the program runs but the output is incorrect and some kind of jumbled numbers and letters.
There is a text file with new information for each line. Each line represents one object.
This is how a line in the file might look:
meat sirloin 6.55 8 8.50 4
Overall I want to be able to store all of my PRODUCT objects in an array (so I have an array of structs). So I attempted to allocate memory with a pointer, use a line count, and then send the pointer to a function called read. In read I add each struct to the array via a pointer. The program doesn't crash, the output is just not correct and I have no clue why not. It's prob something with pointers. If anyone could help me I would really appreciate it. Any help at all would be great.
//prototype
void read(pointerToArr);
typedef struct
{
char supType[15];
char prodName[15];
double wholePrice;
int quantWhole;
double retPrice;
int retProdQuantity;
}PRODUCT;
FILE *fr;
int lineCount = 0;
int main()
{
PRODUCT *ptr;
int i;
char check[50];
fr = fopen("ttt.txt", "r");
while(fgets(check, sizeof(check), fr)!= NULL)
{
if(check[0] != '\n')
{
lineCount++;
}
}
// allocate memory for array based on line count.
PRODUCT prodContainter[lineCount];
ptr = (PRODUCT*)malloc(sizeof(PRODUCT)*lineCount);
ptr = prodContainter;
read(ptr);
//print after adding to array via pointer from other
//function. this was a test.
for(i = 0; i < lineCount; i++)
{
printf("%s ", prodContainter[i].supType);
printf("%s ", prodContainter[i].prodName);
printf("%f ", prodContainter[i].wholePrice);
printf("%d ", prodContainter[i].quantWhole);
printf("%f ", prodContainter[i].retPrice);
printf("%d\n\n", prodContainter[i].retProdQuantity);
}
return 0;
}
void read(PRODUCT *pointerToArr)
{
// objective in this method is to read in data from the file, create an object for every line and
// then use the pointer array to add those objects to prodConstainer up above.
char supplyName[15];
char productName[15];
double wholeP = 0;
int quantityWhole = 0;
double retailPrice = 0;
int retailProductQuant = 0;
while(fscanf(fr, "%s %s %lf %d %lf %d", supplyName, productName, &wholeP, &quantityWhole, &retailPrice, &retailProductQuant) == 6)
{
PRODUCT record;
int i;
strcpy(record.supType, supplyName);
strcpy(record.prodName, productName);
record.wholePrice = wholeP;
record.quantWhole = quantityWhole;
record.retPrice = retailPrice;
record.retProdQuantity = retailProductQuant;
for(i = 0; i < lineCount; i++)
{
pointerToArr[i] = record;
}
}
fclose(fr);
}
You never rewind the file, so all the reading after you count the number of lines fails.
What you're printing is just what happens to be in memory.
There are many ways to fix this, of course.
Rewind the file, using rewind()
Close the file and let your read() function (whose name collides with a POSIX standard function, btw) re-open the file. This would also involve removing the scary global variable fr.
Re-structure so you never count the number of lines, by just reading and letting the ptr array grow as necessary (see realloc()).
Also, you should really avoid casting the return value of malloc() in C. This:
ptr = (PRODUCT*)malloc(sizeof(PRODUCT)*lineCount);
is better written as:
ptr = malloc(lineCount * sizeof *ptr);
This does away with the cast, and also uses sizeof on a value of the type pointed at to automatically compute the proper number of bytes to allocate.

Resources