im trying out using malloc in array of characters by reading each word from that text file and putting it in a array so the array size is exact my problem is when i run the program it makes segmentation fault im not sure where the problem is and if i used the malloc right

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	char *buf;
	FILE *inputFile;
	inputFile = fopen("aa1.txt","r");
	int length = fread(buf, 1, sizeof(buf), inputFile);
	buf = (char *)malloc(length * sizeof(char));

	printf("%d",buf[1]);
	fclose(inputFile);	
	return 0;
}
WaltP commented: Sentences, please. Propper communication is important to understanding! -4

Recommended Answers

All 8 Replies

You're missing one vital line.

if (inputFile == NULL) {printf("File failed to open."); return 1;};

Your file fails to open, and there's where the fault comes in.

But there seem to be several other logical problems with this to accomplish your goal. I'm new myself though, so I don't want to send you in the wrong direction. I'll leave that to others.

>>int length = fread(buf, 1, sizeof(buf), inputFile);

That is not how you get the length of a file. First you have to call fseek() to move the file pointer to end-of-file, then call ftell() to get the file position.

ah tnx but is buf = (char *)malloc(length * sizeof(char)); the right way to use malloc for this problem im kinda new in using malloc

sizeof(char) is guaranteed to be 1, so you can remove that part of the expression. You should also add 1 for the null character at the end, otherwise your string will be limited to length-1 characters, which can be confusing.

p.s. Your code is quite broken. Here is a correction:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    FILE *in = fopen("test.txt", "r");

    if (in != NULL) {
        /* Strictly portable C does not mix declarations with code */
        long len;
        char *buf;

        /* This part is not portable for text mode streams */
        fseek(in, 0, SEEK_END);
        len = ftell(in);
        rewind(in);

        /* Note the lack of a cast */
        buf = malloc(len + 1);

        if (buf != NULL) {
            /* Make sure the string is terminated with '\0' */
            memset(buf, 0, len + 1);

            /* Block read and show the results */
            fread(buf, 1, len, in);
            fputs(buf, stdout);

            /* Clean up allocated resources */
            free(buf);
        }

        fclose(in);
    }

    return 0;
}

Narue is ALMOST correct. If you are going to use fread() then the file should be opened in binary mode, such as using "rb" instead of just "r" FILE *in = fopen("test.txt", "rb");

If you are going to use fread() then the file should be opened in binary mode

Bullshit. There's nothing about fread that requires a binary mode stream. Conceptually fread is nothing more than a convenient wrapper around a loop that uses fgetc.

No, the real issue with that program (as noted by a comment) is that the fseek/ftell trick for figuring file size is not portable except on binary mode streams. It tends to work on text mode streams, more or less, but even when it works there are sticking points.

For example, on one of my Windows compilers the fseek/ftell trick works on a text mode stream, but doesn't do newline conversions. This puts the count off by an extra byte for every newline in the file and was why I used memset instead of buf[len] = '\0' to ensure string termination.

AFAIK, there is no portable way to get the size of a file, because the standard library doesn't really have an abstraction for files per se (despite the standard FILE handle). Rather, it is all based on streams, which in principle can be of indefinite length. Files (as opposed to streams) are a system-dependent concept.

Also, I think we're overlooking something important. From my reading of the problem statement, the OP doesn't want a single array with all of the characters; instead, the problem statement calls for an array of words, or to be a bit more concrete, a pointer to a pointer to char ( char** ). The size of the array presents a problem, as even if you know how long the file is, it tells you nothing about the number of 'words' in it, except that it will be equal to or less than the file size. It also tells you nothing about the size of the individual words.

In other words, this is a tokenizing problem.

My recommendation is that, rather than an array of c-strings, you would be better off with a linked list, with each node holding a single char* for the given word. You would still need to read the file into a buffer, but it need not hold the entire file in memory at once; rather, you could buffer part of the file, then process that section to get the words in it (you've have to handle the edge case of when a word is cut into two parts when buffering, but that can be solved fairly easily). You could probably iterate over strtok() to get the individual words, though you may want to iterate over the buffer directly instead if you mean to get non-word tokens. The trickiest part would be getting the size of the individual tokens (remembering to add one for the delimiter), but that shouldn't be too hard.

AFAIK, there is no portable way to get the size of a file

Not without reading the entire file, at least. This is relatively portable:

size_t file_size(FILE *in)
{
    long save = ftell(in);
    size_t n = 0;
    int ch;

    rewind(in);

    while ((ch = fgetc(in)) != EOF)
        ++n;

    clearerr(in);
    fseek(in, save, SEEK_SET);

    return n;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.