Unexpected Segfault - What am I doing wrong - c

I've been trying to blow the cobwebs off my C programming skills, and I've been getting an error I can't seem to figure out. This program reads in a list of integers separated by newlines. This bit happens in read_integer_file... I have no issues going through the input there. It's when I pass the data back to main via out that I have the problem.
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int* out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%i\n");
num_lines++;
}
/* seek to the beginning of the file*/
rewind(file);
out = malloc(sizeof(int)*num_lines);
if(out == NULL)
return 0;
int inp = 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%i\n", &inp);
out[i] = inp;
printf("%i\n", out[i]); /* <---- Prints fine here! */
i++;
}
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int* numbers = NULL;
int number_count = read_integer_file(array_filename, numbers);
for(int i = 0; i < number_count; i++)
{
/* Segfault HERE */
printf("%i\n", numbers[i]);
}
}

You have not allocated any memory for numbers. Currently it is pointing to no where. When it gets back to the calling function it is still pointed to nowhere. Pass a pointer to a pointer to the function to allocate it within the function.
int read_integer_file(char* filename, int** out)
{
...
*out = malloc(sizeof(int)*num_lines);
...
int number_count = read_integer_file(array_filename, &numbers);

This is a version of your code working.. Keep in mind also that fscanf just skip the \n the way you wrote it so it's like writing fscanf(file, "%d");
And if you don't put a variable to handle what it reads the compiler may not see it but you'll probably get an error..
So here is the code :
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int **out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
int garbi;
char garbc;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%d", &garbi);
fscanf(file, "%c", &garbc);
if (garbc=='\n') ++num_lines;
}
/* seek to the beginning of the file*/
rewind(file);
int *nbr = malloc(sizeof(int)*num_lines);
if(nbr == NULL)
return 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%d", &nbr[i++]);
fscanf(file, "%c", &garbc);
}
*out=nbr;
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int *numbers = NULL;
int number_count = read_integer_file(array_filename, &numbers);
int i;
for(i = 0; i < number_count; ++i)
printf("%d\n", numbers[i]);
return 0;
}

Related

string of undetermined length c

Hi I was trying to create an array of string of an undetermined length in c.
This is my code :
int main()
{
int lineCount=linesCount();
char text[lineCount][10];
printf("%d",lineCount);
FILE * fpointer = fopen("test.txt","r");
fgets(text,10,fpointer);
fclose(fpointer);
printf("%s",text);
return 0;
}
I would like to replace 10 in
char text[lineCount][10];
My code reads out a file I already made the amount of lines dynamic.
Since the line length is unpredictable I would like to replace 10 by a something dynamic.
Thanks in advance.
To do this cleanly, we want a char * array rather than an 2D char array:
char *text[lineCount];
And, we need to use memory from the heap to store the individual lines.
Also, don't "hardwire" so called "magic" numbers like 10. Use an enum or #define (e.g) #define MAXWID 10. Note that with the solution below, we obviate the need for using the magic number at all.
Also, note the use of sizeof(buf) below instead of a magic number.
And, we want [separate] loops when reading and printing.
Anyway, here's the refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
linesCount(void)
{
return 23;
}
int
main(void)
{
int lineCount = linesCount();
char *text[lineCount];
char buf[10000];
printf("%d", lineCount);
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
// store line -- we must allocate this
text[i++] = strdup(buf);
}
fclose(fpointer);
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
return 0;
}
UPDATE:
The above code is derived from your original code. But, it assumes that the linesCount function can predict the number of lines. And, it doesn't check against overflow of the fixed length text array.
Here is a more generalized version that will allow an arbitrary number of lines with varying line lengths:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int lineCount = 0;
char **text = NULL;
char buf[10000];
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
++lineCount;
// increase number of lines in array
text = realloc(text,sizeof(*text) * lineCount);
if (text == NULL) {
perror("realloc");
exit(1);
}
// store line -- we must allocate this
text[lineCount - 1] = strdup(buf);
}
fclose(fpointer);
// print the lines
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
// more processing ...
// free the lines
for (i = 0; i < lineCount; ++i)
free(text[i]);
// free the list of lines
free(text);
return 0;
}

Handling file reading in c

I'm having a problem with this program. I'm trying to send the pointer to the beginning of a file. It usually works but, when I send the file from one function to another, then fgets gets and empty string rather than the first row in the file.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int checkf(FILE *file, char*id){
char row[255];
int line_num = 1;
int find_result = 0;
char temp[255];
while (fgets(temp, 255, file) != NULL){ // here i get an Empty 'temp'
// so the contition is always false
if((strstr(temp, id)) != NULL) {
rewind(file);
for (int i=1; i<(line_num-1); i++) {
fgets(row, 255, file);
}
for (int i=0; i<4; i++) {
fgets(row, 255, file);
choppy(row);
printf("%s",row);
if (i!=3) {
printf(" ");
}
}
find_result++;
}
line_num++;
}
return find_result;
}
void add(FILE *file, char fileName[20]){
int check;
char name[100], id[100] ;
scanf("%s",name);
scanf("%s",id);
check = checkf(file,id);
if(check==0){
fputs("\n",file);
fputs(name,file);
}
}
int main(int argc, char * argv[]) {
// insert code here...
FILE *file;
FILE *file_app;
file_app= fopen(argv[argc-1], "a");
file= fopen(argv[argc-1],"r");
//check the there is a file
if (file== NULL)
{
printf("Can't open file");
return 1;
}
else
{
int cmd= strcmp(argv[1],"add");
if (cmd==0) add(file_app,argv[2]);
fclose(file);
printf("\n");
return 0;
}
}
So in conclusion, I think that when I the function checkf() is called from function add(), the file pointer gets lost. But, when I use checks() directly it works. Any ideas?

How to allocate memory for lines of a file in C?

I have created functions that are supposed to find the number of lines in a file (find_numlines()) and a function to read the lines of the file into char*** lines (read_lines()). The rest of the functions in my main were provided so the problems are not in those functions.
read_lines.c (UPDATED):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "read_lines.h"
int findnum_lines(FILE* fp){
int num_lines = 0;
int line;
line = getc(fp);
if (line != EOF) {
num_lines++;
do {
if (line == '\n') {
num_lines = num_lines + 1;
}
line = getc(fp);
}
while (line != EOF);
}
rewind(fp);
return num_lines;
}
void read_lines(FILE* fp, char*** lines, int* num_lines){
int i;
(*lines) = malloc(*num_lines * sizeof(char*));
for (i=0; i < *num_lines; i++)
{
(*lines)[i] = malloc(1000);
(*lines)[i][0] = '\0';
fgets((*lines)[i], 1000, fp);
}
}
main.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "read_lines.h"
void print_lines(char** lines, int num_lines){
int i;
for(i = 0 ; i < num_lines; ++i){
printf("%d. %s", i+1, lines[i]);
}
}
void free_lines(char** lines, int num_lines){
int i;
for(i = 0 ; i < num_lines; ++i){
free(lines[i]);
}
if(lines != NULL && num_lines > 0){
free(lines);
}
}
FILE* validate_input(int argc, char* argv[]){
FILE* fp = NULL;
if(argc < 2){
printf("Not enough arguments entered.\nEnding program.\n");
exit(0);
}
else if(argc > 2){
printf("Too many arguments entered.\nEnding program.\n");
exit(0);
}
fp = fopen(argv[1], "r");
if(fp == NULL){
perror("fopen");
printf("Unable to open file: %s\nEnding program.\n", argv[1]);
//fprintf(stderr, "Unable to open file %s: %s\n", argv[1], strerror(errno));
exit(0);
}
return fp;
}
int main(int argc, char* argv[]){
char** lines = NULL;
int num_lines = 0;
FILE* fp = validate_input(argc, argv);
num_lines = findnum_lines(fp);
read_lines(fp, &lines, &num_lines);
print_lines(lines, num_lines);
free_lines(lines, num_lines);
fclose(fp);
return 0;
}
read_lines.h :
#ifndef READ_LINES
#define READ_LINES
#include <stdio.h>
void read_lines(FILE* fp, char*** lines, int* num_lines);
int findnum_lines(FILE* fp);
#endif
Whenever I input a file the find_numlines() returns the correct number of lines but something goes wrong in the read_lines() because lines is still NULL.
The example file is normal.txt :
Hello Class
This is what I would call a normal file
It isn't very special
But it still is important
The ouptut should be:
1. Hello Class
2. This is what I would call a normal file
3. It isn't very special
4. But it still is important
In the following code I added the rewind command (mentioned by xing) and the memory allocation for each line and the "line table". Further improvements were performed in the code for counting the lines and the error handling.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int findnum_lines(FILE* fp){
int num_lines = 0;
int c;
c = getc(fp);
if (c != EOF) {
num_lines++;
do {
if (c == '\n') {
num_lines = num_lines + 1;
}
c = getc(fp);
}
while (c != EOF);
}
rewind(fp);
return num_lines;
}
void read_lines(FILE* fp, char*** lines, int* num_lines){
int i;
// allocate memory for pointers to start of lines
(*lines) = malloc(*num_lines * sizeof(char*));
for (i=0; i < *num_lines; i++)
{
(*lines)[i] = malloc(1000);
(*lines)[i][0] = '\0'; // terminate for the case that last line does not contain characters
fgets((*lines)[i], 1000, fp); // read up to 999 characters and terminate string
}
}
void print_lines(char** lines, int num_lines){
int i;
for(i = 0 ; i < num_lines; ++i){
printf("%d. %s", i+1, lines[i]);
}
printf("\n");
}
void free_lines(char** lines, int num_lines){
int i;
for (i = 0 ; i < num_lines; ++i) {
if (lines[i]!=NULL) {
free(lines[i]);
}
}
if (lines != NULL){
free(lines);
}
}
FILE* validate_input(int argc, char* argv[]){
FILE* fp = NULL;
if (argc < 2){
printf("Not enough arguments entered.\n");
}
else if (argc > 2){
printf("Too many arguments entered.\n");
}
else {
fp = fopen(argv[1], "r");
if (fp == NULL){
printf("Unable to open file: %s\n", argv[1]);
}
}
return fp;
}
int main(int argc, char* argv[]){
char** lines = NULL;
int num_lines = 0;
FILE* fp = validate_input(argc, argv);
if (fp != NULL)
{
num_lines = findnum_lines(fp);
read_lines(fp, &lines, &num_lines);
print_lines(lines, num_lines);
free_lines(lines, num_lines);
fclose(fp);
}
return 0;
}

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.

Seg fault from within my print function after reading in a file in c

I have an unknown segfault within my print function when I call it in main and I can't see what the obvious fix is. I have put printf's throughout the program and it doesn't print 'here4' making me think it's due to my print function, or when I call it in main.
I want to read a dictionary file into an array of strings.
Here is a snippet of the code:
Any ideas would be greatly appreciated, thanks.
#define PRIME 1009
void fileRead(int argc, char **argv)
void printTable(int arrayLength, char **table);
int main(int argc, char **argv)
{
char **table;
FILE *fp;
int i, arrayLength = PRIME;
/* Initial memory allocation */
table = (char**)malloc(PRIME*sizeof(char));
fileRead(argc, argv);
printf("here3\n");
for(i = 0; i < arrayLength; i++) {
printTable(arrayLength,table);
}
printf("here4\n");
return 0;
}
void fileRead(int argc, char **argv)
{
FILE *fp;
char *word;
int arrayLength = PRIME;
word = calloc(MAXCHAR, sizeof(char));
fp = fopen (argv[1], "r");
printf("here1\n");
/*read in grid and move along a cell each time */
while (fscanf(fp, "%s", word)!= EOF) {
if (argc != (2)) {
fprintf(stderr, "Cannot open file, %s\n Try again e.g. %s dictionary.txt\n" , argv[1], argv[0]);
}
if(fp == NULL) {
fprintf(stderr, "Cannot open file, %s\n Try again e.g. %s dictionary.txt\n" , argv[1], argv[0]);
return;
}
if (fp == NULL) {
fprintf(stderr, "Error opening file, try file name dictionary.txt\n");
exit(EXIT_FAILURE);
}
}
printf("here2\n");
fclose(fp);
return;
}
void printTable(int arrayLength, char **table)
{
int i;
for(i = 0; i < arrayLength; i++) {
printf("%s\n", table[i]);
}
printf("\n");
}
Let me summarize your code:
you allocate uninitialized memory for table
You call a function fileRead():
Allocate some memory for word
read the file
Do nothing with the data read.
fileRead() does nothing useful: It does not return anything, it doesn't touch table, is vulnerable to a buffer overflow of word and leaves the memory leak of word behind.
And then you printf the unchanged and uninitialized content of table
try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PRIME 1009
#define MAXCHAR 256
char **fileRead(FILE *fp, int *len);
void printTable(int arrayLength, char **table);
int main(int argc, char **argv){
if (argc != 2) {
fprintf(stderr, "Need dictionary file argument.\nTry again e.g. %s dictionary.txt\n" , argv[0]);
exit(EXIT_FAILURE);
}
FILE *fp = fopen (argv[1], "r");
if(fp == NULL) {
fprintf(stderr, "Cannot open file, %s\nTry again e.g. %s dictionary.txt\n" , argv[1], argv[0]);
exit(EXIT_FAILURE);
}
int arrayLength = PRIME;
char **table = fileRead(fp, &arrayLength);//fclose(fp) inside this
printTable(arrayLength, table);
for(int i = 0; i < arrayLength; ++i)
free(table[i]);
free(table);
return 0;
}
char **fileRead(FILE *fp, int *len){
char *word = calloc(MAXCHAR, sizeof(char));
char **table = malloc(*len * sizeof(char*));
int i = 0;
while (i < *len && fscanf(fp, "%s", word) != EOF){
table[i] = malloc(strlen(word)+1);
strcpy(table[i++], word);
}
fclose(fp);
*len = i;
free(word);
return table;
}
void printTable(int arrayLength, char **table){
int i;
for(i = 0; i < arrayLength; i++) {
printf("%s\n", table[i]);
}
printf("\n");
}

Resources