Reading from a file into an array of chars - c

I'm trying to read a list of strings from a file to an array.
in file it looks like this
ItemOne
ItemTwo
ItemThree etc.
I declared an array as:
char** array;
and file as:
FILE *read;
This is what I came up with:
{
i = 0;
printf("Type in the name of the file\n");
scanf("%s", &name);
read = fopen(name, "r");
if (read == NULL)
{
perror("Doesn't work");
return 1;
}
else
{
array = malloc(100 * sizeof(*array));
while (!feof(read))
{
array[i] = malloc(32 * sizeof(*array[i]));
fscanf(read, "%s", &array[i]);
i++;
}
}
}
Tt compiles, but when I try to display the array it's empty. Any ideas?

while (!feof(read))
{
array[i] = malloc(32 * sizeof(*array[i]));
fscanf(read, "%s", array[i]); //You should pass a pointer to a pointer to array of chars
i++;
}
I hope it'll work...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long GetFileSize(FILE *fp){
long fsize = 0;
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
fseek(fp,0,SEEK_SET);//reset stream position!!
return fsize;
}
char *ReadToEnd(const char *filepath){
FILE *fp;
long fsize;
char *buff;
if(NULL==(fp=fopen(filepath, "rb"))){
perror("file cannot open at ReadToEnd\n");
return NULL;
}
fsize=GetFileSize(fp);
buff=(char*)malloc(sizeof(char)*fsize+1);
fread(buff, sizeof(char), fsize, fp);
fclose(fp);
buff[fsize]='\0';
return buff;
}
char** split(const char *str, const char *delimiter, size_t *len){
char *text, *p, *first, **array;
int c;
char** ret;
*len = 0;
text=strdup(str);
if(text==NULL) return NULL;
for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
if(c==0) first=p; //first token top
ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
if(ret==NULL){
free(text);
return NULL;
}
strcpy(text, str+(first-text));//skip until top token
array=ret;
for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
*array++=strdup(p);
}
*array=NULL;
*len=c;
free(text);
return ret;
}
void free4split(char** sa){
char **array=sa;
if(sa!=NULL){
while(*sa)
free(*sa++);//for string
free(array); //for array
}
}
int main(){
char *text, **lines;
size_t line_count;
text=ReadToEnd("data.txt");
lines=split(text, "\r\n", &line_count);
free(text);
{ //test print
int i;
for(i=0;i<line_count;++i)
printf("%s\n", lines[i]);
}
free4split(lines);
return 0;
}

Related

adding char into an array and returning

Im new to c and am trying to understand pointers.
here I am opening a file and reading the lines given. Im trying to append these lines into an array and return it from the function. I dont seem to be appending or accessing the array correctly. output[count] = status; gives an error with mismatched char and char *.
Im essentially trying to get an array with a list of words given by a file where each element in the array is a word.
char *fileRead(char *command, char output[255]) {
int count = 0;
char input[255];
char *status;
FILE *file = fopen(command, "r");
if (file == NULL) {
printf("Cannot open file\n");
} else {
do {
status = fgets(input, sizeof(input), file);
if (status != NULL) {
printf("%s", status);
strtok(status, "\n");
// add values into output array
output[count] = status;
++count;
}
} while (status);
}
fclose(file);
return output;
}
I access fileRead via:
...
char commandArray[255];
char output[255];
int y = 0;
char *filename = "scriptin.txt";
strcpy(commandArray, fileRead(filename, output));
// read from array and pass into flag function
while (commandArray[y] != NULL) {
n = flagsfunction(flags, commandArray[y], sizeof(buf), flags.position, &desc, &parentrd, right, left, lconn);
y++;
...
Example of Read from file Line by line then storing nonblank lines into an array (array of pointer to char (as char*))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//for it does not exist because strdup is not a standard function.
char *strdup(const char *str){
char *ret = malloc(strlen(str)+1);
if(ret)
strcpy(ret, str);
return ret;
}
//Read rows up to 255 rows
int fileRead(const char *filename, char *output[255]) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("Cannot open file:");
return 0;
}
int count = 0;
char input[255];
while(count < 255 && fgets(input, sizeof(input), file)) {
char *line = strtok(input, "\n");
if(line)//When it is not a blank line
output[count++] = strdup(line);//Store replica
}
fclose(file);
return count;
}
int main(void){
char *output[255];//(`char *` x 255)
int number_of_read_line = fileRead("data.txt", output);
for(int i = 0; i < number_of_read_line; ++i){
printf("%s\n", output[i]);
free(output[i]);//Discard after being used
}
return 0;
}

Reading lines from file

I am trying to read strings and integers from a simple text file to my array. But the problem is that I get some random characters in a line in the middle of my list. It probably has to do with a newline problem, but I am not sure. The text file looks like this:
4
Mr Tambourine Man
Bob Dylan
1965
Dead Ringer for Love
Meat Loaf
1981
Euphoria
Loreen
2012
Love Me Now
John Legend
2016
The first number (4), indicates how many songs there are in the list. I have made a struct which will be able to hold the songs and dynamically allocate memory for each pointer.
Struct:
typedef struct Song {
char *song;
char *artist;
int *year;
} Song;
Allocated:
Song *arr;
arr = (Song*)malloc(sizeof(Song));
Function:
int loadFile(char fileName[], Song *arr, int nrOf) {
FILE *input = fopen(fileName, "r");
if (input == NULL) {
printf("Error, the file could not load!\n");
} else {
int i = 0;
fscanf(input, "%d\n", &nrOf);
for (int i = 0; i < nrOf; i++) {
arr[i].song = (char*)malloc(sizeof(char));
arr[i].artist = (char*)malloc(sizeof(char));
arr[i].year = (int*)malloc(sizeof(int));
fgets(arr[i].song, 100, input);
fgets(arr[i].artist, 100, input);
fscanf(input, "%d\n", arr[i].year);
}
printf("The file is now ready.\n");
fclose(input);
}
return nrOf;
}
Are you able to find the problem? Or do you have a better solution?
This is wrong:
arr[i].song = (char*)malloc(sizeof(char));
arr[i].artist = (char*)malloc(sizeof(char));
You are only allocating buffers of size 1, there's no scaling. This gives you undefined behavior when you overrun the buffers by loading more data into them than they can hold.
I would expect those to read:
arr[i].song = malloc(100);
and so on. Note that no cast is necessary, and sizeof (char) is always 1.
Also, this:
arr[i].year = (int*)malloc(sizeof(int));
is super-strange. There's absolutely no reason to dynamically allocate a single integer, just make the field an int and store the value there directly.
First Issue:
arr[i].song = (char*)malloc(sizeof(char));
arr[i].artist = (char*)malloc(sizeof(char));
Are only allocating 1 byte for your char* pointers, song and artist. You can allocate a size for this:
arr[i].song = (char*)malloc(100 * sizeof(char)); /* or malloc(100) */
arr[i].artist = (char*)malloc(100 * sizeof(char));
Or you can simply malloc() enough space from you buffer:
char buffer[100];
fgets(buffer, 100, input);
/* check for failure, remove newline */
arr[i].song = malloc(strlen(buffer)+1);
/* check error from malloc */
strcpy(arr[i].song, buffer);
Or even use strdup():
arr[i].song = strdup(buffer);
Which is a substitute for malloc()/strcpy().
Note: You can also read Do I cast the result of malloc?.
Second Issue:
Your current struct:
typedef struct Song {
char *song;
char *artist;
int *year;
} Song;
Can be simplified to:
typedef struct {
char *song;
char *artist;
int year;
} Song;
Because year does not need to be a pointer. Easier to manage if its just an int. This avoids having to do allocations like:
arr[i].year = (int*)malloc(sizeof(int));
Other Recommendations:
You should check the return of fscanf() and fgets() as its safe to do this. It helps just incase your file will have incorrect data. This goes the same for malloc(), which can return NULL is unsuccessfully allocated on the heap.
Here is some code with the above considerations in mind:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct {
char *song;
char *artist;
int year;
} Song;
Song *create_array(FILE *input, int *nrof);
void load_data(Song *arr, FILE *input, int nrof);
void print_free_data(Song *arr, int nrof);
void get_buffer(char buffer[], FILE *input);
int main(void) {
FILE *input;
Song *arr;
int nrof;
input = fopen("artist.txt", "r");
if (input == NULL) {
fprintf(stderr, "Error reading file\n");
exit(EXIT_FAILURE);
}
arr = create_array(input, &nrof);
load_data(arr, input, nrof);
print_free_data(arr, nrof);
fclose(input);
return 0;
}
Song *create_array(FILE *input, int *nrof) {
Song *arr;
if (fscanf(input, "%d ", nrof) != 1) {
fprintf(stderr, "Cannot find number of songs\n");
exit(EXIT_FAILURE);
}
arr = malloc(*nrof * sizeof(*arr));
if (arr == NULL) {
fprintf(stderr, "Cannot allocate %d spaces for array\n", *nrof);
exit(EXIT_FAILURE);
}
return arr;
}
void load_data(Song *arr, FILE *input, int nrof) {
char buffer[SIZE];
for (int i = 0; i < nrof; i++) {
get_buffer(buffer, input);
arr[i].song = malloc(strlen(buffer)+1);
if (arr[i].song == NULL) {
fprintf(stderr, "Cannot allocate song\n");
exit(EXIT_FAILURE);
}
strcpy(arr[i].song, buffer);
get_buffer(buffer, input);
arr[i].artist = malloc(strlen(buffer)+1);
if (arr[i].artist == NULL) {
fprintf(stderr, "Cannot allocate artist\n");
exit(EXIT_FAILURE);
}
strcpy(arr[i].artist, buffer);
if (fscanf(input, "%d ", &arr[i].year) != 1) {
fprintf(stderr, "Cannot find year for Song: %s Album: %s\n",
arr[i].song, arr[i].artist);
exit(EXIT_FAILURE);
}
}
}
void get_buffer(char buffer[], FILE *input) {
size_t slen;
if (fgets(buffer, SIZE, input) == NULL) {
fprintf(stderr, "Error from fgets(), line not read\n");
exit(EXIT_FAILURE);
}
slen = strlen(buffer);
if (slen > 0 && buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
fprintf(stderr, "Too many characters entered\n");
exit(EXIT_FAILURE);
}
}
void print_free_data(Song *arr, int nrof) {
for (int i = 0; i < nrof; i++) {
printf("%s\n%s\n%d\n\n", arr[i].song, arr[i].artist, arr[i].year);
free(arr[i].song);
arr[i].song = NULL;
free(arr[i].artist);
arr[i].artist = NULL;
}
free(arr);
arr = NULL;
}
Which Outputs correct data:
Mr Tambourine Man
Bob Dylan
1965
Dead Ringer for Love
Meat Loaf
1981
Euphoria
Loreen
2012
Love Me Now
John Legend
2016
Your memory allocation is incorrect. The structure should have char arrays for the song and artist names and an int for the year, and you should modify your API to return the array and its size to the caller:
int loadFile(const char *fileName, Song **arr, int *numberp);
Here is a corrected and simplified of your program:
#include <stdio.h>
#include <stdlib.h>
typedef struct Song {
char song[100];
char artist[100];
int year;
} Song;
/* call as
if (loadFile(fileName, &songs, &songs_size) < 0) {
// deal with error...
}
*/
int loadFile(const char *fileName, Song **arrp, int *numberp) {
FILE *input;
Song *arr;
int i, nrOf;
input = fopen(fileName, "r");
if (input == NULL) {
fprintf(stderr, "Cannot open file %s\n", filename);
return -1;
} else {
if (fscanf(input, "%d\n", &nrOf) != 1) {
fprintf(stderr, "%s: missing number of items\n", filename);
fclose(intput);
return -1;
}
arr = calloc(sizeof(*arr), nrOf);
if (arr == NULL) {
fprintf(stderr, "cannot allocate memory for %d items\n", nrOf);
fclose(intput);
return -1;
}
for (int i = 0; i < nrOf; i++) {
char cc;
if (fscanf(input, "%99[^\n]%*c%99[^\n]%*c%d%c",
sarr[i].song, arr[i].artist,
&arr[i].year, &cc) != 4 || cc != '\n') {
fprintf(stderr, "%s: invalid format for item %d\n",
filename, i);
break;
}
}
printf("The file is now ready.\n");
fclose(input);
*arrp = arr;
*numberp = i;
return i;
}
}

Read from a text file and use each line to compare if they are anagrams

I must modify my program to accept input from
a file called anagrams.txt.This file should have two strings per line, separated by the # character. My program should read
each pair of strings and report back if each pair of strings is an anagram. For example consider the following content of anagrams.txt:
hello#elloh
man#nam
Astro#Oastrrasd
Your program should print out the following:
hello#elloh - Anagrams!
man#nam - Anagrams!
Astro#Oastrrasd- Not anagrams!
I should compile in g++
Here is the code to read from text:
int main()
{
char input[30];
if(access( "anagrams.txt", F_OK ) != -1) {
FILE *ptr_file;
char buf[1000];
ptr_file =fopen("anagrams.txt","r"); if (!ptr_file)
return 1;
while (fgets(buf,1000, ptr_file)!=NULL)
printf("%s",buf);
fclose(ptr_file);
printf("\n");
}
else{ //if file does not exist
printf("\nFile not found!\n");
}
return 0;
}
Code to find if the text are anagrams:
#include <stdio.h>
int find_anagram(char [], char []);
int main()
{
char array1[100], array2[100];
int flag;
printf("Enter the string\n");
gets(array1);
printf("Enter another string\n");
gets(array2);
flag = find_anagram(array1, array2);
if (flag == 1)
printf(" %s and %s are anagrams.\n", array1, array2);
else
printf("%s and %s are not anagrams.\n", array1, array2);
return 0;
}
int find_anagram(char array1[], char array2[])
{
int num1[26] = {0}, num2[26] = {0}, i = 0;
while (array1[i] != '\0')
{
num1[array1[i] - 'a']++;
i++;
}
i = 0;
while (array2[i] != '\0')
{
num2[array2[i] -'a']++;
i++;
}
for (i = 0; i < 26; i++)
{
if (num1[i] != num2[i])
return 0;
}
return 1;
}
You can try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXLINE 1000
#define MAXLETTER 256
int is_anagram(char *word1, char *word2);
void check_lines(FILE *filename);
int cmpfunc(const void *a, const void *b);
void convert_to_lowercase(char *word);
int
main(int argc, char const *argv[]) {
FILE *filename;
if ((filename = fopen("anagram.txt", "r")) == NULL) {
fprintf(stderr, "Error opening file\n");
exit(EXIT_FAILURE);
}
check_lines(filename);
fclose(filename);
return 0;
}
void
check_lines(FILE *filename) {
char line[MAXLINE];
char *word1, *word2, *copy1, *copy2;
while (fgets(line, MAXLINE, filename) != NULL) {
word1 = strtok(line, "#");
word2 = strtok(NULL, "\n");
copy1 = strdup(word1);
copy2 = strdup(word2);
convert_to_lowercase(copy1);
convert_to_lowercase(copy2);
if (is_anagram(copy1, copy2)) {
printf("%s#%s - Anagrams!\n", word1, word2);
} else {
printf("%s#%s - Not Anagrams!\n", word1, word2);
}
}
}
void
convert_to_lowercase(char *word) {
int i;
for (i = 0; word[i] != '\0'; i++) {
word[i] = tolower(word[i]);
}
}
int
is_anagram(char *word1, char *word2) {
qsort(word1, strlen(word1), sizeof(*word1), cmpfunc);
qsort(word2, strlen(word2), sizeof(*word2), cmpfunc);
if (strcmp(word1, word2) == 0) {
return 1;
}
return 0;
}
int
cmpfunc(const void *a, const void *b) {
if ((*(char*)a) < (*(char*)b)) {
return -1;
}
if ((*(char*)a) > (*(char*)b)) {
return +1;
}
return 0;
}
Since this looks like a University question, I won't provide a full solution, only a hint.
All you have to do is replace the stdin input part of the anagram-finding file with the code you wrote to read from a file: it's as simple as changing
printf("Enter the string\n");
gets(array1);
printf("Enter another string\n");
gets(array2);
to
// before program:
#define SIZE 1000
// inside main
if (access("anagrams.txt", F_OK) == -1){
printf("\nFile not found!\n");
return 1; // Abort the program early if we can't find the file
}
FILE *ptr_file;
char buf[1000];
ptr_file = fopen("anagrams.txt","r");
if (!ptr_file)
return 1;
char array1[SIZE], array2[SIZE];
while (fgets(buf, 1000, ptr_file)!=NULL){
// do all your anagram stuff here!
// there is currently one line of the input file stored in buf
// Hint: You need to split buf into array_1 and array_2 using '#' to separate it.
}
fclose(ptr_file);
printf("\n");
Additional comments:
Don't ever ever ever use gets. gets doesn't check that the string it writes to can hold the data, which will cause your program to crash if it gets input bigger than the array size. Use fgets(buf, BUF_SIZE, stdin) instead.
Beautiful code is good code. People are more likely to help if they can read your code easily. (fix your brackets)
Just for interest, a more efficient algorithm for checking anagrams is to use qsort to sort both arrays, then a simple string matcher to compare them. This will have cost O(mnlog(m+n)), as opposed to O(m^2 n^2), awith the current algorithm
You need to split every line you read by fgets (as you did) in to two strings, and pass them to your find_anagram function. You can do that using strtok:
int main()
{
int flag;
char buf[1000];
FILE *ptr_file;
//Check file existence
//Open the file for reading
while (fgets (buf, 1000, ptr_file) != NULL)
{
char *array1 = strtok(buf, "#");
char *array2 = strtok(NULL, "\n");
flag = find_anagram (array1, array2);
//Check flag value to print your message
}
return 0;
}
//put your find_anagram function
Don't forget to #include <string.h> to use strtok().

How to use pointers to return 2D arrays functions?

So I have a function called scanCode which scans words from a text file and stores it in a 2D array. I then want to return this array into an array variable in the main function, this is my code so far
#include <stdio.h>
char **scanCode()
{
FILE *in_file;
int i = 0;
static char scan[9054][6];
in_file = fopen("message.txt", "r");
while (!feof(in_file))
{
fscanf(in_file, "%s", scan[i]);
i++;
}
return scan;
}
int main(void)
{
int hi[9053];
FILE *in_file;
in_file = fopen("message.txt", "r");
char **array = scanCode();
printf("%c", array[0]);
printf("%c", array[1]);
printf("%c", array[2]);
printf("%c", array[3]);
}
So basically the array returned from the scanCode function I want it to be stored in the char array in the main function.. after looking at a lot of questions and answers here, this is what I got to but the pointer etc is hard to understand for me.. could someone tell me what I did wrong here?
Change the return type of the function the following way
#include <stdio.h>
char ( *scanCode() )[6]
{
FILE *in_file;
int i = 0;
static char scan[9054][6];
in_file = fopen("message.txt", "r");
while (!feof(in_file))
{
fscanf(in_file, "%s", scan[i]);
i++;
}
return scan;
}
int main(void)
{
int hi[9053];
FILE *in_file;
in_file = fopen("message.txt", "r");
char ( *array )[6] = scanCode();
printf("%s", array[0]);
printf("%s", array[1]);
printf("%s", array[2]);
printf("%s", array[3]);
}
Also in the printf statements use format specifier %s
And change the loop in the function like
while ( i < 9054 && fscanf(in_file, "%5s", scan[i]) == 1 ) ++i;
I prefer to simplify the code in this way:
#include <stdio.h>
#define NumLines 9054
#define NumCols 6
void freeMem(char **ele) {
while (*ele != NULL) {
free(*ele);
ele++;
}
}
char **scanCode(char *fileName)
{
FILE *in_file;
char readingFormat[128];
int i = 0;
/*
* Instead to declare a static variable I prefer to allocate dynamically
* the bidimensional array.
* It is done in two steps:
* 1. allocate the memory for the first dimension
* 2. for each element in this dimension allocate the memory for each element in the second dimension
*
*/
char **scan = (char **)malloc((NumLines + 1) * sizeof(char *));
if (scan == NULL) {
return NULL;
}
for (int j = 0; j < NumLines; j++) {
scan[j] = (char *)malloc(NumCols + 1);
if (scan[j] == NULL) {
freeMem(scan);
return NULL;
}
scan[j][0] = NULL;
}
scan[NumLines] = NULL; // define the end of memory
in_file = fopen(fileName, "r");
if (fopen == NULL) {
freeMem(scan);
return NULL;
}
sprintf(readingFormat, "%%%ds", NumCols);
while (fscanf(in_file, readingFormat, scan[i]) == 1 && i < NumLines) {
i++;
}
return scan;
}
int main(void)
{
char **array = scanCode("message.txt");
if (array == NULL) {
printf("ERROR\n");
exit(0);
}
for (char **tp = array; **tp != NULL; tp++) {
printf("%s\n", *tp);
}
}
Arrays aren't pointers (hello from me again).
This:
static char scan[9054][6];
have the most obvious type you would expect it to be - 'char [9054][6]' and not 'char **'. It's spelled as an array of 6 elements each of which is another array of 9054 chars. On the other hand the type 'char **' is spelled as 'a pointer to pointer to char' and as you can probably see now they are entirely different things.
Your code should look something like this:
#include <stdio.h>
typedef char yourArrayType[9054][6];
typedef struct { yourArrayType return_value; } letsReturnArraysType;
letsReturnArraysType scanCode()
{
FILE *in_file;
int i = 0;
yourArrayType scan;
in_file = fopen("message.txt", "r");
while (!feof(in_file))
{
fscanf(in_file, "%s", scan[i]);
i++;
}
return *(letsReturnArraysType*)scan;
}
int main(void)
{
int hi[9053];
FILE *in_file;
in_file = fopen("message.txt", "r");
letsReturnArraysType arrayStruct = scanCode();
printf("%s", arrayStruct.return_value[0]);
printf("%s", arrayStruct.return_value[1]);
printf("%s", arrayStruct.return_value[2]);
printf("%s", arrayStruct.return_value[3]);
}

How to read each individual lines of a text file into their own individual variables

Hi guys I am in the second weekend of trying to find the solution to this problem. I am new at c programming and I have been trying to read each individual line of a text file and pass each of them to their own variable, where I will be able to manipulate them(such as compare them, do calculations etc).
I have a code to read each individual lines but I am unsure how to pass each line to a variable, here is the code:
#include <stdlib.h>
#include <stdio.h>
struct line_reader {
FILE *f;
char *buf;
size_t siz;
};
void
lr_init(struct line_reader *lr, FILE *f)
{
lr->f = f;
lr->buf = NULL;
lr->siz = 0;
}
char *
next_line(struct line_reader *lr, size_t *len)
{
size_t newsiz;
int c;
char *newbuf;
*len = 0;
for (;;) {
c = fgetc(lr->f);
if (ferror(lr->f))
return NULL;
if (c == EOF) {
if (*len == 0)
return NULL;
else
return lr->buf;
} else {
if (*len == lr->siz) {
newsiz = lr->siz + 4096;
newbuf = realloc(lr->buf, newsiz);
if (newbuf == NULL)
return NULL;
lr->buf = newbuf;
lr->siz = newsiz;
}
lr->buf[(*len)++] = c;
if (c == '\n')
return lr->buf;
}
}
}
void
lr_free(struct line_reader *lr)
{
free(lr->buf);
lr->buf = NULL;
lr->siz = 0;
}
int
main()
{
struct line_reader lr;
FILE *f;
size_t len;
char *line;
f = fopen("file.txt", "r");
if (f == NULL) {
perror("foobar.txt");
exit(1);
}
lr_init(&lr, f);
while (line = next_line(&lr, &len)) {
fputs("1: ", stdout);
fwrite(line, len, 1, stdout);
}
if (!feof(f)) {
perror("next_line");
exit(1);
}
lr_free(&lr);
return 0;
}
Any help would be appreciated.
What about using an array simply as a suggestion
e.g.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** readFile(const char *filename, size_t *lineCount){
FILE *fp;
char buff[4096];
size_t lines = 0, capacity=1024;
char **line;
if(NULL==(fp=fopen(filename, "r"))){
perror("file can't open.");
return NULL;
}
if(NULL==(line=(char**)malloc(sizeof(char*)*capacity))){
perror("can't memory allocate.");
fclose(fp);
return NULL;
}
while(NULL!=fgets(buff, sizeof(buff), fp)){
line[lines++] = strdup(buff);
if(lines == capacity){
capacity += 32;
if(NULL==(line=(char**)realloc(line, sizeof(char*)*capacity))){
perror("can't memory allocate.");
fclose(fp);
return NULL;
}
}
}
*lineCount = lines;
fclose(fp);
return (char**)realloc(line, sizeof(char*)*lines);
}
void freeMem(char** p, size_t size){
size_t i;
if(p==NULL) return;
for(i=0;i<size;++i)
free(p[i]);
free(p);
}
int main(){
size_t lines;
char **line;
if(NULL!=(line=readFile("file.txt", &lines))){//lines: set line count of file
printf("%s", line[25]);// 26th line of file, zero origin
}
freeMem(line, lines);
return 0;
}
On any POSIX-compliant system just use the m scan modifier:
for ( char *line, nl; scanf("%m[^\n]%c",&line,&nl) != EOF ; free(line) ) {
if ( !line )
strcpy(line=malloc(1),""), getchar();
// ...
}
m has been in the standard for five years now.

Resources