Segmentation fault when writing contents of dictionary to file - c

The code I am working on reads in a dictionary of 45430 words and then prints to the file all the other words in the dictionary contained within each word. I am just working on getting the file MyDictionary txt file read into the char array word[45430][30] and then printing this to the words-in-words txt file. I run into a seg fault at 44946 word when I do so, but in the same while loop I am also printing to the console and all words print out properly. Why is it I am getting this seg fault for writing to the file? And why is there no seg fault writing to the console?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
//char ***alloc_array(int,int);
int main(void){
FILE *fr; //declare file read file pointer
FILE *fp; //declare file printed file pointer
//char array to read in up to 30 chars
char line[31];
long numwords=45430; //number of words in dictionary
int maxlength=31; // the longest string in dictionary (30 chars)
long i; //counts up to 45430
//allocate space for 45430 words at a max length of 30 chars (1 extra char for "\0")
char ***word = calloc(numwords, sizeof(char **));
for(i = 0; i != numwords; i++) {
word[i] = calloc(maxlength, sizeof(char *));
}
//Open MyDictionary.txt and determine if there is an error or not
fr = fopen ("MyDictionary.txt", "r"); // open the file for reading
if(fr==NULL){
printf("\nError! opening input file");
exit(1); //Program exits if file pointer returns NULL.
}
//Open words-within-words.txt and determine if there is an error or not
fp = fopen ("words-within-words.txt", "w"); // open the file for reading
if(fp==NULL){
printf("\nError! opening output file");
exit(1); //Program exits if file pointer returns NULL.
}
int j=0; //counts to 30 for max length
i=0;
while(fgets(line, 40, fr) != NULL){ //get a line, up to 40 chars from fr and put first . done if NULL
for(j=0;j<30;){
word[i][j]=&line[j];
j++;
}
j=0;
printf("\n%s",word[i][j]); //print out each word of dictionary to console on its own line
/*
if((i>4 && i<8)||(i>45428)){
fprintf(fp,"\nanalyze:word[i][0]=%s\tword[i][2]=%s\ti=%li",word[i][0],word[i][2],i+1);
}
*/
fprintf(fp,"%s",word[i][j]); //print out each word of dictionary to words-in-words on its own line
i++;
}
fclose(fr); //close the files prior to exiting
fclose(fp);
return 0;
} //main

char ***word = calloc(numwords, sizeof(char **));
for(i = 0; i != numwords; i++) {
word[i] = calloc(maxlength, sizeof(char *));
}
You've got one too many levels of indirection. You are storing a list of words. A word is a char *, so a list of words would be char **.
char **word = calloc(numwords, sizeof(char *));
for (i = 0; i != numwords; i++) {
word[i] = calloc(maxlength, sizeof(char));
}
This will then necessitate changes to the rest of your code. You can get rid of j entirely. This:
for(j=0;j<30;){
word[i][j]=&line[j];
j++;
}
Becomes:
strcpy(word[i], line);
And this:
j=0;
printf("\n%s",word[i][j]);
fprintf(fp,"%s",word[i][j]);
i++;
Becomes:
printf("%s\n", word[i]);
fprintf(fp, "%s\n", word[i]);

'word' should be an array of pointers, so the right type is char **, not char ***.
Each entry in the array is a pointer to a buffer of characters:
char **word = (char **)calloc(numwords, sizeof(char *));
if (!word)
// exit with error
for (i = 0; i != numwords; i++) {
word[i] = (char *)calloc(maxlength, sizeof(char)); // just allocate 31 bytes
if (!word[i])
// exit with error
}
Then a read from file can be done like this:
for (i = 0; fgets(line, 40, fr); i++) {
strncpy(word[i], line, maxlength);
printf("word %d: %s\n", i, word[i]);
}

To have one chunk of memory do allocate like this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int result = EXIT_SUCCESS;
size_t n = 45430;
size_t l = 30;
char (* words)[n][l + 1] = calloc(n, l + 1);
if (NULL == words)
{
result = EXIT_FAILURE;
perror("calloc() failed");
goto lblExit;
}
for (size_t i = 0; i < n; ++i)
{
strncpy((*words)[i], "test", l);
}
for (size_t i = 0; i < n; ++i)
{
printf("%zu: '%s'\n", i, (*words)[i]);
}
free(words);
lblExit:
return result;
}

Related

Parsing senteces from a txt file to a multidimensional array in C

this is driving me crazy. I'm trying to parse from a txt file every sentence (that is all characters between dots) and insert each sentence into an array. The end goal is to have a multi dimensional array with each sentence as single array.
I managed to reach a point where I think it should work but I'm getting a segmentation fault (core dumped) error from the line numOfRow++
void parseRows(FILE* file){
int c;
int numOfRow = 0;
int numOfChar = 0;
int numOfRows = countNumOfRows(file);
fseek(file, 0, SEEK_SET); // Reset file pointer position to the beginning
char **rows = malloc(numOfRows*sizeof(char*));
for (int i=0; i < numOfRows; i++) rows[i] = malloc(1000*sizeof(char));
while ((c=fgetc(file))!= EOF) {
if (c != '.') {
rows[numOfRow][numOfChar] = c;
numOfChar++;
} else {
rows[numOfRow][numOfChar] = '\0';
numOfRow++; // This is throwing the error
numOfChar = 0;
}
}
printOutput(rows, numOfRows);
}
If I comment out that line the program overwrites every line on the first array and I get only the last sentence as result so I know it's working.
What am I missing?
Complete code here:
#include <stdio.h>
#include <stdlib.h>
#define USAGE "USAGE: ./huffman <textFile.txt>\n"
FILE* openFile(char[]);
void parseRows(FILE*);
int countNumOfRows(FILE*);
void printOutput(char**, int);
int main(int argc, char** argv){
FILE* fd;
if (argc != 2) printf("%s", USAGE);
fd = openFile(argv[1]);
parseRows(fd);
}
FILE* openFile(char* file){
FILE* stream;
stream = fopen(file, "r");
return stream;
}
int countNumOfRows(FILE* file){
int i = 0;
char c;
while ((c=fgetc(file))!= EOF) {
if (c == '.') i++;
}
printf("numero di righe %d\n", i);
return i;
}
void parseRows(FILE* file){
int c;
int numOfRow = 0;
int numOfChar = 0;
int numOfRows = countNumOfRows(file);
fseek(file, 0, SEEK_SET); // Reset file pointer position to the beginning
char **rows = malloc(numOfRows*sizeof(char*));
for (int i=0; i < numOfRows; i++) rows[i] = malloc(1000*sizeof(char));
while ((c=fgetc(file))!= EOF) {
if (c != '.') {
rows[numOfRow][numOfChar] = (char)c;
numOfChar++;
} else {
rows[numOfRow][numOfChar] = '\0';
numOfRow += 1;
numOfChar = 0;
}
}
printOutput(rows, numOfRows);
}
void printOutput(char** matrix, int rows){
for (int i=0; i<rows; i++){
printf("%s", matrix[i]);
}
}
Example of input file textFile.txt:
Any text that contains more than one sentence.
This Should get parsed and return a 2 dimension array with every sentence as single array.
Your countNumOfRows() function counts the dots in a file, and you use that number to malloc space for your array. However, there are likely more characters beyond the last dot and before EOF (e.g. a CR or LF or CRLF), so you can easily write past the end of your malloc'd memory.
Try:
return (i + 1)
at the end of countNumOfRows() and see if that eliminates the segfault.

Printing to file from global array of chars in c

I am having a problem while trying to print to txt file from global array of char*.
My array is declared as
char* codes[256];
also i have a function that construct a string and returns it to after which that value is placed into this global array
char* printArr(int arr[], int n)
{
char* code = (char *) malloc(sizeof(char) * (n+1));
int i;
for (i = 0; i < n; ++i)
{
code[i] = arr[i] + '0';
}
code[n] = '\0';
return code;
}
after which I just simply place that value into that global array. After that I am trying to print that array values into a txt file like this :
void PrintToFile(char* outputFileName)
{
FILE* f = fopen(outputFileName, "w+");
int i;
for (i = 0; i < 256; ++i)
{
//printf("%s\n", codes[i]);
fprintf(f, "%s\n", codes[i]);
}
fclose(f);
}
But for some reason my txt file turns out blank.
Also without opened stream when I try to print to stdout i get those values but with both printf and fprintf I don't get anything out either on stdout or in txt file.
Thanks in advance!

C project with files

I need some help with my C project:
I need to write a c program who receives 2 parameters:
1) The name of a text file(infile) which is in the same catalog
2) A number k>0
And creates 2 new files,outfile1 & outfile 2 as:
Outfile 1: k,2*k,3*k…. character of infile
Outfile 2: k,2*k,3*k…..line of infile
Example:
INFILE
Abcdefg
123456
XXXXXX
01010101
OUTFILE 1:
Cf25XX101
OUTFILE 2:
XXXXXX
I wrote some code ,but its not working. Any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** read_lines(FILE* txt, int* count) {
char** array = NULL;
int i;
char line[100];
int line_count;
int line_length;
*count = 0;
line_count = 0;
while (fgets(line, sizeof(line), txt) != NULL) {
line_count++;
}
rewind(txt);
array = malloc(line_count * sizeof(char *));
if (array == NULL) {
return NULL;
}
for (i = 0; i < line_count; i++) {
fgets(line, sizeof(line), txt);
line_length = strlen(line);
line[line_length - 1] = '\0';
line_length--;
array[i] = malloc(line_length + 1);
strcpy(array[i], line);
}
*count = line_count;
return array;
}
int main(int argc, char * argv[]) {
char** array = NULL;
FILE* file = NULL;
const char* filename = NULL;
int i;
int line_count;
int k;
char c;
printf("ENTER ONE PHYSICAL NUMBER\n");
do{
if(k>0)
scanf("%d",&k);
else{
printf("ENTER ONE PHYSICAL NUMBER\n");
scanf("%d",&k);
}
}while(k<=0);
file = fopen("LEIT.txt", "rt");
if (file == NULL) {
printf("CANT OPEN FILE %s.\n", filename);
return 1;
}
array = read_lines(file, &line_count);
printf("ARRAY:\n");
for (i = 0; i < line_count; i++) {
printf("[%d]: %s\n", (i+1), array[i]);
}
printf("CALCULATING OUTFILE1 AND OUTFILE2\n");
printf("OUTFILE1:\n");
for(i=0;i<line_count;i++){
c=i*k;
printf("%c\n",array[c]);
}
printf("WRITING OUTFILE1 COMPLETE!\n");
printf("OUTFILE2:\n");
for(i=0;i<line_count;i++){
c=i*k;
printf("%c\n",array[c]);
}
printf("WRITING OUTFILE2 COMPLETE!\n");
return 0;
}
My actual problem is calculate and write into files (outfile1 and outfile2) the result...
You need to close file after finishing reading/writing it with fclose.
You can create and write strings to a file using fopen with correct mode.
You can output formatted string to a file by using fprintf.
It seems that you don't want to print the 0th character/line, so in the last for loop, i should start from 1 (or start from 0 but add 1 later).
array[c] is a string, not a character. So when printing it, you should use %s specifier instead of %c.
It is not a good idea using char as count in later for loops unless you know input file will be very short. signed char can only count to 127 before overflow (unsigned char can count to 255). But if you have a very long file, for example thousands of lines, this program would not work properly.
array is malloced in function char** read_lines(FILE* txt, int* count). After finish using it, you need to dealloc, or free it by calling
for (i = 0; i < line_count; i++) {
free(array[i]);
}
and followed by free(array). This avoids memory leakage.
Modified code is here. In the following code, char c is not used. This is the part where you process output files, and before return 0; in main function.
printf("CALCULATING OUTFILE1 AND OUTFILE2\n");
printf("OUTFILE1:\n");
// Since we finished using LEIT.txt, close it here.
fclose(file);
// Mode: "w" - Write file. "+" - Create if not exist.
// You can lso use "a+" (append file) here if previous record need to be preserved.
FILE *out1 = fopen("OUTFILE1.txt", "w+");
FILE *out2 = fopen("OUTFILE2.txt", "w+");
if ((out1 == NULL) || (out2 == NULL)) {
printf("CANT CREATE OUTPUT FILES.\n");
return 1;
}
// Out file 1.
unsigned int count = k;
for (i = 0; i < line_count; i++){
while (count < strlen(array[i])) {
// This just prints to stdout, but is good for debug.
printf("%c", array[i][count]);
// Write to the file.
fprintf(out1, "%c", array[i][count]);
// Calculate c for next char.
count += k + 1;
}
// Before go to next line, minus string length of current line.
count -= strlen(array[i]);
}
printf("\n");
printf("WRITING OUTFILE1 COMPLETE!\n");
// Close file.
fclose(out1);
// Out file 2.
printf("OUTFILE2:\n");
for (i = 1;i < line_count / k; i++){
count = i * k;
// This just prints to stdout, but is good for debug.
printf("%s\n", array[count]);
// Write to the file.
fprintf(out2, "%s\n", array[count]);
}
printf("WRITING OUTFILE2 COMPLETE!\n");
//Close file.
fclose(out2);
// dealloc malloced memory.
for (i = 0; i < line_count; i++) {
free(array[i]);
}
free(array);

struct pointers to same memory address producing different data?

I have this simple code to read the lines of a file and store them in a struct:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct filedata {
char **items;
int lines;
};
struct filedata *read_file(char *filename) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("Can't read %s \n", filename);
exit(1);
}
char rbuff;
int nlines = 0; // amount of lines
int chr = 0; // character count
int maxlen = 0; // max line length (to create optimal buffer)
int minlen = 2; // min line length (ignores empty lines with just \n, etc)
while ((rbuff = fgetc(file) - 0) != EOF) {
if (rbuff == '\n') {
if (chr > maxlen) {
maxlen = chr + 1;
}
if (chr > minlen) {
nlines++;
}
chr = 0;
}
else {
chr++;
}
}
struct filedata *rdata = malloc(sizeof(struct filedata));
rdata->lines = nlines;
printf("lines: %d\nmax string len: %d\n\n", nlines, maxlen);
rewind(file);
char *list[nlines];
int buffsize = maxlen * sizeof(char);
char buff[buffsize];
int i = 0;
while (fgets(buff, buffsize, file)) {
if (strlen(buff) > minlen) {
list[i] = malloc(strlen(buff) * sizeof(char) + 1);
strcpy(list[i], buff);
i++;
}
}
rdata->items = (char **)list;
fclose(file);
int c = 0;
for (c; c < rdata->lines; c++) {
printf("line %d: %s\n", c + 1, rdata->items[c]);
}
printf("\n");
return rdata;
}
int main(void) {
char fname[] = "test.txt";
struct filedata *ptr = read_file(fname);
int c = 0;
for (c; c < ptr->lines; c++) {
printf("line %d: %s\n", c + 1, ptr->items[c]);
}
return 0;
}
This is the output when I run it:
lines: 2
max string len: 6
line 1: hello
line 2: world
line 1: hello
line 2: H��
For some reason when it reaches the second index in ptr->items, it prints gibberish output. But yet, if I throw some printf()'s in there to show the pointer addresses, they're exactly the same.
Valgrind also prints this when iterating over the char array the second time:
==3777== Invalid read of size 8
==3777== at 0x400AB3: main (test.c:81)
==3777== Address 0xfff000540 is on thread 1's stack
==3777== 240 bytes below stack pointer
But that really doesn't give me any clues in this case.
I'm using gcc 4.9.4 with glibc-2.24 if that matters.
list is an non-static local variable and using it after exiting its scope (returning from read_file in this case) will invoke undefined behavior because it will vanish on exiting its scope. Allocate it dynamically (typically on the heap) like
char **list = malloc(sizeof(char*) * nlines);
Adding code to check if malloc()s are successful will make your code better.
The variable list is local to read_file, but you store a pointer to list in rdata->items. When read_file returns, rdata->items is a dangling pointer, and accessing it is undefined behavior.

Reading each line of file into array

I'm reading a file and want to put each line into a string in an array. The length of the file is arbitrary and the length of each line is arbitrary (albeit assume it will be less than 100 characters).
Here's what I've got and it's not compiling. Essentially this is an array to an array of characters, right? So shouldn't it be char** words = (**char)malloc(sizeof(*char));?
#include <stdio.h>
#include <stdlib.h>
int main(){
int BUFSIZE = 32767;//max number of lines to read
char** words = (**char)malloc(sizeof(*char));//gives error: expected expression before 'char'
FILE *fp = fopen("coll.txt", "r");
if (fp == 0){
fprintf(stderr, "Error opening file");
exit(1);
}
int i = 0;
words[i] = malloc(BUFSIZE);
while(fscanf(fp, "%100s", words[i]) == 1)//no line will be longer than 100
{
i++;
words[i] = realloc(words, sizeof(char*)*i);
}
int j;
for(j = 0; j < i; j++)
printf("%s\n", words);
return 0;
}
Note: I've read "Reading from a file and storing in array" but it doesn't answer my question.
There are a few issues with your program. The realloc() statement is not used correctly. I also prefer fgets() for getting a line. Here is my solution. This also uses realloc() to increase the allocation of the buffer lines so that you neither have to know the number of lines in advance nor do you have to read the file in two passes (faster that way). This is a common technique to use when you don't know how much memory you'll have to allocate in advance.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int lines_allocated = 128;
int max_line_len = 100;
/* Allocate lines of text */
char **words = (char **)malloc(sizeof(char*)*lines_allocated);
if (words==NULL)
{
fprintf(stderr,"Out of memory (1).\n");
exit(1);
}
FILE *fp = fopen("coll.txt", "r");
if (fp == NULL)
{
fprintf(stderr,"Error opening file.\n");
exit(2);
}
int i;
for (i=0;1;i++)
{
int j;
/* Have we gone over our line allocation? */
if (i >= lines_allocated)
{
int new_size;
/* Double our allocation and re-allocate */
new_size = lines_allocated*2;
words = (char **)realloc(words,sizeof(char*)*new_size);
if (words==NULL)
{
fprintf(stderr,"Out of memory.\n");
exit(3);
}
lines_allocated = new_size;
}
/* Allocate space for the next line */
words[i] = malloc(max_line_len);
if (words[i]==NULL)
{
fprintf(stderr,"Out of memory (3).\n");
exit(4);
}
if (fgets(words[i],max_line_len-1,fp)==NULL)
break;
/* Get rid of CR or LF at end of line */
for (j=strlen(words[i])-1;j>=0 && (words[i][j]=='\n' || words[i][j]=='\r');j--)
;
words[i][j+1]='\0';
}
/* Close file */
fclose(fp);
int j;
for(j = 0; j < i; j++)
printf("%s\n", words[j]);
/* Good practice to free memory */
for (;i>=0;i--)
free(words[i]);
free(words);
return 0;
}
You should change the line:
char** words = (**char)malloc(sizeof(*char));
into this:
char** words=(char **)malloc(sizeof(char *)*Max_Lines);

Resources