How to fix this code written in C? - c

It works perfectly well for a 20-20 table but for anything else it crashes.
the file is in this link:http://www.csd.uoc.gr/~hy100/glid.txt.
I can not figure out what the problem is because when I put an 20-20 table it works and when
I give a 21-20 table it does the job perfectly fine but crashes before being able to return 0; .
#include <stdio.h>
#include <stdlib.h>
int height, length;
char **world, **new_world;
int load_world_from_file(char filename[]) {
int i, j;
char ch;
FILE *fp;
fp = fopen(filename, "r");
if (fp == NULL ) {
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
fscanf(fp, "%d %d", &height, &length);
printf("here:%d,%d\n", height, length);
/*dilosi dunamika tou pinaka kataxoriseis*/
/* declaration under the table entries */
world = (char **) malloc(sizeof(char *) * (height + 1));/*height + 1 ('\0')*/
for (i = 0; i < 2 * height; i++) {
/* height + height ('|') + 1 ('\0') */
world[i] = (char *) malloc(sizeof(char) * (length + length + 1));
}
/* height + 1 ('\0') */
new_world = (char **) malloc(sizeof(char *) * (height + 1));
for (i = 0; i < 2 * height; i++) {
/* height + height ('|') + 1 ('\0') */
new_world[i] = (char *) malloc(sizeof(char) * (length + length + 1));
}
printf("The contents of %s file are :\n", filename);
i = 0;
j = 0;
while ((ch = fgetc(fp)) != EOF) {
i++;
if (i = length + length + 1) {
j++;
i = 0;
}
world[j] = ch;
printf("%c", world[j]);
}
printf("\n");
for (i = 0; i < (((2 * length) + 2) * height) + 1; i++) {
printf("%c", world[i]);
}
fclose(fp);
return 0;
}
int main() {
char filename[30], filename2[30];
printf("Enter the name of file you want to open:\n");
scanf("%s", &filename);
load_world_from_file(filename);
return 0;
}
Your help is much appreciated.
IT

Related

i have been on this question for quaring the document for two days straight, and it is not working. don't want to cheat, can you point the problem

I am not able to debug what is going on. The code seems correct yet I am new to pointers to pointers, and here there are 4 in series.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
return *(*(*(document + n - 1) + m - 1) + k - 1);
}
char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) {
return (*(*(document + m - 1) + k - 1));
}
char ***kth_paragraph(char ****document, int k) {
return *(document + k - 1);
}
char ****get_document(char *text) {
/* allocating memory */
int len = strlen(text);
/* allocate memory for each component first */
char ****document = malloc(sizeof(char ***));
char ***paragraph = malloc(sizeof(char **));
char **sentence = malloc(sizeof(char *));
char *word = malloc(sizeof(char) * 1024);
/* connect all the components to point in the sequence that is required */
*document = paragraph;
*paragraph = sentence;
*sentence = word;
/* declare some numbers as iterators for the words, sentences,etc. */
int parano = 0;
int sentno = 0;
int wordno = 0;
int charno = 0;
/* now iterate over the text filling and expanding the document at the same time */
/*----------------------------------------------------------------------------------------------------*/
/* feeding data in those spaces */
for (int i = 0; i < len; i++) {
if (text[i] == ' ') {
/* wrapping the current word, that is, resizing to len + 1 */
char *current_word = *(*(*(document + parano) + sentno) + wordno);
current_word = realloc(current_word, strlen(current_word) + 1);
/* resizing the current sentence to add another word*/
char **current_sentence = (*(*(document + parano) + sentno));
current_sentence = realloc(current_sentence, sizeof(char *) * (wordno + 2));
wordno++;
charno = 0;
/* allocating space to that new char * / word that has been created in the same sentence */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
}
else if (text[i] == '.') {
/* wrapping of the current word has to be done anyways */
char *current_word1 = *(*(*(document + parano) + sentno) + wordno);
current_word1 = realloc(current_word1, strlen(current_word1) + 1);
charno = 0;
if (text[i + 1] != '\n') {
/* the paragraph does not change, and the sentence ends */
/* resize that paragraph for adding another sentence */
char ***current_para = *(document + parano);
current_para = realloc(current_para, sizeof(char **) * (sentno + 2));
sentno++;
wordno = 0;
/* allocating word to that sentence */
*(*(document + parano) + sentno) = malloc(sizeof(char *));
/* allocating space for that word */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
} else {
/* if this is the last sentence of this paragraph*/
wordno = 0;
charno = 0;
sentno = 0;
}
}
else if (text[i] == '\n') {
/* paragraph has changed */
/* add another paragraph to the document */
document = realloc(document, sizeof(char ***) * (parano + 2));
parano++;
/* add sentence to that paragraph */
(*(document + parano) ) = malloc(sizeof(char **));
/* add a word to that paragrapgh */
(*(*(document + parano) + sentno)) = malloc(sizeof(char *));
/* allocate space for that word */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
} else {
scanf("%c", *(*(*(document + parano) + sentno) + wordno) + charno);
printf("%c\n", **(*(*(document + parano) + sentno) + wordno) + charno);
charno++;
}
}
return document;
}
char *get_input_text() {
int paragraph_count;
scanf("%d", &paragraph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char *returnDoc = (char *)malloc((strlen(doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
void print_word(char *word) {
printf("%s", word);
}
void print_sentence(char **sentence) {
int word_count;
scanf("%d", &word_count);
for (int i = 0; i < word_count; i++) {
printf("%s", sentence[i]);
if (i != word_count - 1)
printf(" ");
}
}
void print_paragraph(char ***paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(*(paragraph + i));
printf(".");
}
}
int main() {
char *text = get_input_text();
char ****document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3) {
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
char *word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
print_word(word);
}
else if (type == 2) {
int k, m;
scanf("%d %d", &k, &m);
char **sentence = kth_sentence_in_mth_paragraph(document, k, m);
print_sentence(sentence);
} else {
int k;
scanf("%d", &k);
char ***paragraph = kth_paragraph(document, k);
print_paragraph(paragraph);
}
printf("\n");
}
}
this is one of the questions on Hackerrank for the C language.
link to the question
hacker rank question
my profile
shows aborted, realloc invalid size. I couldn't find anything for the last 2 days.
inputs for the problem
2
Learning C is fun.
Learning pointers is more fun.It is good to have pointers.
3
1 2
2
5
6
2 1 1
4
3 1 1 1
expected output
Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
When processing regular characters (final else clause) you read additional input instead of operating over text, i.e. instead of:
scanf("%c", &document[parano][sentno][wordno][charno]);
printf("%c\n", document[parano][sentno][wordno][charno]);
charno++;
you want to do:
document[parano][sentno][wordno][charno++] = text[i];
By the time we hit text[i] == ' ' for the first time the value of ***document is "3\n1 2\n2\n" but you wanted it to be "Learning".
(not fixed) When processing a word (`text[i] == ' ') you expand current word, yet, you hard-code 1000 when you allocate it initially so this doesn't make sense. Be consistent.
parano, sentno, wordno, charno is indices but same suggest they are counts. It's not wrong just confusing and why you have to wordno + 2 when relloc'ing.
Terminate words with `\0'.
When you process ' ' you add another word which you may or may not need which is fine. But when process a '.' you look ahead to the following letter is a \n or not. Be consistent. If you look ahead then you need to check that i + 1 < len, and it's fragile, say, there is a stray space before the \n.
(not fixed) Memory leaks. As the size of the sub-elements (paragraph, sentences and words) are private implementation details of get_document() you will have refactor the code to make those available. I suggest:
struct document {
char ****document;
size_t paragraphs;
size_t sentences;
size_t words;
}
(not fixed) Deduplicate. Similar to the print functions, create a allocation function per type.
(not fixed, really) get_input_text(). You split the into paragraphs then concatenate everything again into a local variable then copy it into a dynamically allocated variable:
char *str = malloc(BUFFER_LEN);
for(size_t i = 0, l = 0; l < lines && i + 1 < BUFFER_LEN; i += strlen(str + i)) {
int rv = fgets(str + i, BUFFER_LEN - i, stdin);
if(!rv) {
// handle error
break;
}
}
return s;
(not fixed) Separate i/o from processing. This simplifies testing and it makes it easier to figure out what is going on. In main(), you read a query type then 1 to 3 numbers. scanf()` tells you how many items where read so you simply do. As you don't use the kth_ functions for anything else just combine then with print_ funci
int n = scanf("%d %d %d %d", &type, &p, &s, &w);
switch(type) {
case 1:
if(n != 2) {
// handle error
}
print_paragraph(document, p);
break;
...
}
(not fixed) Add error checks for the remainingmalloc(), strdup() etc.
Don't hard-code magic values (1000). I introduced the constant WORD_LEN but you also have MAX_CHARACTERS which is kinda the same thing.
(not fixed) Consider using char *s = strpbrk(text + i, " .\n") to copy a word at a time. It will simplify \0 handling, and likely to be faster than walking the text a byte at a time, i.e. i += s - text + i, just handle the s == NULL special case.
valgrind is now happy other than leaks (see above):
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
#define WORD_LEN 1000
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int p, int s, int w) {
return document[p - 1][s - 1][w - 1];
}
char **kth_sentence_in_mth_paragraph(char ****document, int p, int s) {
return document[p - 1][s - 1];
}
char ***kth_paragraph(char ****document, int p) {
return document[p - 1];
}
char ****get_document(char* text) {
char ****document = malloc(sizeof ***document);
*document = malloc(sizeof **document);
**document = malloc(sizeof *document);
***document = malloc(WORD_LEN);
/* declare some numbers as iterators for the words, sentences,etc.*/
int parano = 0;
int sentno = 0;
int wordno = 0;
int charno = 0;
/* now iterate over the text filling and expanding the document at the same time*/
/*----------------------------------------------------------------------------------------------------*/
/* feading data in those spaces*/
size_t len = strlen(text);
for (size_t i = 0; i < len; i++) {
switch(text[i]) {
case ' ': {
document[parano][sentno][wordno][charno] = '\0';
wordno++;
char **words = realloc(
document[parano][sentno],
(wordno + 1) * sizeof *document[parano][sentno]
);
if(!words) {
printf("realloc of words failed\n");
exit(1);
}
document[parano][sentno] = words;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
case '.': {
document[parano][sentno][wordno][charno] = '\0';
sentno++;
char ***sentences = realloc(
document[parano],
(sentno + 1) * sizeof *document[parano]
);
if(!sentences) {
printf("realloc of sentences failed\n");
exit(1);
}
document[parano] = sentences;
document[parano][sentno] = malloc(sizeof **document);
wordno = 0;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
case '\n': {
document[parano][sentno][wordno][charno] = '\0';
parano++;
char ****paragraphs = realloc(
document,
(parano + 1) * sizeof *document
);
if(!paragraphs) {
printf("realloc of paragraphs failed\n");
exit(1);
}
document = paragraphs;
document[parano] = malloc(sizeof ***document);
sentno = 0;
document[parano][sentno] = malloc(sizeof **document);
wordno = 0;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
default: // character
document[parano][sentno][wordno][charno++] = text[i];
}
}
return document;
}
char *get_input_text() {
int paragraph_count;
scanf("%d", &paragraph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS];
char doc[MAX_CHARACTERS];
memset(doc, 0, sizeof doc);
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
return strdup(doc);
}
void print_word(char *word) {
printf("%s", word);
}
void print_sentence(char **sentence) {
int word_count;
scanf("%d", &word_count);
for(int i = 0; i < word_count; i++){
print_word(sentence[i]);
if(i + 1 != word_count)
printf(" ");
}
}
void print_paragraph(char ***paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(paragraph[i]);
printf(".");
}
}
int main() {
char *text = get_input_text();
char ****document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
switch(type) {
case 1: {
int p;
scanf("%d", &p);
print_paragraph(kth_paragraph(document, p));
break;
}
case 2: {
int p, s;
scanf("%d %d", &p, &s);
print_sentence(kth_sentence_in_mth_paragraph(document, p, s));
break;
}
case 3: {
int p, s, w;
scanf("%d %d %d", &p, &s, &w);
print_word(kth_word_in_mth_sentence_of_nth_paragraph(document, p, s, w));
break;
}
default:
printf("error\n");
}
printf("\n");
}
free(text);
}
Output as expected:
Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
Btw, a whole different way of solving this is problem is keep the original input (text) then write functions to directly extract a paragraph, sentence or word from that string. If you input is huge then create an index, say, (paragraph, sentence, word) to &text[i].
finally did it.
a big thanks to #allanwind for your support
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
return *(*(*(document + n - 1) + m - 1) + k - 1);
}
char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) {
return (*(*(document + m - 1) + k - 1));
}
char ***kth_paragraph(char ****document, int k) {
return *(document + k - 1);
}
char ****get_document(char *a)
{
int len = strlen(a);
char ****document = malloc(sizeof(char ***) * MAX_PARAGRAPHS);
int parano = 0;
char ***paragraph = malloc(sizeof(char **) * MAX_CHARACTERS);
int sentno = 0;
char **sentence = malloc(sizeof( char *) * MAX_CHARACTERS);
int wordno = 0;
char *word = malloc(sizeof(char ) * MAX_CHARACTERS);
int charno = 0;
for (int i = 0; i < len; i++)
{
/* after this way, try to learn switch conditionals*/
if (a[i] == ' ')
{
/* if find a space, that is there are more words within the same sentence*/
/* close the word*/
word[charno] = '\0';
/* add the word to the sentence*/
sentence[wordno] = word;
wordno++;
charno = 0;
/* create another word*/
char *tmp = malloc(sizeof(char) * MAX_CHARACTERS);
/* if the word got space without errors,*/
if (tmp != NULL)
{
word = tmp;
}
}
else if (a[i] == '.')
{
// terminate the word
word[charno] = '\0';
// add word to the sentence
sentence[wordno] = word;
wordno = 0;
charno = 0;
// add sentence to paragraph
paragraph[sentno] = sentence;
if (i != len - 1)
{
sentno++;
// allocate space for new sentence, as it is not the end
char **tmp1 = malloc(sizeof(char *) * MAX_CHARACTERS);
if (tmp1 != NULL)
{
sentence = tmp1;
}
// allocate space for new word
char *tmp2 = malloc(sizeof(char) * MAX_CHARACTERS);
if (tmp2 != NULL)
{
word = tmp2;
}
}
else
{
document[parano] = paragraph;
}
}
else if (a[i] == '\n')
{
// add paragraph to the document
document[parano] = paragraph;
parano++;
// allocate memory for another paragraph
char ***tmp3 = malloc(sizeof(char **) * MAX_CHARACTERS);
if (tmp3 != NULL)
{
paragraph = tmp3;
}
charno = 0;
wordno = 0;
sentno = 0;
}
else
{
/* step 1 read the text into the word char by char*/
word[charno] = a[i];
charno++;
}
}
return document;
}
char* get_input_text() {
int paragraph_count;
scanf("%d", &paragraph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char* returnDoc = (char*)malloc((strlen (doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
void print_word(char* word) {
printf("%s", word);
}
void print_sentence(char** sentence) {
int word_count;
scanf("%d", &word_count);
for(int i = 0; i < word_count; i++){
printf("%s", sentence[i]);
if( i != word_count - 1)
printf(" ");
}
}
void print_paragraph(char*** paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(*(paragraph + i));
printf(".");
}
}
int main()
{
char* text = get_input_text();
char**** document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3){
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
char* word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
print_word(word);
}
else if (type == 2){
int k, m;
scanf("%d %d", &k, &m);
char** sentence = kth_sentence_in_mth_paragraph(document, k, m);
print_sentence(sentence);
}
else{
int k;
scanf("%d", &k);
char*** paragraph = kth_paragraph(document, k);
print_paragraph(paragraph);
}
printf("\n");
}
}

File overflowing into allocated memory C

I am trying to write a basic mutant testing script in C, but I've come across some errors which I cannot seem to solve. The first thing to comment is that in the function that seems to be having problems, namr, I try am trying to name the file I am creating using a simple caesar cypher to avoid having unwanted characters in the file name. When I run it as is, it seems as though the strings cexp and mcexp are sometimes getting content from a file I am reading in another function switchr.
When I add the printf at Annotation 1 it seems to run fine but the filenames come out wrong. Still, if I comment Annotation 1 out, there is a malloc(): corrupted top size error. I have tried various prints to see what is wrong. By the time it gets to Annotation 2, cexp and mcexp are still the desired length and content but, by the time they get to Annotation 3, they're 26 or 25 characters long and include the starting lines of the file I am reading in other parts of the script.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *namr(char *exp, char *mexp, int ignv) {
int explen = strlen(exp);
int mexplen = strlen(mexp);
//printf("EXPLEN: %d MEXPLEN: %d\n",explen,mexplen);
//ANNOTATION 1
char *cexp = (char *)malloc(explen + 1);
char *cmexp = (char *)malloc(mexplen + 1); //Exp in Caeser Cipher
for (int i = 0; i < explen; i++) {
cexp[i]= (exp[i] ? 'A' + exp[i] % 25 : exp[i]);
printf("%d - %c - %c\n", i, exp[i], 'A' + exp[i] % 25);
//ANNOTATION 2
}
for (int i = 0; i < mexplen; i++) {
cmexp[i]= (mexp[i] ? 'A' + mexp[i] % 25 : mexp[i]);
}
printf("EXP: %s\nMEXP: %s\n", exp, mexp);
printf("CEXP: %s\nCMEXP: %s\n", cexp, cmexp);
//ANNOTATION 3
printf("%s - %d\n%s - %d\n%d\n", cexp, strlen(cexp),
cmexp, strlen(cmexp), strlen("./U_SWITCH_MTNTS/TO%03.c"));
char *outname = (char *)malloc((30 + explen + mexplen));
sprintf(outname, "./U_SWITCH_MTNTS/%sTO%s%03d.c", cexp, cmexp, ignv);
free(cexp);
free(cmexp);
return outname;
}
int countr(char *filename, char *exp) {
int out = 0;
int i, flag;
int inlen = strlen(exp);
char c;
FILE *f = fopen(filename, "r");
while (c != EOF) {
for (i = 0, flag = 0; i < inlen; i++) {
if (exp[i] != c) {
flag = 1;
break;
}
c = getc(f);
}
if (flag == 0)
out++;
c = getc(f);
}
fclose(f);
return out;
}
char *switchr(char *filename, char *exp, char *mexp, int ignv) {
int i, flag,buffcount;
FILE *f = fopen(filename, "r");
char *outname = namr(exp, mexp, ignv);
FILE *fout = fopen(outname, "w");
char c = getc(f);
int ignc = ignv;
int inlen = strlen(exp);
char *buffer = (char *)malloc(inlen * sizeof(char));
while (c != EOF) {
for (i = 0, flag = 0, buffcount = 0; i < inlen; i++) {
if (exp[i] != c) {
flag = 1;
break;
} else {
buffer[buffcount] = c;
buffcount++;
c = getc(f);
}
}
if (flag == 0) {
if(ignc == 0) {
fputs(mexp, fout);
} else {
for (i = 0; i < buffcount; i++)
fputc(buffer[i], fout);
}
ignc--;
} else {
for (i = 0; i < buffcount; i++)
fputc(buffer[i], fout);
}
fputc(c, fout);
c = getc(f);
}
fclose(f);
fclose(fout);
return outname;
}
void mstrswitch(char *filename) {
int ecount = countr(filename, "==");
char **filenames = (char **)malloc(5 * ecount * sizeof(char *));
char command[100];
system("mkdir U_SWITCH_MTNTS");
system("mkdir TEST_OBJECTS");
for (int i = 0;i < ecount; i++) {
filenames[5 * i] = switchr("test.c", "==", "<=", i);
filenames[5 * i + 1] = switchr("test.c", "==", ">=", i);
filenames[5 * i + 2] = switchr("test.c", "==", ">", i);
filenames[5 * i + 3] = switchr("test.c", "==", "<", i);
filenames[5 * i + 4] = switchr("test.c", "==", "!=", i);
}
for (int i = 0; i < 5 * ecount; i++) {
sprintf(command, "gcc -o ./TEST_OBJECTS/test%03d %s", i, filenames[i]);
system(command);
sprintf(command, "./TEST_OBJECTS/test%03d", i);
system(command);
free(filenames[i]);
}
free(filenames);
}
int main() {
mstrswitch("test.c");
return 0;
}
You never zero terminates the strings cexp and cmexp. So add these two lines:
for(int i=0;i<explen;i++)
{
cexp[i]= (exp[i]?'A'+exp[i]%25: exp[i]);
printf("%d - %c - %c\n",i,exp[i],'A'+exp[i]%25);
}
cexp[explen]= '\0'; <------------------- add
for(int i=0;i<mexplen;i++)
{
cmexp[i]= (mexp[i]?'A'+mexp[i]%25: mexp[i]);
}
cmexp[mexplen]= '\0'; <------------------- add
Besides that the following line looks strange:
cexp[i]= (exp[i]?'A'+exp[i]%25: exp[i]);
^^^^^^
Always true
Having a condition that always returns true is probably not what you intended.

file size exceeds buffer size

I want to compare 2 files for identical lines: mytab2411.txt(15,017,210 bytes in size) and shadow.txt (569 bytes in size) but when I compiled this code and ran the program, I get a segmentation fault. I know that it's because the "mytab2411.txt" file exceeds the size of "char buf" but how do I go about solving this problem without overflowing the buffer?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
int cmp(const void * s1, const void * s2)
{
return strcasecmp(*(char **)s1, *(char **)s2);
}
int cmp_half(const char * s1, const char * s2)
{
int i;
for (i = 0; i < 3; i++)
{
int res = strncasecmp((char *)s1+i*3, (char *)s2+i*3, 2);
if (res != 0) return res;
}
return 0;
}
char * line[1024];
int n = 0;
int search(const char * s)
{
int first, last, middle;
first = 0;
last = n - 1;
middle = (first+last)/2;
while( first <= last )
{
int res = cmp_half(s, line[middle]);
if (res == 0) return middle;
if (res > 0)
first = middle + 1;
else
last = middle - 1;
middle = (first + last)/2;
}
return -1;
}
int main()
{
FILE * f1, * f2;
char * s;
char buf[1024*1024], text[1024];
f1 = fopen("shadow.txt", "rt");
f2 = fopen("mytab2411.txt", "rt");
s = buf;
while (fgets(s, 1024, f2) != NULL)
{
line[n] = s;
s = s+strlen(s)+1;
n++;
}
qsort(line, n, sizeof(char *), cmp);
while (fgets(text, 1024, f1) != NULL)
{
text[strlen(text)-1] = 0;
int idx = search(text);
if (idx >= 0)
{
printf("%s matched %s\n", text, line[idx]);
}
else
{
printf("%s not matched\n", text);
}
}
return 0;
}
Your method assumes that each line in the file is 1024 bytes long. In practice the lines can be up to 1024 bytes, but most lines are much shorter. Use strdup or malloc to allocate memory for each line based on line's length.
Store the lines in dynamically allocated arrays. This is about 15 MB of data and it should not be a problem unless there are resource limitations.
int main(void)
{
char buf[1024];
char **arr1 = NULL;
char **arr2 = NULL;
int size1 = 0;
int size2 = 0;
FILE * f1, *f2;
f1 = fopen("shadow.txt", "r");
f2 = fopen("mytab2411.txt", "r");
while(fgets(buf, 1024, f1))
{
size1++;
arr1 = realloc(arr1, sizeof(char*) * size1);
arr1[size1 - 1] = strdup(buf);
}
while(fgets(buf, 1024, f2))
{
size2++;
arr2 = realloc(arr2, sizeof(char*) * size2);
arr2[size2 - 1] = strdup(buf);
}
for(int i = 0; i < size1; i++)
for(int j = 0; j < size2; j++)
{
if(strcmp(arr1[i], arr2[j]) == 0)
printf("match %s\n", arr1[i]);
}
return 0;
}

Aborted Core dumped only with large string

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)

Reading from csv file and dynamic memory allocation

My code has a memory leak problem. I don't know where I went wrong. Below is the code: I am trying to read from csv file and store a particular columns.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
FILE *result = fopen ("C:\\Users\\pa1rs\\Desktop\\local.csv", "w");
const char *text = "LOA,NAME,";
fprintf (result, "%s", text);
char *token;
char *endToken;
int lines = 0;
char ch; /* should check the result */
FILE *file = fopen ("C:\\Users\\pa1rs\\Desktop\\samplee.csv", "r");
char line[300];
if (file == NULL) {
perror ("Error opening the file");
} else {
while (!feof (file)) {
ch = fgetc (file);
if (ch == '\n') {
lines = lines + 1;
}
}
//printf(" no of lines existing in the file %d\n\n", lines);
}
fseek (file, 0, SEEK_SET);
while ((ch = fgetc (file)) != '\n') {
// we don't need the first line on sample.csv
// as it is just the description part
}
int s[lines - 1];
int j = 0;
char *N[lines - 1];
while (fgets (line, sizeof (line), file)) {
int i = 0;
token = line;
do {
endToken = strchr (token, ',');
if (endToken)
*endToken = '\0';
if (i == 3) {
s[j] = atoi (token);
}
if (i == 12) {
N[j] = (char *) malloc (strlen (token) * sizeof (char));
strcpy (N[j], token);
}
if (endToken)
token = endToken + 1;
i++;
} while (endToken);
j = j + 1;
}
//******************************************************unigue loa
int count = 0;
int g = 0;
int h = 0;
int LOA[lines - 1];
int dd = 0;
for (dd = 0; dd < lines - 1; dd++) {
LOA[dd] = 0;
}
for (g = 0; g < lines - 1; g++) {
for (h = 0; h < count; h++) {
if (s[g] == LOA[h])
break;
}
if (h == count) {
LOA[count] = s[g];
count++;
}
}
int xw = 0;
for (xw = 0; xw < count; xw++) {
//printf("%d \t",LOA[xw]);
}
//printf("LOA Array Length is: %d \n",count);
//********************************************************
////FOR UNIQUE NAMES ARRAY
//printf("No of unique names are %d",county);
//FOR UNIQUE CAUSES ARRAY
char *sa[9] =
{ "Monticello", "Valparaiso", "Crown Point", "Plymouth", "Goshen",
"Gary", "Hammond", "Laporte", "Angola" };
int countz = 0;
int gz = 0;
int hz = 0;
char *LOAz[lines - 1];
int zero2 = 0;
for (zero2 = 0; zero2 < lines - 1; zero2++) {
LOAz[zero2] = NULL;
}
for (gz = 0; gz < lines - 1; gz++) {
for (hz = 0; hz < countz; hz++) {
if (strcmp (N[gz], LOAz[hz]) == 0)
break;
}
if (hz == countz) {
LOAz[countz] = (char *) malloc (strlen (N[gz]) * sizeof (char));
strcpy (LOAz[countz], N[gz]);
countz++;
}
}
int nz = 0;
for (nz = 0; nz < countz; nz++) {
fprintf (result, "%s,", LOAz[nz]);
}
fprintf (result, "\n");
// printf("%d",countz);
//*****************************
int i = 0;
int jjj = 0;
int xxx = 0;
int ggg = 0;
int k = 0;
int kount[count][countz];
for (xxx = 0; xxx < count; xxx++) {
for (ggg = 0; ggg < countz; ggg++) {
kount[xxx][ggg] = 0;
}
}
for (i = 0; i < count; i++) {
for (k = 0; k < countz; k++) {
for (jjj = 0; jjj < lines - 1; jjj++) {
if (LOA[i] == s[jjj]) {
if (strcmp (LOAz[k], N[jjj]) == 0) {
kount[i][k]++;
}
}
}
}
}
int ig = 0;
int ik = 0;
for (ig = 0; ig < count; ig++) {
fprintf (result, "%d,%s", LOA[ig], sa[ig]);
for (ik = 0; ik < countz; ik++) {
fprintf (result, ",%d", kount[ig][ik]);
}
fprintf (result, "\n");
}
int rrr = 0;
free (N);
for (rrr = 0; rrr < lines - 1; rrr++) {
free (LOAz[rrr]);
}
//*****************************
//fclose(result);
fclose (file);
return 0;
}
Lines I got here is 13761 and LOAz was declared with array size lines-1=13761, but unique ones I got here are only 49, So I am reallocating memory for that and remaining are unused , I think problem started there.
Please help! Thanks in Advance.
One problem in your code is that you don't allocate enough memory for strings. For example, in these lines:
N[j] = (char*) malloc(strlen(token) * sizeof(char));
strcpy(N[j], token);
// ...
LOAz[countz] = (char*) malloc(strlen(N[gz]) * sizeof(char));
strcpy(LOAz[countz], N[gz]);
The problem is that strlen returns the number of non-zero symbols in the string. However, to store the string you need one more byte, to also store the zero terminating character, so the buffer size to store s should be at least strlen(s) + 1.
Also, a better coding style is to avoid casting the return value of malloc.

Resources