Why does this part gives segmentation fault? - c

This is an incomplete code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define W 1031
#define B 256
struct FileCoordinates{
int x; /*line number*/
int y; /*word number*/
struct FileCoordinates *next;
};
struct FileStruct{
char *filename;
struct FileCoordinates *coordinates;
struct FileStruct *next;
};
struct WordStruct{
char *word;
struct WordStruct *left;
struct WordStruct *right;
struct FileStruct *files;
};
typedef struct FileCoordinates *CoorPtr;
typedef struct FileStruct *FilePtr;
typedef struct WordStruct *WordPtr;
WordPtr HashTable[W];
long int power(int a, long b){
long int pow, i;
pow = 1;
for (i = 0; i < b; i++){
pow = pow*a;
}
return pow;
}
int hashvalue (char *word){
long int i, value=0, n;
n = strlen(word);
for (i=0; i<n; i++){
value = value + power(B,n-i-1) * word[i];
}
return(value%W);
}
void putPosition(int x, int y, FilePtr *currfile){
CoorPtr currcors = (*currfile)->coordinates;
while (currcors!=NULL){
currcors = currcors->next;
}
currcors = (CoorPtr)malloc(sizeof(struct FileCoordinates));
currcors->x=x;
currcors->y=y;
}
void putFile(char *filename, WordPtr *currWord, int x, int y){
FilePtr currfile = (*currWord)->files;
while(currfile != NULL && strcmp(currfile->filename,filename)!=0){
currfile=currfile->next;
}
if (strcmp(currfile->filename,filename)==0){
putPosition(x, y, &currfile);
}
else{
currfile = (FilePtr)malloc(sizeof(struct FileStruct));
currfile->filename = filename;
putPosition(x, y, &currfile);
}
}
void insert(char *word, WordPtr *leaf, char *filename, int x, int y)
{
if( *leaf == NULL )
{
*leaf = (WordPtr) malloc( sizeof( struct WordStruct ) );
(*leaf)->word = word;
putFile(filename, &(*leaf), x, y);
/* initialize the children to null */
(*leaf)->left = 0;
(*leaf)->right = 0;
}
else if(word < (*leaf)->word)
{
insert( word, &(*leaf)->left, filename, x, y);
}
else if(word > (*leaf)->word)
{
insert( word, &(*leaf)->right, filename, x, y);
}
else if(word == (*leaf)->word){
putFile(filename, &(*leaf), x, y);
}
}
int main(int argc, char *argv[]){
int i, words, lines, value;
char *filename, *word, c;
FILE *fp;
word = (char *)malloc(21*sizeof(char));
if (argc<2){
perror("no files were inserted");
}
for (i=1; i<argc; i++){
words=1;
lines=1;
fp = fopen(argv[i], "r");
if (fp==NULL){
printf("Could not open file named %s! \n", argv[i]);
return 2;
}
filename = malloc( strlen( argv[i] ) + 1 );
strcpy( filename, argv[i] );
fscanf(fp, "%s", word);
value=hashvalue(word);
c=getc(fp);
insert(word, &HashTable[value], filename, lines, words);
if (c==' '){
words = words+1;
}
else if(c=='\n'){
lines=lines+1;
words=1;
}
}
system("PAUSE");
return 0;
}
And debugger gives me segmentation fault at this part:
while(currfile != NULL && strcmp(currfile->filename,filename)!=0){
currfile=currfile->next;
}
The reason of the code is to get text files as arguments, sort the words into binary trees placed in the hashtable and then by searching the keyword it shows you the coordinates it appears.
Anyway, i know this is a very novice code but im trying to understand.

You forget to set currfile->next to NULL when you create the object:
currfile = (FilePtr)malloc(sizeof(struct FileStruct));
currfile->filename = filename;
Reserve space with calloc instead of malloc, or add:
currfile->next = NULL;

Where do you initialize files? (Hint: you don't). This means it is an undefined value (not necessarily NULL). You need to initialize files before calling putFile.
As noted in the comment, once you fix that one, you need to do the same for next in both FileCoordinates and FileStruct and for coordinates in FileStruct.
Also as noted in the comments, you reuse the word buffer, meaning that all the nodes in the tree will have the same string. You should allocate a new buffer for the string when it is stored in the tree. Perhaps use strdup.
(*leaf)->word = strdup(word);
Once that is fixed, you also need to work on your string comparison. if(word == (*leaf)->word) compares the pointers, not their contents. You need to use strcmp if you want to compare the actual string data.
else if(strcmp(word, (*leaf)->word) == 0){

Related

Incompatible pointer type when making structure of function pointers

I'm trying to make a array of structures which contain a string and a function pointer, however when I compile I get a warning that I've initialized from an incompatible pointer type.
I have no idea why (sorry if I sound ignorant, I'm fairly new to C programming).
typedef struct
{
char Player1[2], Player[2], **gameGrid;
int height,width;
int moveNum, player1Num, player2Num;
bool player1Win, player2Win;
}Game;
typedef int (*pointer_func)(Game *);
typedef struct
{
char *funcName;
pointer_func *f;
}userFunc;
int save(Game *struc);
int load(Game *struc);
int move(Game *struc);
int quit(Game *struc);
void free_grid(Game *struc);
int main(){
//initialised variables
userFunc Name_arr[] = {
{"save",save},
{"load",load},
{"quit",quit},
{"move",move}
};
The four functions being referenced are as follows:
int save(Game *struc)
{
char *str, *inputString, *writeString;
FILE *fp;
int nextPlayer;
int maxRead = 20;
bool DIRresponse;
while(true)
{
printf("Please provide a file name (20 characters max): ");
inputString = input_String(inputString, maxRead, stdin);
if((DIRresponse = check_Directory(inputString)) == true){
printf("That name already exists, choose another\n");
continue;
}
else
break;
}
if(struc->moveNum % 2 == 0)
nextPlayer = struc->player1Num;
else
nextPlayer = struc->player2Num;
sprintf(str,"%s.txt",inputString);
fp = fopen(str,"w");
sprintf(writeString, "%d %d %d %d %d", nextPlayer, struc->height,
struc->width, struc->moveNum, struc->moveNum);
fprintf(fp,writeString);
fclose(fp);
return 0;
}
int move(Game *struc)
{
return 1;
}
int load(Game *struc)
{
return 1;
}
int quit(Game *struc)
{
free_grid(struc);
exit(EXIT_SUCCESS);
}
You have a mismatch in levels of pointers:
typedef int (*pointer_func)(Game *); << Pointer type
typedef struct
{
char *funcName;
pointer_func *f; << Pointer to a pointer type.... OOPS
}userFunc;
Make *f -> f and it should work.

Unsure of how to store integers from a file to a struct in c

I created two structs to store values in.
struct pair {
int x_pos;
int y_pos;
};
struct coordinates_header {
int length;
struct pair data[1000];
};
typedef struct coordinates_header coordinates;
coordinates *coords;
I then try to store data from a file using
char line[max_read];
int x, y;
FILE *in_file = fopen(filename, "r");
int i = 0;
coordinates *new = (coordinates *)coords;
while (fgets(line,max_read,in_file) != NULL) {
sscanf(line,"%d %d", &x, &y);
new -> data[i].x_pos = x;
new -> data[i].y_pos = y;
i++;
}
new -> length = i;
Then I try to print out the values
int print_struct(void *coords) {
coordinates *new = (coordinates *)coords;
for (int i = 0; i < new -> length; i++) {
printf("%d, %d\n", new->data[i].x_pos, new->data[i].y_pos);
}
return 0;
}
And then I get a segmentation fault
I was wondering if someone could point out where the error is. I have no experience with void but require the flexibility for the structure in some functions I'm going to use.
The file read will have the form
100 30
50 200
.. ..
I believe their are some mistakes in your code:
Instead of using coordinates *coords;, which is just a dangling pointer not pointing anywhere in memory, you should just declare a structure member coordinates coords.
Their is no need for void* pointers in your code. You would be better off using coordinates *coords to access the address of the structure member coordinates coords, instead of void *coords.
You are not checking the return value of FILE *in_file, which could return NULL if not opened properly.
It is always good to check the result of sscanf(), just incase two x and y coordinates were not found on a line.
With these recommendations, you can write your code like this:
#include <stdio.h>
#include <stdlib.h>
#define NUMCOORDS 1000
#define MAXREAD 100
typedef struct {
int x_pos;
int y_pos;
} coords_t;
typedef struct {
coords_t coords[NUMCOORDS];
int length;
} coordinates_t;
void print_struct(coordinates_t *coordinates);
int main(void) {
coordinates_t coordinates;
char line[MAXREAD];
FILE *in_file;
int i = 0;
in_file = fopen("coords.txt", "r");
if (in_file == NULL) {
fprintf(stderr, "Error reading file.\n");
exit(EXIT_FAILURE);
}
while (fgets(line, MAXREAD, in_file) != NULL) {
if (sscanf(line, "%d %d", &coordinates.coords[i].x_pos,
&coordinates.coords[i].y_pos) != 2) {
fprintf(stderr, "two coordinates(x, y) not found.\n");
exit(EXIT_FAILURE);
}
i++;
}
coordinates.length = i;
print_struct(&coordinates);
fclose(in_file);
return 0;
}
void print_struct(coordinates_t *coordinates) {
int i;
for (i = 0; i < coordinates->length; i++) {
printf("%d, %d\n", coordinates->coords[i].x_pos, coordinates->coords[i].y_pos);
}
}

Parsing function assigns proper value to array within itself but after call value is wrong

Having a problem with a 2D variable array of structs.
Trying to parse a text file and populate the array with the following function:
void populateTable(int x; int y; Entry table[x][y],
int x, int y, char fileName[])
{
char currentLineStr[8192];
int yIndex = 0;
FILE *fileIn;
FILE *fileOut;
fileIn = fopen(fileName, "r");
if(fileIn == 0)
{
perror("Cannot open input file\n");
system("PAUSE");
exit(-1);
}
else
{
fgets(currentLineStr, 8192, fileIn);
while (currentLineStr[0] == '#')
fgets(currentLineStr, 8192, fileIn);
TokenizeLine(currentLineStr, table, yIndex, x, y);
yIndex++;
while(fgets(currentLineStr, 8192, fileIn) != NULL)
{
TokenizeLine(currentLineStr, table, yIndex, x, y);
yIndex++;
//printf("%i\n",yIndex);
}
fclose(fileIn);
}
printf("%s\n", table[0][0].str);
printf("%f\n", table[1][0].dVal);
}
The printf statements at the end of this return the values that they should. However immediately after the call of this function I do the same printf statements and they return the wrong information.
int main(int argc, char *argv[])
{
char stringToFind[256] = {"DWL_FaceMountTile"};
char fileName[64] = {"rtest.txt"};
char timeFile[64] = {"timefile.msgr"};
int numEntries = 0;
int x;
int y;
double time;
double temp;
int tTableXdim = 36;
int tTableYdim = 20;
x = NumColumns(fileName);
y = NumRows(fileName);
Entry eTable[x][y];
Entry tTable[x][y];
int idInstances[y];
int rowQuantity[y];
double clipLines[x][y];
populateTable(tTable,tTableXdim,tTableYdim,timeFile);// call for above code.
printf("%s\n", tTable[0][0].str);
printf("%f\n", tTable[1][0].dVal);// I call these any they return wrong
If anyone could shine some light on this issue I'd appreciate it greatly.
Edit (was suggested that I post my TokenizeLine function):
void TokenizeLine(int x; int y; char currentLineStr[], Entry table[x][y], int yIndex, int x, int y)
{
char *tokPtr;
char *current;
int xIndex = 0;
current = currentLineStr;
tokPtr = mystrsep(&current, "|");
while(tokPtr != NULL)
{
if(IsDouble(tokPtr))
{
table[xIndex][yIndex].str = NULL;
table[xIndex][yIndex].dVal = atof(tokPtr);
}
else
{
table[xIndex][yIndex].str = malloc(strlen(tokPtr) + 1);
strcpy(table[xIndex][yIndex].str, tokPtr);
table[xIndex][yIndex].dVal = 0;
}
tokPtr = mystrsep(&current, "|")
xIndex++;
}
}
As requested the Entry definition.
typedef struct Entry
{
char *str;
double dVal;
} Entry;
The output that I get within the populateTable function is.
DWL_FaceMountTile
1.000000
Which is completely correct and the correctness holds true for all the entries when accessed within populateTable
The below is what I get when accessing the table outside of populateTable after its been called.
the str values of the table all appear to be correct, however the dVal are all set to zero somehow as shown below.
DWL_FacMountTile
0.000000

Hash Table - Sort Structure with qsort

Alright sorry for creating another question but the last one got overwhelmed and chaotic.
So I'm making a hash table which inserts words from a file (tokens) and after I have inserted them I need to sort them. The program template was given, the only functions that weren't complete were : insert_ht() , clear_ht() and compare. Even though I've done tons of search about qsort with compare, the program doesn't sort the frequencies (number of times each word was inserted) . I want em sorted from the highest to lowest.
Here is the code : "note that i shouldn't change any function except insert_ht() , clear_ht() and compare
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define HTABLE_SIZ 1001
#define MAX_LINE_SIZ 1024
/* Hash Table */
typedef struct node* link;
struct node { char *token; int freq; link next; };
link htable[HTABLE_SIZ] = { NULL }; /* Table of lists (#buckets) */
int size = 0; /* Size (number of elements) of hash table */
unsigned int hash (char *tok );
void insert_ht (char *data);
void clear_ht ( );
void print_ht ( );
void Process(FILE *fp);
int main(int argc, char *argv[])
{
int i;
FILE *fp;
printf("prin tin for \n");
for (i=1; i < argc; i++)
{
printf("prin tin fopen \n");
fp = fopen(argv[i],"r");
if (NULL == fp)
{
fprintf(stderr,"Problem opening file: %s\n",argv[i]);
continue;
}
printf("prin tin process \n");
Process(fp);
fclose(fp);
}
print_ht();
//clear_ht();
return 0;
}
void Process(FILE *fp)
{
const char *seperators = " ?!'\";,.:+-*&%(){}[]<>\\\t\n";
char line[MAX_LINE_SIZ];
char *s;
while((fgets(line,MAX_LINE_SIZ, fp)) != NULL)
{
for (s=strtok(line,seperators); s; s=strtok(NULL,seperators)){
printf("prin tin insert %s \n",s);
insert_ht(s);
}
}
}
/* Hash Function */
unsigned int hash(char *tok)
{
printf("bike stin hash \n");
unsigned int hv = 0;
while (*tok)
hv = (hv << 4) | toupper(*tok++);
printf("VGAINEIIIIIIIIIIIIII %d \n",hv);
return hv % HTABLE_SIZ;
}
void insert_ht(char *token)
{
printf("bike stin insert %s \n",token);
unsigned int hashval = hash(token);
struct node *new_list;
if (htable[hashval]==NULL){
printf("mesa stin prwti if %u %s \n",hashval,token);
//token = strdup(token);
new_list = malloc(sizeof(link));
new_list->token = strdup(token) ;
new_list->freq = 1;
new_list->next = htable[hashval];
htable[hashval] = new_list;
size++;
}else {
htable[hashval]->freq++;
}
printf("ta evale epitixws \n");
}
void clear_ht()
{
int i;
for(i=0; i<HTABLE_SIZ; i++) {
while(htable[i]->token!=NULL) {
htable[i]->token=NULL;
htable[i]->freq=NULL;
free(htable[i]);
}
}
}
int compare(const void *elem1, const void *elem2)
{
const struct node *p1 = elem1;
const struct node *p2 = elem2;
if (p1->freq > p2->freq)
return(+1);
else if (p1->freq < p2->freq)
return(-1);
else
return(0);
}
void print_ht()
{
int i, j=0;
link l, *vector = (link*) malloc(sizeof(link)*size);
for (i=0; i < HTABLE_SIZ; i++)
for (l=htable[i]; l; l=l->next)
vector[j++] = l;
qsort(vector,size,sizeof(link),compare);
for (i=0; i < size; i++)
printf("%-50s\t%7d\n",vector[i]->token,vector[i]->freq);
free(vector);
}
Ι found the solution. Apparently for some reason my compare function was wrong.
I still haven't figured out why but here is the correct one, hopefully someone else will find this post helpful!
int compare(const void *elem1, const void *elem2)
{
return (*(link*)elem2)->freq - (*(link*)elem1)->freq;
}

Structure issue using C

I'm trying to store strings into dynamical allocated memory. I'm able to break the strings down and store them within the members of the struct and print them perfectly within the function readFile, but when it comes to printing it in main, it's only printing the last scan and everything else is null. I'm thinking that maybe I'm not allocating the array of structures correctly. Here's my program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef _MSC_VER
#include <crtdbg.h> // needed to check for memory leaks (Windows only!)
#endif
#define MEM_ERROR printf("Not enough memory\n")
#define FLUSH while( getchar() != '\n' )
typedef struct
{
char id[5];
char *name;
int *sales;
int total;
int low;
int high;
}PERSON;
typedef struct
{
int worker;
int weeks;
PERSON *pAry;
}HEADER;
// Function Declaration
void valiFile(char nameIn[]);
FILE* openFile(char nameIn[]);
void getHeader(FILE* fpFile, HEADER *pHead);
PERSON* aloPerson(int workers);
void readFile(FILE* fpFile, HEADER *pHead);
char* aloName(HEADER *pHead, int strCount);
void repeat(char nameIn[]);
int main ( void )
{
// Local Declaration
FILE* fpFile;
char nameIn[25];
char *endPro = "end";
HEADER *pHead = (HEADER*)calloc(1, sizeof(HEADER));
// Statement
printf("Please select file to to open.\nsales or sales_2: ");
scanf("%s", nameIn);
FLUSH;
do
{
valiFile(nameIn);
fpFile = openFile(nameIn);
getHeader(fpFile, pHead);
readFile(fpFile, pHead);
//printf("%s\n", pHead->pAry[0].id);
//free(pHead);
repeat(nameIn);
}
return 0;
}// main
/* ========== valiFile ==========
========== */
void valiFile(char nameIn[])
{
// Local Declaration
char *file = "sales";
char *file2 = "sales_2";
int i;
int check = 0;
// Statement
do
{
for(i = 0; nameIn[i]; i++)
{
nameIn[i] = tolower(nameIn[i]);
}
if(strcmp(file, nameIn) != 0)
{
if(strcmp(file2, nameIn) != 0)
{
printf("\nPlease enter a valid file.\n");
printf("sales or sales_2: ");
scanf("%s", nameIn);
FLUSH;
}
else
check = 1;
}
else
check = 1;
}
while(check != 1)
;
return;
}// valiFile
/* ========== openFile ==========
========== */
FILE* openFile(char nameIn[])
{
// Local Declaration
FILE* fpFile;
char *strSale = "sales";
// Statement
if(strcmp(strSale, nameIn) == 0)
{
fpFile = fopen("sales.txt", "r");
if(fpFile == NULL)
{
printf("File didn't read correcty.\n");
exit(100);
}
}
else
{
fpFile = fopen("sales_2.txt", "r");
if(fpFile == NULL)
{
printf("File didn't read correcty.\n");
exit(100);
}
}
return fpFile;
}// openFile
/* ========================= getHeader ========================
============================================================*/
void getHeader(FILE* fpFile, HEADER *pHead)
{
// Local Declaration
int worker, salesWeek, i;
PERSON *list;
// Statement
fscanf(fpFile, "%d %d", &worker, &salesWeek);
list = aloPerson(worker);
HEADER header = {worker, salesWeek, list};
*pHead = header;
return;
}// getHeader
/* aloPerson
*/
PERSON* aloPerson(int worker)
{
// Local Declaration
PERSON *list;
// Statement
list =(PERSON*)calloc(worker, sizeof(PERSON));
if(list == NULL)
{
MEM_ERROR, exit(103);
}
return list;
}// aloPerson
/* readFile
*/
void readFile(FILE* fpFile, HEADER *pHead)
{
// Local Declaration
char temp[50];
int strCount = 0;
char *loc;
char *ptr;
int i;
// Statement
fscanf(fpFile, "%*d %*d");
for(i = 0; i < pHead->worker; i++)
{
while(fgets(temp, sizeof(temp), fpFile))
{
ptr = temp;
loc = strchr(temp, ' ');
strncpy(pHead->pAry[i].id, temp, (loc - ptr));
ptr += (loc - temp);
*ptr++;
loc = strchr(temp, ';');
strCount = (loc - ptr);
pHead->pAry[i].name = aloName(pHead, strCount);
strncpy(pHead->pAry[i].name, ptr, (loc - ptr));
ptr += (loc - ptr);
printf("%s\n", pHead->pAry[i].name);
}
}
return;
}// readFile
/* aloName
*/
char* aloName(HEADER *pHead, int strCount)
{
// Local Declaration
char *names;
// Statement;
names = malloc((strCount + 1)*sizeof(char));
return names;
}

Resources