Function int load(const char *filename, int ***ptr, enum save_format_t format) should load data from binary or text file (which name is saved under filename pointer) to matrix which is under ptr pointer to matrix. File extension depends on value of variable format: 0 or 1 (in function I showed there is only option with format=0, which is primarily for text files, because only this one makes trouble). Proper data in file looks for example as below:
10 20 30 40 50 60 70 -1
100 200 300 400 500 600 700 800 -1
For data exact like an example above, data should be loaded like this:
int A[] = {10, 20, 30, 40, 50, 60, 70, -1};
int B[] = {100, 200, 300, 400, 500, 600, 700, 800, -1};
int D[] = {A, B, C, NULL};
That means that every row has to end with '-1', (data has to be loaded to matrix with '-1'). Pointer to row after the last row should be equal to NULL.
If in any part off function allocation failed, function should return 4.
Tests carried out on file with extension ".bin" and with heap limit return this error:
Function should return 4, but it returned 0.
I use notation like for example **ptr because I'm not allowed to use square brackets.
Can someone help me how can I make my function return the right integer. My function is as it follows:
int load(const char *filename, int ***ptr, enum save_format_t format) {
if (filename == NULL || ptr == NULL || format != 0 && format != 1) {
return 1;
}
int val = 0;
int **temp = NULL;
FILE *fp, *pp;
if (format == 0) {
int i = 0, x = 0, h = 0, w = 0;
fp = fopen(filename, "r");
if (fp == NULL) {
return 2;
}
pp = fopen(filename, "r");
if (pp == NULL) {
fclose(fp);
return 2;
}
int val2 = 0;
while (1) {
if (fscanf(fp, "%d", &val2) != 1) {
if (i == 0 || val != -1) {
fclose(fp);
fclose(pp);
return 3;
}
break;
}
val = val2;
if (val == -1) {
h++;
}
i++;
}
if (i == h) {
fclose(fp);
fclose(pp);
return 3;
}
i = 0;
fseek(fp, 0, SEEK_SET);
temp = malloc(sizeof(temp) * (h + 1));
if (temp == NULL) {
fclose(fp);
fclose(pp);
return 4;
}
*(temp + h) = NULL;
for (i = 0; i < h; i++) {
val = 0, w = 0;
while (val != -1) {
if (fscanf(pp, "%d", &val) == EOF) {
break;
}
w++;
}
if (*(temp + i) != NULL) {
*(temp + i) = (int *)malloc(sizeof(int) * w);
if (*(temp + i) == NULL) {
for (int s = 0; s < i; s++) {
free(*(temp + s));
}
free(temp);
fclose(pp);
fclose(fp);
return 4;
}
} else {
fclose(fp);
fclose(pp);
free(temp);
return 0;
}
for (x = 0; x < w; x++) {
fscanf(fp, "%d", *(temp + i) + x);
}
}
fclose(fp);
fclose(pp);
}
*ptr = temp;
return 0;
}
There are multiple problems in your code:
if (i == h) seems incorrect: what if the file contains a single row with a -1 terminator, in other words an empty matrix?
temp = malloc(sizeof(temp) * (h + 1)); should be temp = malloc(sizeof(*temp) * (h + 1));
if (*(temp + i) != NULL) { read an uninitialized entry in the array allocated by malloc(). The test should be removed and you should always allocate the row.
Here is a modified version:
int load(const char *filename, int ***ptr, enum save_format_t format) {
if (filename == NULL || ptr == NULL || format != 0 && format != 1) {
return 1;
}
int **temp = NULL;
FILE *fp, *pp;
if (format == 0) {
int i = 0, x = 0, h = 0, w = 0, val = 0;
fp = fopen(filename, "r");
if (fp == NULL) {
return 2;
}
pp = fopen(filename, "r");
if (pp == NULL) {
fclose(fp);
return 2;
}
// determine the number of rows
val = 0;
while (fscanf(fp, "%d", &val) == 1) {
if (val == -1)
h++;
}
if (val != -1) {
// empty file or file does not end with -1
fclose(fp);
fclose(pp);
return 3;
}
temp = malloc(sizeof(*temp) * (h + 1));
if (temp == NULL) {
fclose(fp);
fclose(pp);
return 4;
}
fseek(fp, 0, SEEK_SET);
for (i = 0; i < h; i++) {
w = 0;
while (fscanf(pp, "%d", &val) == 1) {
w++;
if (val == -1)
break;
}
if (w == 0 || (*(temp + i) = malloc(sizeof(int) * w)) == NULL) {
while (i-- > 0) {
free(*(temp + i));
}
free(temp);
fclose(pp);
fclose(fp);
return 4;
}
for (x = 0; x < w; x++) {
fscanf(fp, "%d", *(temp + i) + x);
}
}
*(temp + h) = NULL;
fclose(fp);
fclose(pp);
}
*ptr = temp;
return 0;
}
Consider reading a string and parsing with strtol.
The memory allocations will return NULL when there is no RAM available.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
int load ( char const *filename, int ***ptr) {
if ( filename == NULL || ptr == NULL) {
return 1;
}
char entry[100] = "";
char *end = NULL;
int **temp = NULL;
int *temprow = NULL;
long int val = 0;
int rows = 0;
int cols = 0;
int problem = 0;
int result = 0;
FILE* fp = NULL;
fp = fopen ( filename, "r");
if ( fp == NULL) {
perror ( filename);
return 2;
}
while ( 1 == ( result = fscanf ( fp, "%99s", entry))) {
if ( -1 == val || ( 0 == rows && 0 == cols)) {
if ( -1 == val) {
++rows;
}
if ( NULL == ( temp = realloc ( *ptr, sizeof **ptr * ( rows + 2)))) {
fprintf ( stderr, "problem realloc *ptr\n");
problem = 4;
break;
}
*ptr = temp;
*( ( *ptr) + rows) = NULL;
*( ( *ptr) + rows + 1) = NULL;//sentinel
cols = 0;
}
errno = 0;
val = strtol ( entry, &end, 10);
if ( entry == end) {//nothing could be parsed to int
problem = 3;
break;
}
else if ( 0 != *end) {//extra characters after int
problem = 3;
break;
}
if ( ( errno == ERANGE && ( val == LONG_MAX || val == LONG_MIN))
|| ( errno != 0 && val == 0)) {// parsing error from strtol
perror ( "input error");
problem = 3;
break;
}
if ( val > INT_MAX || val < INT_MIN) {
problem = 3;
break;
}
if ( NULL == ( temprow = realloc ( *( ( *ptr) + rows), sizeof ***ptr * ( cols + 2)))) {
fprintf ( stderr, "problem realloc *( (*ptr) + row)\n");
problem = 4;
break;
}
*( ( *ptr) + rows) = temprow;
++cols;
*( *( ( *ptr) + rows)) = cols;//save cols in index 0
*( *( ( *ptr) + rows) + cols) = val;
}
fclose(fp);
if ( 0 == result) {
problem = 3;
}
return problem;
}
int main ( void) {
char const *filename = "ints.txt";
int **array = NULL;
int row = 0;
int each = 0;
load ( filename, &array);
row = 0;
while ( array && ( *(array + row))) {
each = 0;
while ( each <= *( *(array + row))) {
printf ( "%d\n", *( *(array + row) + each));
++each;
}
++row;
}
row = 0;
while ( array && ( *(array + row))) {
free ( *(array + row));
++row;
}
free ( array);
return 0;
}
Related
I am writing a program, that will open csv file and save data to 3D array.
Most of code works pretty good, but I have a problem with assiging records to 2D array.
Here is a code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILE_MODE "r"
/*
Explode string with given token and assign result to list variable
*/
int explode(const char *src, const char *tokens, char ***list, size_t *len)
{
if(src == NULL || list == NULL || len == NULL) {
return 0;
}
char *str, *copy, **_list = NULL, **tmp;
*list = NULL;
*len = 0;
copy = strdup(src);
if(copy == NULL)
return 1;
str = strtok(copy, tokens);
if(str == NULL) {
goto free_and_exit;
}
_list = realloc(NULL, sizeof *_list);
if(_list == NULL) {
goto free_and_exit;
}
_list[*len] = strdup(str);
if(_list[*len] == NULL)
goto free_and_exit;
(*len)++;
while((str = strtok(NULL, tokens)))
{
tmp = realloc(_list, (sizeof *_list) * (*len + 1));
if(tmp == NULL)
goto free_and_exit;
_list = tmp;
_list[*len] = strdup(str);
if(_list[*len] == NULL)
goto free_and_exit;
(*len)++;
}
free_and_exit:
*list = _list;
free(copy);
return 2;
}
/*
Exploding lines in CSV file
*/
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE *stream;
char fileName[256], table[256], line[256],
**list, **columns, **data;
size_t length;
printf("Witaj uzytkowniku! Podaj nazwe pliku z rozszerzeniem .csv. \n");
scanf("%s", fileName);
explode(fileName, ".", &list, &length);
strcpy(table, list[0]);
stream = fopen("file.csv", FILE_MODE); // not to write path every single time
if (stream == NULL) {
printf("Nie moge otworzyc pliku %s do odczytu!\n", fileName);
exit(1);
}
fgets(line, sizeof line, stream);
explode(line, ";", &columns, &length);
int recordNumber = 0
,columnNumber = 0;
while (fgets(line, sizeof line, stream))
{
char* tmp = strdup(line);
if (getfield(tmp, recordNumber) != NULL) {
columnNumber++;
}
recordNumber++;
free(tmp);
}
fseek(stream, 0, SEEK_SET); // Go to beginning of file
fgets(line, 1024, stream);
int i = 0 // Number of records
,h = 0; // number of columns
char **records[recordNumber][columnNumber];
length = 0;
char *tmp[recordNumber];
// Here I get number of lines and columns in csv file to make 3D array??
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
memcpy(records[i][h], data[h], sizeof(data[h]));
}
i++;
}
for (i = 0; i < recordNumber; i++)
{
for (h = 0; h < columnNumber; h++)
{
printf("%s ", records[i][h][0]);
}
printf("\n");
}
fclose(stream);
return EXIT_SUCCESS;
}
Problem starts, when I try do a loop, that assign data to array:
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
memcpy(records[i][h], data[h], sizeof(data[h]));
}
i++;
}
I tried to use memcpy and strcpy, but none works correctly - I am pretty sure.
When code goes to these lines, there is an error: segmentation fault (core dumping).
All i want to achieve is to fill this array with data from csv file and print it.
Thanks for your help! :)
EDIT:
explode function is not mine. Probably, I found it somewhere on stackoverflow.
When, it comes to the code, after little change, it works
char records[recordNumber][columnNumber][1024];
length = 0;
char *tmp[recordNumber];
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
strcpy(records[i][h], data[h]);
}
i++;
}
Read each line of the file with fgets. strpbrk can be used to find the delimiters. Two pointers can be used to get the number of characters between the delimiters. Then allocate memory and use memcpy to copy the field to the allocated memory.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char ***strpdlm ( char *pdelim, int skip);
char ***freedlm ( char ***ppp);
int main()
{
char ***expld = NULL;
int line = 0;
int field = 0;
//last argument of 1 is skip consecutive delimiters. 0 do not skip
expld = strpdlm ( ";\n", 1);// delimiters semicolon and newline
//print each extracted string
line = 0;
if ( expld) {//not null
while ( expld[line]) {//not null
field = 0;
printf ( "\nfields for line %d\n", line);
while ( expld[line][field]) {//not null
printf ( "expld[%d][%d] %s\n", line, field, expld[line][field]);
field++;
}
line++;
}
}
//free memory and set NULL
expld = freedlm ( expld);
return 0;
}
char ***freedlm ( char ***ppp) {
size_t each = 0;
size_t item = 0;
if ( ppp) {
while ( ppp[each]) {
item = 0;
while ( ppp[each][item]) {
free ( ppp[each][item]);
item++;
}
free ( ppp[each]);
each++;
}
free ( ppp);
}
return NULL;
}
char ***strpdlm ( char *pdelim, int skip) {
char ***xpld = NULL;
char ***temprecord = NULL;
char **tempfield = NULL;
char *pnt = NULL;
char *cur = NULL;
char line[1024] = "";
int span = 0;
int len = 0;
int record = 0;
int field = 0;
FILE *pf = NULL;
if ( ( pf = fopen ( "file.csv", "r")) == NULL) {
perror ( "could not open \"file.csv\"");
return NULL;
}
if ( pdelim) {
while ( fgets ( line, sizeof line, pf)) {
//make sure each line ends with \n
len = strcspn ( line, "\n");
if ( len + 1 < sizeof line) {
line[len] = '\n';
line[len + 1] = '\0';
}
//allocate record + 2 pointers
if ( ( temprecord = realloc ( xpld, ( record + 2) * sizeof ( *xpld))) == NULL) {
fprintf ( stderr, "problem realloc records\n");
fclose ( pf);
return xpld;
}
xpld = temprecord;
xpld[record] = NULL;
field = 0;
cur = line;//cur points to line
while ( ( pnt = strpbrk ( cur, pdelim))) {
if ( pnt != cur || !skip) {
if ( ( tempfield = realloc ( xpld[record], ( field + 2) * sizeof ( **xpld))) == NULL) {
fprintf ( stderr, "problem realloc fields\n");
fclose ( pf);
return xpld;
}
xpld[record] = tempfield;
xpld[record][field] = NULL;
if ( pnt) {
span = pnt - cur;
}
else {
span = strlen ( cur);
}
if ( ( xpld[record][field] = malloc ( span + 1)) == NULL) {
fprintf ( stderr, "problem malloc\n");
fclose ( pf);
return xpld;
}
memcpy ( xpld[record][field], cur, span);
xpld[record][field][span] = '\0';
field++;
xpld[record][field] = NULL;//sentinel NULL
}
cur = pnt + 1;//set cur to point to next field
}
record++;
xpld[record] = NULL;//sentinel NULL
}
}
fclose ( pf);
return xpld;
}
In the function RenameSubs() when I try debugging I get segmentation fault at this line of code
subsdir[i] = (char*)malloc((GetStringSize(moviesdir[i]) + 1 + 4) * sizeof(char));
I don't understand why — can you explain?
int main()
{
int number;
char *mainDirectory = NULL,**names = NULL;
printf("Give the movies directory: ");
mainDirectory = ReadMainDirectory();
if(GetFiles(&mainDirectory,&names,&number) != 0)
{
RenameSubs(number,mainDirectory,names);
system("PAUSE");
return 1;
}
system("PAUSE");
return 0;
}
char* ReadMainDirectory()
{
char *dir,c;
int size = 1;
dir = (char*)malloc(size+1);
dir[size-1] = '\0';
while((c = getchar()) != '\n')
{
dir[size-1] = c;
size++;
dir = (char*)realloc(dir,size+1);
dir[size-1] = '\0';
}
return dir;
}
int GetFiles(char **dir,char ***names,int *number)
{
struct dirent *dp;
DIR *fd;
if ((fd = opendir(*dir)) == NULL)
{
printf("Can't open directory %s!\n",*dir);
return 0;
}
*number = 0;
*names = (char**)malloc(((*number)+1) * sizeof(char*));
while ((dp = readdir(fd)) != NULL)
{
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
{
continue;
}
(*names)[*number] = strdup(dp->d_name);
(*number)++;
*names = (char**)realloc(*names,((*number)+1) * sizeof(char*));
}
closedir(fd);
return 1;
}
int GetStringSize(char *string)
{
int size = 0;
while(string[size] != '\0')
{
size++;
}
return size;
}
int StringEndsWith(char* string,char* extension)
{
int size;
char *strextension = NULL;
size = GetStringSize(string);
strextension = (char*)malloc(5 * sizeof(char));
strextension[0] = string[size-4];
strextension[1] = string[size-3];
strextension[2] = string[size-2];
strextension[3] = string[size-1];
strextension[4] = '\0';
if(strcmp(strextension,extension) == 0)
{
return 1;
}
return 0;
}
void RenameSubs(int number,char* mainDir,char** filenames)
{
int i,mainDirSize,movieDirSize[number],moviesdirnumber,subsdirnumber,j,y;
char **moviesdir = NULL,**subsdir = NULL,**subsdest = NULL,**moviesdirfilenames = NULL,**subsdirfilenames = NULL,*moviesname = NULL;
moviesdir = (char**)malloc(number * sizeof(char*));
mainDirSize = GetStringSize(mainDir);
for(i=0;i<number;i++)
{
movieDirSize[i] = mainDirSize + 1 + GetStringSize(filenames[i]);
moviesdir[i] = (char*)malloc((movieDirSize[i]+1) * sizeof(char));
strcpy(moviesdir[i],mainDir);
strcat(moviesdir[i],"\\");
strcat(moviesdir[i],filenames[i]);
GetFiles(&moviesdir[i],&moviesdirfilenames,&moviesdirnumber);
subsdir[i] = (char*)malloc((GetStringSize(moviesdir[i]) + 1 + 4) * sizeof(char));
strcpy(subsdir[i],moviesdir[i]);
strcat(subsdir[i],"\\");
strcat(subsdir[i],"Subs");
GetFiles(&subsdir[i],&subsdirfilenames,&subsdirnumber);
subsdest[i] = (char*)malloc((GetStringSize(subsdir[i]) + GetStringSize(subsdirfilenames[0]) + 1) * sizeof(char));
strcpy(subsdest[i],subsdir[i]);
strcat(subsdest[i],"\\");
strcat(subsdest[i],subsdirfilenames[0]);
for(j=0;j<moviesdirnumber;j++)
{
if(StringEndsWith(moviesdirfilenames[j],".mkv") || StringEndsWith(moviesdirfilenames[j],".mp4") || StringEndsWith(moviesdirfilenames[j],".avi"))
{
moviesname = (char*)malloc((GetStringSize(moviesdirfilenames[j]) - 4 + 1) * sizeof(char));
for(y=0;y<(GetStringSize(moviesdirfilenames[j]) - 4);y++)
{
moviesname[y] = moviesdirfilenames[j][y];
}
moviesname[y] = '\0';
break;
}
}
}
}
You are using array of pointers without initializing it first . initialize it.
In loop
subsdir[i] = malloc((GetStringSize(moviesdir[i]) + 1 + 4) * sizeof(char));
This is the second step . First u need to initialize
subsdir = malloc (sizeof(char*) * number);
which performs a lexicographical comparison of the two blocks. I test my
program using various types of blocks.
The tests for characters are all goods.
The First test isn't Ok because the good answer is 0 but now is 1.
The second test is ok (1 == 1)
The third test is ok (-1 == -1)
Help me for the first test.
Thanks
This is my codes :
int compare_ints(const void* v1, const void* v2) {
int *a = (int*)v1;
int *b = (int*)v2;
if (*a == *b) return 0;
else if (*a > *b) return 1;
else return -1;
}
int compare_gen(const void *block1, const void *block2,
size_t elem_size, size_t block1size, size_t block2size,
int (*compare_it)(const void*, const void*)) {
int i = 0;
int result = -2;
if ( elem_size == sizeof(char) )
{
while ( i < block1size && i < block2size)
{
result = (*compare_it)((&((char*)block1)[i]),(&((char*)block2)[i]));
if ( result == 0)
{
i++;
}
else if ( result == -1 || result == 1 )
{
return result;
}
}
if ( result == 0 )
{
if (i == block1size && i == block2size)
{
return result;
}
else if (i != block1size && i == block2size)
{
result = -1;
return result;
}
else
{
result = 1;
return result;
}
}
}
else if (elem_size == sizeof(int))
{
while ( i < block1size && i < block2size)
{
result = (*compare_it)((&((int*)block1)[i]),(&((int*)block2)[i]));
if ( result == 0)
{
i++;
}
else if ( result == -1 || result == 1 )
{
return result;
}
}
if ( result == 0 )
{
if (i == block1size && i == block2size)
{
return result;
}
else if (i != block1size && i == block2size)
{
result = -1;
return result;
}
else
{
result = 1;
return result;
}
}
}
return result;
}
int main()
{
int array1 [10] = {10};
int array2 [10] = {10};
int array3 [10] = {10};
int array4 [9] = {10};
int i;
for (i = 0; i < 10; i++) {
array1[i] = 10;
array2[i] = 10;
array3[i] = 10;
if (i < 9) array4[i] = 10;
}
array3[5] = 9;
// First test
int result = compare_gen(array1, array2, sizeof(int), sizeof(array1), sizeof(array2), (&compare_ints));
printf("1 --> %d\n",result);
// Second test
result = compare_gen(array1, array3, sizeof(int), sizeof(array1), sizeof(array3), (&compare_ints));
printf("2 --> %d\n",result);
// third test
result = compare_gen(array1, array4, sizeof(int), sizeof(array1), sizeof(array4), (&compare_ints));
printf("3 --> %d\n",result);
return 0;
}
Indexing outside range
In the while(), wherever blockXsize is used, should be replaced with blockXsize/elem_size. Once this is done,i will index over its proper range. Further, the if ( elem_size == ... will the not be needed. Other simplifications are possible.
if (1)
{
while ( i < block1size/elem_size && i < block2size/elem_size)
{
//result = (*compare_it)((&((int*)block1)[i]),(&((int*)block2)[i]));
result = (*compare_it)(
(&((char*)block1)[i*elem_size]),
(&((char*)block2)[i*elem_size]));
if ( result == 0)
{
i++;
}
else if ( result == -1 || result == 1 )
{
return result;
}
}
if ( result == 0 )
{
if (i == block1size/elem_size && i == block2size/elem_size)
{
return result;
}
else if (i != block1size/elem_size && i == block2size/elem_size)
{
result = -1;
return result;
}
else
{
result = 1;
return result;
}
}
typedef struct {
int *info;
} row;
struct {
row* head;
int len;
int size;
} list;
int main{
list.len = 0;
list.size = 1;
list.head = malloc(list.size * sizeof(row));
//...... some other code that calls addRow (list.len) times
for (i = list.len - 1; i > 0; i--) {
free(list.head[i].info);/*****HERE**********/
}
free(list.head);
}
void addRow(int* data) {
int i;
if (list.len == list.size) {
row *temp = malloc(sizeof(row) * list.size * 2);
if (temp == NULL) {
fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
return;
}
for (i = 0; i < list.len; i++) {
temp[i] = list.head[i];
}
free(list.head);
list.head = temp;
}
list.head[list.len].info = malloc(sizeof(int) * numCols);
for (i = 0; i < numCols; i++) {
list.head[list.len].info[i] = data[i];
}
list.len++;
}
This is the code that I used to addRow is were I malloc all the data. and I don't see why I'm getting a double free/ corruption error. At the area I marked HERE, I believe I am malloc-ing for all instances of info in the row struct, These line are the only ones doing malloc/free.
I just want to get into the habit free-ing properly when terminating the program.
FULL PROGRAM:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
typedef struct {
int *info;
} row;
struct {
row* head;
int len;
int size;
} list;
static int sortCol, numCols;
int qSortCompare(const void*, const void*);
void printList();
int processInput();
void nullify(char*, int);
int main(int n, char **args) {
sortCol = 1;
numCols = 0;
if (n > 1 && args[1][0] == '-' && args[1][1] == 'c') {
sortCol = atoi(args[2]);
}
list.len = 0;
list.size = 1;
list.head = malloc(list.size * sizeof(row));
processInput();
if (sortCol < 1 || sortCol > numCols) {
fprintf(stderr, "Error (enter): (Line ##) Invalid column to sort.\n");
return 1;
}
printList();
qsort(list.head, list.len, sizeof(row), &qSortCompare);
printf("\n");
printList();
int i;
printf("add1:%p\nadd2:%p\n", list.head[0].info, list.head[1].info);
for (i = 0; i < list.len; i++) {
free(list.head[i].info);
}
free(list.head);
return 0;
}
void nullify(char* str, int n) {
int i;
for (i = 0; i < n; i++)
str[i] = '\0';
}
int parseInt(char *str, int index) {
int num = -1;
sscanf(str + index, "%d", &num);
return num;
}
void addRow(int* data) {
int i;
if (list.len == list.size) {
row *temp = malloc(sizeof(row) * list.size * 2);
if (temp == NULL) {
fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
return;
}
for (i = 0; i < list.len; i++) {
temp[i] = list.head[i];
}
free(list.head);
list.head = temp;
}
list.head[list.len].info = malloc(sizeof(int) * numCols);
if (list.head[list.len].info == NULL) {
fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
return;
}
for (i = 0; i < numCols; i++) {
list.head[list.len].info[i] = data[i];
}
list.len++;
}
int processInput() {
int i, maxChars = 200, totalN = 0;
int *nums, curNumIndex = 0, onNum, curNum;
numCols = maxChars / 2;
nums = (int*) (malloc(sizeof(int) * numCols));
char str[maxChars], ch;
for (i = 0; i < numCols; i++) {
nums[i] = -1;
}
while (!feof(stdin)) {
nullify(str, maxChars);
fgets(str, maxChars, stdin);
onNum = isdigit(str[0]);
curNumIndex = 0;
for (i = 0; i < maxChars; i++) {
ch = str[i];
if ((!isspace(ch)) && (!isdigit(ch)) && (ch != '\0')) {
fprintf(stderr, "Error 1: (Line ##) Invalid char in input.\n");
//return 0;
}
if (isspace(ch) && onNum) {
curNum = parseInt(str, curNumIndex);
curNumIndex = i;
nums[totalN % numCols] = curNum;
totalN++;
if (totalN % numCols == 0)
addRow(nums);
} else {
onNum = isdigit(str[i]);
}
if (ch == '\n' || ch == '\0')
break;
}
if (numCols > totalN) {
if (totalN > 0) {
numCols = totalN;
addRow(nums);
} else {
fprintf(stderr,
"Error (enter): (Line ##) Invalid first line of input.\n");
}
}
if (ch != '\n' && ch != '\0') {
fprintf(stderr,
"Error (enter): (Line ##) A row from input too long.\n");
//return 0;
}
}
return 1;
}
int qSortCompare(const void *c1, const void *c2) {
row *t1, *t2;
t1 = (row*)c1;
t2 = (row*)c2;
return t1->info[sortCol - 1] - t2->info[sortCol - 1];
}
void printList() {
int i, j;
for (i = 0; i < list.len; i++) {
for (j = 0; j < numCols; j++) {
printf("%10d ", list.head[i].info[j]);
}
printf("\n");
}
}
Program needs a EOF terminated input of integer numbers. Specifically with the same number of integers before the newline.
UPDATE: I used gdb to analysis the free part i it only fails on the second iteration, using for(i = 0; i < list.len; i++) and for(i = list.len - 1; i > 0 ; i--)
Another thing is that I don't see the update to list.size (it should be updated when resizing head)
"I just want to get into the habit free-ing properly when terminating the program."
The correct way to handle things like this is to free a non-NULL pointer and then set the pointer to NULL.
For example:
int* x = malloc (sizeof (int));
if (x != NULL) {
free (x);
x = NULL;
}
/* Misc. Code ... */
/* Now for whatever reason, you want to free x again */
/* This branch is never triggered, because you were smart enough to set x to NULL
* when you freed it the first time...
*/
if (x != NULL) {
free (x);
x = NULL;
}
filenamelists is a struct with two file pointers. merge mergesorts these two fileptrs. I'm getting a segfault on the while(fscanf(filenamelist[0].file1, "%d", &chd) != EOF). I think its because I'm not implementing pthread correctly. Ive been trying to debug forever so any help would be appreciated. tempf is a file ptr to the mergesorted arrays. It is rewinded in the merge function itself.
for(i=0; i<size; i++)
{
if(argc==1)
{
char* tedious2 = (char*) malloc((strlen(argv[i+1]+7))*sizeof(char));
strcpy(tedious2,argv[i+1]);
filenamelist[i].file1 = fopen(strcat(tedious2,".sorted"),"r");
filenamelist[i].file2 = NULL;
filenamelist[i].alone = 1;
free(tedious2);
break;
}
else if(size-1 ==i && size%2 != 0)
{
char* tedious1 = (char*) malloc((strlen(argv[i+1]+7))*sizeof(char));
strcpy(tedious1,argv[i+1]);
filenamelist[i].file1 = fopen(strcat(tedious1,".sorted"),"r");
filenamelist[i].file2 = NULL;
filenamelist[i].alone = 1;
free(tedious1);
}
else
{
char* tedious3 = (char*) malloc((strlen(argv[i+1]+7))*sizeof(char));
strcpy(tedious3,argv[i+1]);
char* tedious4 = (char*) malloc((strlen(argv[i+2]+7))*sizeof(char));
strcpy(tedious4,argv[i+2]);
filenamelist[i].file1 = fopen(strcat(tedious3,".sorted"),"r");
filenamelist[i].file2 = fopen(strcat(tedious4,".sorted"),"r");
filenamelist[i].alone = 0;
free(tedious3);
free(tedious4);
}
}
// pthread_t* threadid2;
// threadid2 = (pthread_t*) malloc(sizeof(pthread_t)*(2*argc));
while(size>=0)
{
i = 0;
pthread_t* threadid2;
threadid2 = (pthread_t*) malloc(sizeof(pthread_t)*size);
for ( ; i<size;i++ )
{
pthread_create(&threadid2[i], NULL, merge, &filenamelist[i]);
}
i = 0;
for ( ; i<size; i++)
{
pthread_join(threadid2[i], tempf);
if (i%2 == 0)
{
filenamelist[i/2].file1 = tempf;
}
else
{
filenamelist[i/2].file2 = tempf;
}
}
zit=0;
truth = 0;
while(zit<z)
{
if(inputFiles[zit] == tempf)
truth = 1;
zit++;
}
if(truth != 1)
{
inputFiles[z] = tempf;
z++;
}
if(size==1)
size = 0;
else if (size % 2 == 0)
size = size/2;
else
size = (size/2)+1;
free(threadid2);
}
int chd = 0;
// if(0!=feof(tempf))
// rewind(tempf);
//rewind(filenamelist[0]->file1);
int finish = 0;
//printf("file 1:%p",tempf);
while(fscanf(filenamelist[0].file1, "%d", &chd) != EOF)
finish++;
rewind(filenamelist[0].file1);
int* finarr = (int*) malloc(finish*sizeof(int));
int xx =0;
for(;fscanf(filenamelist[0].file1, "%d", &chd) != EOF; xx++)
finarr[xx] = chd;
tempf is declared at start of func as FILE* tempf;
char* tedious2 = (char*) malloc((strlen(argv[i+1]+7))*sizeof(char));
Make that:
char *tedious2 = malloc( strlen(argv[i+1]) + strlen(".sorted") + 1 );