Store strings from file into dynamically alocated array - c

I am reading words from a file, exact number 2243. And I am trying to store them inside array so I can read them later on the program. Code is inside function. The file doesn't have sentences, just words one below the other.
char** fill_word_array(char* filename){
int i = 0, j = 0;
int lines = 0;
char str[20];
char *array[i][j];
array[i][j] = malloc(lines * sizeof(char*));
FILE * fp = fopen("words.txt", "r");
if (fp == NULL)
{
printf("Cannot open file");
return 0;
}
while (fscanf(fp, "%s", str) != EOF)
{
lines++;
}
printf("%d\n", lines);
fseek(fp, 0, SEEK_SET);
array[i][j] = malloc(sizeof(char*) * lines);
for(i = 0; i <= lines; i++)
{
strcpy(array[lines][j], str);
printf("%s", array[i][j]);
}
return 0;
}
This code prints only the last word of the file as shown here http://tinypic.com/r/2zhjmgx/9.

A declaration like char *array[i][j] with i==0 and j==0 will reserve an array of size 0, such that even position array[0][0] is not legally accessible (undefined behaviour). So when you write array[i][j] = malloc(lines * sizeof(char*)), you already write to array[0][0] yielding UB.
Usually one gets punished by the community for providing the solution to somebody asking for help and thereby steeling him the chance to make the experiences on his own. For your maturity level, however, it seems to me that the exercise is to hard, and therefore I'll provide a solution following your approach and describe the things that are to consider.
Hope it helps.
With your approach you need to...
count the words
allocate space for "words * sizeof(char*)" +
one word to store a NULL-pointer at the end (otherwise the users
of your result will not know where to stop).
rewind and read in every word in a loop;
in the loop, make a copy of the temporary word content and store it in the array
after the loop, write the
final NULL-pointer.
return the array (and tell the user that he
will have to free memory later)
Here's the code:
char** fill_word_array(char* filename){
int words = 0;
char str[100];
char **array;
FILE * fp = fopen("words.txt", "r");
if (fp == NULL)
{
printf("Cannot open file");
return 0;
}
while (fscanf(fp, "%s", str) != EOF)
{
words++;
}
printf("%d\n", words);
fseek(fp, 0, SEEK_SET);
array = malloc(sizeof(char*) * (words+1));
for(int i = 0; i < words && fscanf(fp, "%s", str) != EOF; i++)
{
array[i] = strdup(str);
}
array[words] = NULL;
return array;
}
int main() {
char **array = fill_word_array("someFile.txt");
for (int i=0; array[i] != NULL; i++) {
printf("%s\n", array[i]);
free(array[i]);
}
free(array);
}

Related

Reading a file line-by-line into an array of strings in C

I'm trying to read the following file line by line into an array of strings where each line is an element of the array:
AATGC
ATGCC
GCCGT
CGTAC
GTACG
TACGT
ACGTA
CGTAC
GTACG
TACGA
ACGAA
My code is as follows:
void **get_genome(char *filename) {
FILE *file = fopen(filename, "r");
int c;
int line_count = 0;
int line_length = 0;
for (c = getc(file); c != EOF; c = getc(file)) {
if (c == '\n') line_count++;
else line_length++;
}
line_length /= line_count;
rewind(file);
char **genome = calloc(line_length * line_count, sizeof(char));
for (int i = 0; i < line_count; i++) {
genome[i] = calloc(line_length, sizeof(char));
fscanf(file, "%s\n", genome[i]);
}
printf("%d lines of %d length\n", line_count, line_length);
for (int i = 0; i < line_count; i++)
printf("%s\n", genome[i]);
}
However, for some reason I get garbage output for the first 2 elements of the array. The following is my output:
`NP��
�NP��
GCCGT
CGTAC
GTACG
TACGT
ACGTA
CGTAC
GTACG
TACGA
ACGAA
You seem to assume that all lines have the same line length. If such is the case, you still have some problems:
the memory for the row pointers is allocated incorrectly, it should be
char **genome = calloc(line_count, sizeof(char *));
or better and less error prone:
char **genome = calloc(line_count, sizeof(*genome));
the memory for each row should be one byte longer the the null terminator.
\n is the fscanf() format string matches any sequence of whitespace characters. It is redundant as %s skips those anyway.
it is safer to count items separated by white space to avoid miscounting the items if the file contains any blank characters.
you do not close file.
you do not return the genome at the end of the function
you do not check for errors.
Here is a modified version:
void **get_genome(const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL)
return NULL;
int line_count = 1;
int item_count = 0;
int item_length = -1;
int length = 0;
int c;
while ((c = getc(file)) != EOF) {
if (isspace(c)) {
if (length == 0)
continue; // ignore subsequent whitespace
item_count++;
if (item_length < 0) {
item_length = length;
} else
if (item_length != length) {
printf("inconsistent item length on line %d\", line_count);
fclose(file);
return NULL;
}
length = 0;
} else {
length++;
}
}
if (length) {
printf("line %d truncated\n", line_count);
fclose(file);
return NULL;
}
rewind(file);
char **genome = calloc(item_count, sizeof(*genome));
if (genome == NULL) {
printf("out of memory\n");
fclose(file);
return NULL;
}
for (int i = 0; i < item_count; i++) {
genome[i] = calloc(item_length + 1, sizeof(*genome[i]));
if (genome[i] == NULL) {
while (i > 0) {
free(genome[i]);
}
free(genome);
printf("out of memory\n");
fclose(file);
return NULL;
}
fscanf(file, "%s", genome[i]);
}
fclose(file);
printf("%d items of %d length on %d lines\n",
item_count, item_length, line_count);
for (int i = 0; i < item_count; i++)
printf("%s\n", genome[i]);
return genome;
}
char **genome = calloc(line_length * line_count, sizeof(char));
must be
char **genome = calloc(line_count, sizeof(char*));
or more 'secure'
char **genome = calloc(line_count, sizeof(*genome));
in case you change the type of genome
else the allocated block if not enough long if you are in 64b because line_count is 5 rather than 8, so you write out of it with an undefined behavior
You also need to return genome at the end of the function
It was also possible to not count the number of lines and to use realloc to increment your array when reading the file
As I see the lines have the same length. Your function should inform the caller how many lines have been read. There is no need of reading the file twice. There is no need of calloc (which is more expensive function). Always check the result of the memory allocation functions.
Here is a bit different version of the function:
char **get_genome(char *filename, size_t *line_count) {
FILE *file = fopen(filename, "r");
int c;
size_t line_length = 0;
char **genome = NULL, **tmp;
*line_count = 0;
if(file)
{
while(1)
{
c = getc(file);
if( c == EOF || c == '\n') break;
line_length++;
}
rewind(file);
while(1)
{
char *line = malloc(line_length + 1);
if(line)
{
if(!fgets(line, line_length + 1, file))
{
free(line);
break;
}
line[line_length] = 0;
tmp = realloc(genome, (*line_count + 1) * sizeof(*genome));
if(tmp)
{
genome = tmp;
genome[*line_count] = line;
*line_count += 1;
}
else
{
// do some memory free magic
}
}
}
fclose(file);
}
return genome;
}

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);

Detecting the rows of an array and finding common words of two arrays in C

I have a filed called a1.txt which contains the words
amazing
malevolent
permanent
and another one called a2.txt with
Amazing
Bridge
Malevolent
Here is the code that I use to read the files into arrays, thanks to #M Oehm.
NOTE: void b(); is the same as void a() but it reads a2.txt instead.
void a();
void b();
char (*a1)[50];
char (*a2)[50];
int n;
int main(int argc, char *argv[]) {
a();
printf("\n\n");
b();
int i=0, j=0;
for (i; i < strlen(*a1); i++)
{
for (j; j <strlen(*a2); j++)
{
printf("\n%d", strcmp(a1[i], a2[j]));
}
}
return 0;
}
void a(){
FILE *f;
int i;
f = fopen("a1.txt", "r");
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(1);
}
/* first pass */
n = 0;
while (fscanf(f, "%*s") != EOF) n++; /* star means: scan, but don't store */
a1 = malloc((n + 1) * sizeof(*a1));
if (a1 == NULL) {
fprintf(stderr, "Allocation failed\n");
exit(1);
}
/* second pass */
fseek(f, 0, SEEK_SET);
for (i = 0; i < n; i++) {
fscanf(f, "%49s", a1[i]);
}
*a1[n] = '\0';
/* process words */
for (i = 0; i < n; i++) {
printf("%s\n",a1[i]);
}}
As you can see the rows of the arrays are dynamic(I used three words as a test, however this should be done for an unknown amount of words hence the usage of calloc). Is it possible to detect the rows of each array and write the common words of each in a new file?
Finding the common words is a simple matter, I assume, of using strstr.
You seem to have some misconceptions about memory allocation:
char *str[50] creates an array of 50 (uninitialised) pointers of char. Perhaps you want char (*str)[50], which is a pointer to an array of 50 chars, to which you can allocate memory.
lSize is the length of the file, i.e. the number of chars. It looks a bit as if you wanted to count the number of words.
I'll present two strategies for reading words into a char array.
Read fixed-size words
This strategy uses a fixed word size of 50, as in your example. It opens the file and reads it in two passes. The first to determine the number of words, the next to read the actual words after allocating enough space.
int main(int argc, char *argv[])
{
FILE *f;
char (*str)[50]; /* Pointer to words of max length 49 */
int n; /* number of words */
int i;
if (argc != 2) {
fprintf(stderr, "Usage: $fifo file_name.ip\n");
exit(1);
}
f = fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(1);
}
/* first pass */
n = 0;
while (fscanf(f, "%*s") != EOF) n++; /* star means: scan, but don't store */
str = malloc((n + 1) * sizeof(*str));
if (str == NULL) {
fprintf(stderr, "Allocation failed\n");
exit(1);
}
/* second pass */
fseek(f, 0, SEEK_SET);
for (i = 0; i < n; i++) {
fscanf(f, "%49s", str[i]);
}
*str[n] = '\0';
/* process words */
for (i = 0; i < n; i++) {
printf("%4d: '%s'\n", i, str[i]);
}
free(str);
return 0;
}
This approach is reasonably simple, but it has two drawbacks: You will waste memory, because most words won't be 50 characters long. And you have to scan the file twice. Both drawbacks are not serious on modern computers.
Allocate as you go
You can also maintain the words as pointers to pointers to char, char **str. str[i] gives you a word, which is stored as pointer into existing memory of a null-terminated string. The function strtok gives you such strings.
This "existing memory" is the contents of the file as char buffer. Rohan has shown you how to get ti: By getting the file length, allocating and reading.
This method takes only one pass, because it reallocates memory according to its needs. Start with space for, say, 64 words, read them, find out we need more, so reallocate to make 128 words fit, read words 64-127, and so on.
int main(int argc, char *argv[])
{
FILE *f;
char *buf; /* Buffer that hold the file's contets */
size_t size; /* Size of that buffer */
char **str; /* Array of pointers to words in that buffer */
int n; /* number of words */
int nalloc; /* For how many words space is allocated */
int i;
if (argc != 2) {
fprintf(stderr, "Usage: $fifo file_name.ip\n");
exit(1);
}
f = fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(1);
}
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
buf = malloc(size + 1);
if (buf == NULL) {
fprintf(stderr, "Allocation failed\n");
exit(1);
}
/* read whoe file */
fread(buf, 1, size, f);
buf[size] = '\0';
fclose(f);
n = 0;
nalloc = 0;
str = NULL;
for (;;) {
if (n >= nalloc) {
/* reallocate */
nalloc = nalloc * 2;
if (nalloc == 0) nalloc = 64;
str = realloc(str, nalloc * sizeof(*str));
if (str == NULL) {
fprintf(stderr, "Reallocation failed\n");
exit(1);
}
}
str[n] = strtok(n ? NULL : buf, " \t\n\r");
if (str[n] == NULL) break;
n++;
}
/* process words */
for (i = 0; i < n; i++) {
printf("%4d: '%s'\n", i, str[i]);
}
free(buf);
free(str);
return 0;
}
This approach is more efficient, but also more complicated. Note how many variables I need to keep track of everything: The llocated size, the actual size, the size of the text buffer. And I have to take care of two allocated arrays.
Given that you want to read two files, it makes sense to pack these variables into a structure and read each file into such a structure.
Conclusion
These are only two of many ways to read words from a file. Both are not trivial and require that you understand how to manage memory.
I think one of the most basic things to learn is that a pointer may be used for many different things. It can just point to existing memory, whether that has been allocated or is an automatic array. But it can also be used as a handle to allocated memory; it will then behave like an array, excapt that you have to free the memory after use. You should not "move" such pointers, i.e. change the address they point to.
Both kinds of pointers look the same in your code, but you have to know which pointer acts as what.
With
char *a1[50];
char *a2[50]; //not used so can remove
You are creating array of char pointers, not array of characters. You may want to just use char pointers as
char *a1;
char *a2;
Then instead of
a1[50] = calloc(1, lSize +1);
do
a1 = calloc(1, lSize +1);
Using a1[50] as in your code is incorrect and will cause undefined behavior (including segmentation fault). The array elements are from 0 to 49, so last element is a1[49].
Also, you can use lSize to read those many characters as below
for (i=0; i <lSize; i++)
{
if (fscanf(file, "%c", &a1[i]) == 1){
printf("%c", a1[i]);
}
}
But may be you can skip the for loop limit and read from file until there is no error.

Segmentation fault when writing contents of dictionary to file

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;
}

fgets + dynamic malloc/realloc with a .txt as stdin

i'm trying to read lines of a file. txt, but without knowing the size of each lines...First I used the getline instruction (and works fine), but my teacher does not let me use that instruction, he says I can only use the fgets statement with malloc and realloc...
This is an input example, with variable line sizes:
[9.3,1.2,87.9]
[1.0,1.0]
[0.0,0.0,1.0]
As shown, each line defines a different vector with no size limit
Someone could help me implement this method?
Thank you very much.
NOTE: I forgot to mention, to compile the program I use these commands:
g++ -Wall-Wextra-Werror-pedantic main.c-o metbasicos.c metintermedios.c eda.exe
./eda.exe <eda.txt
I would say do something similar to this
while(fgets(buf, LEN, stdin)){
z = strtok(buf, ",");
*(*(matrix + i)) = atof(z);
for(j = 1; j < col; ++j){
z = strtok(NULL, ",");
*(*(matrix + i) + j) = atof(z);
}
++i;
}
The only extra thing you would have to take care of is making sure that you strip the brackets off of the first and last element.
Of course, if you don't know the size of the final array, you might need something like this:
struct data_t {
int nval; /* current number of values in array */
int max; /* allocated number of vlaues */
char **words; /* the data array */
};
enum {INIT = 1, GROW = 2};
...
while (fgets(buf, LEN, stdin)) {
if (data->words == NULL)
data->words = malloc(sizeof(char *));
else if (data->nval > data->max) {
data->words = realloc(data->words, GROW * data->max *sizeof(char *));
data->max = GROW * data->max;
}
z = strtok(buf, "\n");
*(data->words + i) = malloc(sizeof(char) * (strlen(z) + 1));
strcpy(*(data->words + i), z);
i++;
data->nval++;
}
data->nval--;
If you combine both of those while loops into a single one, you should be all set. The first one reads in floats, the second one is good for dynamically allocating space on the fly.
If you can use multiple steps, then use one function to get the information you need to malloc memory. (for example determine number of lines, and longest line) This function will do that for you (given the file name and location)
[EDIT] LineCount - This function will get you the number of lines, and the longest line so you can dynamically allocate memory in char **strings; in which to read the lines of the input file.
int lineCount(char *file, int *nLines)
{
FILE *fp;
int cnt=0, longest=0, numLines=0;
char c;
fp = fopen(file, "r");
while ( (c = fgetc ( fp) ) != EOF )
{
if ( c != '\n' )
{
cnt++;
if (cnt > longest) longest = cnt;
}
else
{
numLines++;
cnt= 0;
}
}
*nLines = numLines+1;//add one more
fclose(fp);
return longest+1;
}
Here is the implementation to read the input file you provided, using the function above to get the unknown dimensions of the input file...
#include <ansi_c.h>
#include <stdio.h>
#define FILENAME "c:\\dev\\play\\in.txt" //put your own path here
#define DELIM "- ,:;//_*&[]\n" //change this line as needed for search criteria
int lineCount(char *file, int *cnt);
void allocMemory(int numStrings, int max);
void freeMemory(int numStrings);
char **strings;
int main()
{
int numLines, longest, cnt, i;
FILE *fp;
longest = lineCount(FILENAME, &numLines);
char wordKeep[longest];
allocMemory(numLines, longest);
//read file into string arrays
fp = fopen(FILENAME, "r");
cnt=0;
i=0;
for(i=0;i<numLines;i++)
{
fgets(strings[i], longest, fp);
}
fclose(fp);
freeMemory(numLines);
getchar();
return 0;
}
int lineCount(char *file, int *nLines)
{
FILE *fp;
int cnt=0, longest=0, numLines=0;
char c;
fp = fopen(file, "r");
while ( (c = fgetc ( fp) ) != EOF )
{
if ( c != '\n' )
{
cnt++;
if (cnt > longest) longest = cnt;
}
else
{
numLines++;
cnt= 0;
}
}
*nLines = numLines+1;//add one more
fclose(fp);
return longest+1;
}
void allocMemory(int numStrings, int max)
{
int i;
// need number of lines by longest line for string containers
strings = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
strings[i] = calloc(sizeof(char)*max + 1, sizeof(char));
}
}
void freeMemory(int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(strings[i]) free(strings[i]);
free(strings);
}

Resources