I made some research but nothing was really concerning my problem...
I'm actually trying to code LZW compression for school, and I need a function to check if an element is in my dictionnary.
However, when I'm calling this function, it tries to access to the 64th element in my dictionnary, but it has desapeared !! I checked it before the function calling, it was here !! And the worse is that I can call this element in the previous callings of the function.
Could you help me please ?
The function :
int is_in_dictionnary(dico * p_pRoot, char * p_string){
int i = 0, j = 0;
char a[1024] = { 0 }, b[1024] = { 0 };
//strcpy(b, p_pRoot->m_dico[64].m_info);
for (i = 0; i < p_pRoot->m_index; i++){
printf("dico %s\n", p_pRoot->m_dico[i].m_info);
strcpy(a, p_string);
strcpy(b, p_pRoot->m_dico[i].m_info);
j = strcmp(a, b);
if (j == 0)
return i;
}
return -1;
}
The console, we are herer abble to see that the function previously called the 64th element "#", whithout any problem
The error on visual studio
Some people Asked me to add the code part where it's not functionning :
void lzw_compress(dico *p_pRoot, char * path)
{
FILE *pFile = NULL, *pCompFile = NULL;
int len_c = 0, size_tamp = 0, i = 0, masked_tamp = 0, tamp_to_write = 0, index_tamp = 0, a;
unsigned char char_tamp = 0, cAndTamp[1024] = { 0 }, tampon[1024] = { 0 }, c = '\0', temp[2] = { 0 };
char test[128] = { 0 };
pFile = fopen(path, "r+");
if (!pFile)
{
printf("problem while opening file to compress");
return;
}
size_t len = strlen(path); //creation of the output file name : paht+ ".lzw"
unsigned char *compress_name = malloc(len + 4 + 1);
strcpy(compress_name, path);
compress_name[len] = '.';
compress_name[len + 1] = 'l';
compress_name[len + 2] = 'z';
compress_name[len + 3] = 'h';
compress_name[len + 4] = '\0';
pCompFile = fopen(compress_name, "w"); //creation of the output file
free(compress_name);
while (1)
{
if (feof(pFile))
break;
c = freadByte(pFile);
for (i = 0; i < 1024; i++)
cAndTamp[i] = 0;
temp[0] = c;
strcat(cAndTamp, tampon);
strcat(cAndTamp, temp);
strcpy(test, p_pRoot->m_dico[64].m_info);
a = 0;
if (is_in_dictionnary(p_pRoot, cAndTamp) > -1)
{
strcpy(tampon, cAndTamp);
a = 0;
}
else
{
if (is_in_dictionnary(p_pRoot, tampon) < 256) //write the character in the file
{
char_tamp = tampon[0];
fwrite(&char_tamp, sizeof(char), 1, pCompFile);
a = 0;
}
else
{
a = 0;
index_tamp = is_in_dictionnary(p_pRoot, tampon);
a = 0;
for (i = 0; i < p_pRoot->m_size; i++)
{
mask = 1 << i;
masked_tamp = index_tamp & mask;
tamp_to_write = masked_tamp >> i;
fwriteBit(tamp_to_write, pCompFile);
flush(pCompFile);
}
}
strcpy(test, p_pRoot->m_dico[64].m_info); //HERE IT'S OK
add_dictionnary(p_pRoot, cAndTamp, size_tamp + 1); //add the string tamp + read byte in the dictionnay
strcpy(test, p_pRoot->m_dico[64].m_info); //HERE IT IS NOT OK
strcpy(tampon, temp);
}
strcpy(test, p_pRoot->m_dico[64].m_info);
size_tamp = is_in_dictionnary(p_pRoot, tampon);
}
if (tampon < 256) //write the character in the file
{
char_tamp = (char)tampon;
fwrite(&char_tamp, sizeof(char), 1, pCompFile);
}
else
{
index_tamp = is_in_dictionnary(p_pRoot, tampon);
for (i = 0; i < p_pRoot->m_size; i++)
{
mask = 1 << i;
masked_tamp = index_tamp & mask;
tamp_to_write = masked_tamp >> i;
fwriteBit(tamp_to_write, pCompFile);
flush(pCompFile);
}
}
fclose(pFile);
fclose(pCompFile);
}
The fucnction that where I think there is a problem
void add_dictionnary(dico * p_pRoot, char * p_string, int p_stringSize)
{
p_pRoot->m_index++;
if (p_pRoot->m_index == pow(2, p_pRoot->m_size))
realloc_dictionnary(p_pRoot);
p_pRoot->m_dico[p_pRoot->m_index].m_info = (char*)calloc(p_stringSize, sizeof(char));
strcpy(p_pRoot->m_dico[p_pRoot->m_index].m_info, p_string);
}
Another thank you guys !
I showed again the program to my teacher and he found the problem !
The problem is that i never use malloc and rarely use realloc so here was the problem :
void realloc_dictionnary(dico * p_pRoot)
{
int real = p_pRoot->m_size + 1;
int size = pow(2, real);
printf("index %d, previous pow %d, new power %d, size %d\n", p_pRoot->m_index, p_pRoot->m_size, real, size);
p_pRoot->m_dico = (code*) realloc(p_pRoot->m_dico, size);
p_pRoot->m_size = real;
}
size in a number of bits, ...
So the correction is : size * sizeof(code)!
void realloc_dictionnary(dico * p_pRoot)
{
int real = p_pRoot->m_size + 1;
int size = pow(2, real);
printf("index %d, previous pow %d, new power %d, size %d\n", p_pRoot->m_index, p_pRoot->m_size, real, size);
p_pRoot->m_dico = (code*) realloc(p_pRoot->m_dico, size * sizeof(code));
p_pRoot->m_size = real;
}
I would like to first of all say sorry because of this so little errror and also a big thanks for your great patience !
Related
I could use some help with my program,
I wrote a program that is counting the number of anagrams in a sentence, for which I am using a malloc() function, you can see in my code **ArrPtr=malloc.
I use this to count the anagrams, after finishing it I want to continue to my second part of the program and I wish to free the memory with free(arrPtr);
and the program crashes (It didn't crash when I did not use the free option).
Here's my code,
void main()
{
char str[1001] = { 0 };
char temp[1001] = { 0 }, temp2;
char strB[1001] = { 0 };
int printf_i, counter, i, q, flag, j = 1, r = 0, m = 1, length = 0, root = 0, m1 = 0;
int max_analogy = 0, counter2 = 0, O, sum, sum2;
char **arrPtr;
int k = 0;
int **matrix;
printf("Please enter the sentence, and then press Enter:\n");
gets(str);
//bubble sort
strcpy_s(strB, 1001, str);
for (i = 0; i < strlen(strB); i = q + 2)
{
do
{
flag = 0;
for (q = i; strB[q + 1] != 32 && strB[q + 1] != 0; q++)
{
if (strB[q] > strB[q + 1])
{
// Swap
temp2 = strB[q];
strB[q] = strB[q + 1];
strB[q + 1] = temp2;
flag = 1;
}
}
} while (flag != 0);
}
counter = 1;
length = strlen(strB);
for (i = 0; strB[i] != 0; i++)
{
if (strB[i] == 32)
{
strB[i] = 0;
counter++;
}
}
arrPtr = (char*)malloc(sizeof(char)*counter);
arrPtr[0] = strB;
q = 1;
for (i = 0; i < length - 1; i++)
{
if (strB[i] == 0)
{
arrPtr[q] = &strB[i + 1];
q++;
}
}
counter2 = 0;
for (i = 0; i < counter; i++)
{
for (q = i + 1; q < counter; q++)
{
if (arrPtr[q] == 0 || arrPtr[i] == 0)
continue;
if (!strcmp(arrPtr[q], arrPtr[i]))
{
counter2++;
arrPtr[q] = 0;
}
}
if (max_analogy < counter2)
max_analogy = counter2;
counter2 = 0;
}
printf("The maximum number of anagram words in this sentence is %d.\n", max_analogy);
free(arrPtr);
}
arrPtr = (char*)malloc(sizeof(char)*counter);
is wrong fo many reason:
arrPtr is (char **).
cast using a C compiler is useless and dangerous.
you must allocate sizeof(char *)
reason 3 is the real reason of you problem: you are allocating counter bytes while you write counter*sizeof(char *) (most probably counter*8), so you are writing out of bounds of allocated memory corrupting malloc memory pool.
You can fix it using
arrPtr = malloc(sizeof(char *)*counter);
So this program crashes and tells me "Aborted (core dumped)" but only when my decleration of "GENERATIONS" is greater than 6... I know its a pain that I've uploaded the whole code but I really cant figure out where it is other than it's after the return from "fibonacci_quasicrystal_generator(GENERATIONS, crystal);", as the printf statement just after gets printed, then the message appears. Code below:
#define GENERATIONS 5
#define OUTFILE "frequencies.txt"
#define GNUPLOT_EXE "gnuplot"
#define GNUPLOT_SCRIPT "frequencyplot.script"
static void fibonacci_quasicrystal_generator(int generations, char * chain);
static int plot();
int main()
{
double k = 1.0, m_a = 100.0, m_b = 1.0, m = 0.0;
char * crystal = malloc(2);
//strcopy(crystal, "A"); //gsl_vector * y_vector = gsl_vector_calloc(CHAIN_LENGTH);
fibonacci_quasicrystal_generator(GENERATIONS, crystal);
if (crystal == NULL){
printf("Crystal write failed.");
exit(0);
}
int chain_length = strlen(crystal);
printf("%i member Crystal generated, after %i generations.\n", chain_length, GENERATIONS);
gsl_matrix * a_matrix = gsl_matrix_calloc(chain_length, chain_length);
gsl_matrix * b_matrix = gsl_matrix_calloc(chain_length, chain_length);
gsl_matrix_set_identity(b_matrix);
gsl_vector * eigenvalues_vector = gsl_vector_calloc(chain_length);
for (int i = 0; i < chain_length; ++i){
if (crystal[i] == 'A'){
m = m_a;
} else {
m = m_b;
}
for (int j = 0; j < chain_length; ++j){
if ((i == j) && (i != 0 && i != chain_length)){
gsl_matrix_set(a_matrix, i, j,(2*k)/m);
}
else if (i == j-1){
gsl_matrix_set(a_matrix, i, j,(-1)*(k/m));
}
else if (i == j+1){
gsl_matrix_set(a_matrix, i ,j, (-1)*(k/m));
}
}
}
gsl_eigen_gensymm_workspace * workspace = gsl_eigen_gensymm_alloc(chain_length);
gsl_eigen_gensymm(a_matrix, b_matrix, eigenvalues_vector, workspace);
gsl_eigen_gensymm_free(workspace);
free(crystal);
gsl_matrix_free(a_matrix);
gsl_matrix_free(b_matrix);
gsl_sort_vector(eigenvalues_vector);
FILE * outfile = fopen(OUTFILE, "w");
for (int i = 0; i < chain_length; ++i){
fprintf(outfile, "%e \t%i \r\n", pow(gsl_vector_get(eigenvalues_vector, i),2), i);
}
fclose(outfile);
gsl_vector_free(eigenvalues_vector);
plot();
return 0;
}
static void fibonacci_quasicrystal_generator(int generations, char * chain){
printf("generating fibonacci quasicrystal...\n");
int i;
i = 0;
char * chain_1 = malloc(2), * chain_2 = malloc(2), * tmp = malloc(2);
strcpy(chain_1, "B");
strcpy(chain_2, "A");
size_t chain_1_size = strlen(chain_1) + 1, chain_2_size = strlen(chain_2) + 1;
if (generations == 1){
chain = realloc(chain, chain_1_size);
snprintf(chain, chain_1_size, "%s", chain_1);
}
else if (generations == 2){
chain = realloc(chain, chain_2_size);
snprintf(chain, chain_2_size, "%s", chain_2);
}
else if (generations > 2){
size_t chain_3_size = strlen(chain_1) + strlen(chain_2) + 1;
char * chain_3 = malloc(chain_3_size);
printf("%i\n", generations);
for (i = 0; i < generations - 1; ++i){
printf("%i\n", i);
snprintf(chain_3, chain_3_size, "%s%s", chain_1, chain_2);
chain_1_size = chain_2_size;
chain_2_size = chain_3_size;
if ((tmp = realloc(chain_1, chain_1_size)) != NULL){
chain_1 = tmp;
}
if ((tmp = realloc(chain_2, chain_2_size)) != NULL){
chain_2 = tmp;
}
snprintf(chain_1, chain_1_size, "%s", chain_2);
snprintf(chain_2, chain_2_size, "%s", chain_3);
if (i < generations - 2){
chain_3_size = strlen(chain_1) + strlen(chain_2) + 1;
if ((tmp = realloc(chain_3, chain_3_size)) != NULL){
chain_3 = tmp;
} else {
printf("oops!\n");
exit(1);
}
}
}
chain = realloc(chain, chain_3_size);
snprintf(chain, chain_3_size, "%s", chain_3);
free(chain_3);
}
free(chain_1);
free(chain_2);
}
static int plot(){
char command[PATH_MAX];
snprintf(command, sizeof(command), "%s %s", GNUPLOT_EXE, GNUPLOT_SCRIPT);
system(command);
return 0;
}
The problem is that char *chain into fibonacci_quasicrystal_generator function has local scope: the function does not modify the crystal pointer of main, so that pointer is left with 2 bytes.
You can change the function to
static char *fibonacci_quasicrystal_generator(int generations, char * chain)
{
// YOUR STUFF
return chain;
}
And call it from main using
crystal = fibonacci_quasicrystal_generator(GENERATIONS, crystal);
You can achieve the same using a double pointer so
static void ibonacci_quasicrystal_generator(int generations, char ** chain)
I'm observing some really weird behavior regarding realloc .... I was wondering if y'all could help me.
I have an array of dynamically allocated char *'s called "frags". I also have a char * called "combination" which points to some string literal that represents a new fragment. I want to replace one of the fragments within "frags" with the contents of "combination." The way my project is structured, I am sending the frags array, index of to-be-replaced frag, and combination string into a function. Within this function I have:
printf("combination before realloc: %s\n", combination);
char *newString = (char *) realloc(frags[firstIndex], strlen(combination) + 1);
assert(newString != NULL);
printf("combination after realloc: %s\n", combination);
strcpy(newString, combination);
frags[firstIndex] = newString;
Oddly, the printf's do not print the same thing. The first printf yields "hellol" which is correct, but the next printf yields jibberish - something like "{?`?p??". Thus, the problem resides in the call to realloc. And I honestly have no idea what's going on. It seems the very call to realloc has messed with combination somehow, but I thought that if that could possibly happen then it would return NULL?
Please help me :(
Edit: Adding code
bool findMaxOverlap(char *first, char *second, char **combination, int *roundMax) {
// setup lng and shrt
char *lng, *shrt;
if (strlen(first) >= strlen(second)) { lng = first; shrt = second; }
else { lng = second; shrt = first; }
int shrtLen = strlen(shrt), lngLen = strlen(lng);
// check if lng contains shrt
if (strstr(lng, shrt) != NULL && shrtLen > *roundMax) {
*combination = lng;
*roundMax = shrtLen;
return true;
}
else // check if lng's tail ends contain part of shrt
{
int numChars = shrtLen - 1, max = 0, shrtOffset = 0, lngOffset = 0;
for (int i = 0; i < shrtLen && numChars > *roundMax && numChars > max; i++) {
numChars = shrtLen - 1 - i;
for (int j = 0; j < lngLen; j++) {
if (strncmp(shrt + i, lng + j, numChars) == 0) {
max = numChars;
shrtOffset = i;
lngOffset = j;
}
}
}
if (shrtOffset > lngOffset) {
// short first
char newFrag[lngLen + shrtOffset + 1];
strncpy(newFrag, shrt, shrtOffset);
strcat(newFrag, lng + shrtOffset);
*combination = newFrag;
*roundMax = numChars;
return true;
} else {
// lng first
char newFrag[lngLen + (shrtLen - numChars) + 1];
strcpy(newFrag, lng);
strcat(newFrag, shrt + numChars);
*combination = newFrag;
printf("combination in findmax is: %s\n", *combination);
*roundMax = numChars;
return true;
}
}
return false;
}
void mergeFrags(char *frags[], int index1, int index2, char *combination) {
int firstIndex, secondIndex;
if (index1 < index2) {
firstIndex = index1;
secondIndex = index2;
} else {
firstIndex = index2;
secondIndex = index1;
}
char temp[strlen(combination) + 1];
strcpy(temp, combination);
char *newString = (char *) realloc(frags[firstIndex], strlen(combination) + 1);
assert(newString != NULL);
strcpy(newString, temp);
frags[firstIndex] = newString;
free(frags[secondIndex]);
}
char *reassemble(char *frags[], int numFrags) {
if (numFrags > 1) {
char *combination;
int max, index1, index2, currNumFrags = numFrags;
for (int currentRound = 0; currentRound < numFrags - 1; currentRound++) {
max = index1 = index2 = 0, combination = NULL;
for (int i = 0; i < currNumFrags; i++) {
for (int j = i+1; j < currNumFrags; j++) {
//find max overlap of pair
if (findMaxOverlap(frags[i], frags[j], &combination, &max)) {
printf("round #: %d, combination: %s, max: %d\n", currentRound, combination, max);
index1 = i; index2 = j;
}
}
}
// merge
mergeFrags(frags, index1, index2, combination);
currNumFrags--;
}
}
return frags[0];
}
You said (in the comments above) that you were using strdup to allocate the data in combination, but what you're really doing is setting combination to point to data that's on the stack. After findMaxOverlap returns, you are now pointing at unallocated space on the stack, and this provides you with the undefined behavior you're seeing. When realloc is called, the area in the stack is reused, and the value of combination looks like garbage.
I got a segment fault error at the line with the comments that contains lots of equals signs below.
The function below str_spit, I wrote it because I want to split a string using a specific char, like a comma etc.
Please help.
int str_split(char *a_str, const char delim, char *** result)
{
int word_length = 0;
int cur_cursor = 0;
int last_cursor = -1;
int e_count = 0;
*result = (char **)malloc(6 * sizeof(char *));
char *char_element_pos = a_str;
while (*char_element_pos != '\0') {
if (*char_element_pos == delim) {
char *temp_word = malloc((word_length + 1) * sizeof(char));
int i = 0;
for (i = 0; i < word_length; i++) {
temp_word[i] = a_str[last_cursor + 1 + i];
}
temp_word[word_length] = '\0';
//
*result[e_count] = temp_word;//==============this line goes wrong :(
e_count++;
last_cursor = cur_cursor;
word_length = 0;
}
else {
word_length++;
}
cur_cursor++;
char_element_pos++;
}
char *temp_word = (char *) malloc((word_length + 1) * sizeof(char));
int i = 0;
for (i = 0; i < word_length; i++) {
temp_word[i] = a_str[last_cursor + 1 + i];
}
temp_word[word_length] = '\0';
*result[e_count] = temp_word;
return e_count + 1;
}
//this is my caller function====================
int teststr_split() {
char delim = ',';
char *testStr;
testStr = (char *) "abc,cde,fgh,klj,asdfasd,3234,adfk,ad9";
char **result;
int length = str_split(testStr, delim, &result);
if (length < 0) {
printf("allocate memroy failed ,error code is:%d", length);
exit(-1);
}
free(result);
return 0;
}
I think you mean
( *result )[e_count] = temp_word;//
instead of
*result[e_count] = temp_word;//
These two expressions are equivalent only when e_count is equal to 0.:)
[] has a higher precedence than *, so probably parentheses will solve THIS problem:
(*result)[e_count] = temp_word;
I didn't check for more problems in the code. Hint: strtok() might do your job just fine.
I am trying to write a code which gives coordinates of corners of a skyline, it was one of my friends' homework and I am trying it as a practice for myself. So, here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct building
{
int start, height, width;
} BUILDING;
int main()
{
FILE *buildingsptr, *outlineptr;
char karakter;
int satir = 1, i = 0, j = 0, *heights, lastpoint = 0 ;
BUILDING *ptr, *a, temp;
buildingsptr = fopen("buildings.txt", "r");
if (buildingsptr == NULL)
{
printf("An error occured while opening the file.\n");
system("PAUSE");
return 0;
}
while ((karakter = fgetc(buildingsptr)) != EOF)
{
if (karakter == '\n') satir++;
}
ptr = (BUILDING *) malloc(satir * sizeof(BUILDING));
a = ptr;
rewind(buildingsptr);
for (i = 0; i < satir; i++)
{
fscanf(buildingsptr, "%d %d %d", &ptr->start, &ptr->height, &ptr->width);
ptr++;
}
fclose(buildingsptr);
ptr = a; // a is for accessing the first part of the allocated memory,
// compiler gave some errors while I tried to access the first
// block of the array.
for (j = 0; j < satir; j++) //bubble sort to buildings
{
for (i = 0; i < satir; i++)
{
if (ptr[i].start > ptr[i + 1].start)
{
temp = ptr[i];
ptr[i] = ptr[i + 1];
ptr[i + 1] = temp;
}//end of if
}//end of second for
}//end of first for
lastpoint = ((ptr[satir - 1].start + ptr[satir - 1].width) + 1);
heights = (int *)calloc(lastpoint, sizeof(int));
for (j = 0; j < lastpoint; j++) // j travels the x axis
{
for (i = 0; i < satir; i++) // i counts buildings
{
if (j <= (ptr[i].start + ptr[i].width && ptr[i].start <= j))
{
if (ptr[i].height > heights[i])
heights[i] = ptr[i].height;
}
}
}
outlineptr = fopen("outline.txt", "w");
for (i = 0; i < lastpoint; i++) // for every point x,checking the heights
// and transforming them as the coordinates
{
if (heights[i + 1] > heights[i])
{
fprintf(outlineptr, "(%d,%d),", i + 1, heights[i]);
fprintf(outlineptr, "(%d,%d),", i + 1, heights[i + 1]);
}//end if
if (heights[(i + 1)] < heights[i])
{
fprintf(outlineptr, "(%d,%d),", i, heights[i]);
fprintf(outlineptr, "(%d,%d),", i, heights[i + 1]);
}//end if
}//end for
fprintf(outlineptr, "(%d,%d),", lastpoint, heights[lastpoint]);
fprintf(outlineptr, "(%d,%d)", lastpoint, 0);
getch();
return 0;
}
Code is working but it is writing wrong coordinates to the outline.txt. "buildings.txt" is something like:
24 7 4
5 7 11
26 9 7
9 5 5
3 12 4
33 9 6
37 5 7
12 9 10
First integer is starting point of a building, second one is height of the building and third one is width of the building. So, how can I re-write this code? I edited my code to be more proper.
This is a basic example of how the frame of your program should look.
The implementation of the algorithm itself should be up to you.
There is no need for separate line counting.
#include <stdio.h>
#include <stdlib.h>
typedef struct building
{
int start, height, width;
struct building *next;
struct building *prev;
} BUILDING;
int main()
{
FILE *inputFilePtr;
inputFilePtr = fopen("input.txt", "r");
if (inputFilePtr == NULL)
{
printf("An error occured while opening the file.\n");
return EXIT_FAILURE;
}
struct building *build = malloc(sizeof(*build));
struct building *reserve = build;
reserve->prev = NULL;
build->prev = NULL;
char lineBuf[1024];
while (fgets(lineBuf, 1024, inputFilePtr) != NULL)
{
sscanf(lineBuf, "%d %d %d", &(build->start), &(build->height), &(build->width));
build->next = malloc(sizeof(*build));
build->prev = build;
build = build->next;
}
build->next = NULL;
fclose(inputFilePtr);
/////////
// whatever logic comes here
////////
FILE *out = fopen("out.txt","w");
if (out == NULL) return EXIT_FAILURE;
// modify output function to fit your algorithm
while(reserve->next != NULL)
{
fprintf(out, "Build coordinates: (%d, %d, %d)\n", reserve->start, reserve->height, reserve->width);
reserve->prev = reserve;
reserve = reserve->next;
}
fclose(out);
// possible memory cleanup
/*
while(reserve->prev != NULL)
{
reserve = reserve->prev;
free(reserve->next);
}
*/
return 0;
}