Parsing .csv file into 2D array in C - c

I have a .csv file that reads like:
SKU,Plant,Qty
40000,ca56,1245
40000,ca81,12553.3
40000,ca82,125.3
45000,ca62,0
45000,ca71,3
45000,ca78,54.9
Note: This is my example but in reality this has about 500,000 rows and 3 columns.
I am trying to convert these entries into a 2D array so that I can then manipulate the data. You'll notice that in my example I just set a small 10x10 matrix A to try and get this example to work before moving on to the real thing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *getfield(char *line, int num);
int main() {
FILE *stream = fopen("input/input.csv", "r");
char line[1000000];
int A[10][10];
int i, j = 0;
//Zero matrix
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
A[i][j] = 0;
}
}
for (i = 0; fgets(line, 1000000, stream); i++) {
while (j < 10) {
char *tmp = strdup(line);
A[i][j] = getfield(tmp, j);
free(tmp);
j++;
}
}
//print matrix
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
printf("%s\t", A[i][j]);
}
printf("\n");
}
}
const char *getfield(char *line, int num) {
const char *tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",\n"))
{
if (!--num)
return tok;
}
return 0;
}
It prints only "null" errors, and it is my belief that I am making a mistake related to pointers on this line: A[i][j] = getfield(tmp, j). I'm just not really sure how to fix that.
This is work that is based almost entirely on this question: Read .CSV file in C . Any help in adapting this would be very much appreciated as it's been a couple years since I last touched C or external files.

It looks like commenters have already helped you find a few errors in your code. However, the problems are pretty entrenched. One of the biggest issues is that you're using strings. Strings are, of course, char arrays; that means that there's already a dimension in use.
It would probably be better to just use a struct like this:
struct csvTable
{
char sku[10];
char plant[10];
char qty[10];
};
That will also allow you to set your columns to the right data types (it looks like SKU could be an int, but I don't know the context).
Here's an example of that implementation. I apologize for the mess, it's adapted on the fly from something I was already working on.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Based on your estimate
// You could make this adaptive or dynamic
#define rowNum 500000
struct csvTable
{
char sku[10];
char plant[10];
char qty[10];
};
// Declare table
struct csvTable table[rowNum];
int main()
{
// Load file
FILE* fp = fopen("demo.csv", "r");
if (fp == NULL)
{
printf("Couldn't open file\n");
return 0;
}
for (int counter = 0; counter < rowNum; counter++)
{
char entry[100];
fgets(entry, 100, fp);
char *sku = strtok(entry, ",");
char *plant = strtok(NULL, ",");
char *qty = strtok(NULL, ",");
if (sku != NULL && plant != NULL && qty != NULL)
{
strcpy(table[counter].sku, sku);
strcpy(table[counter].plant, plant);
strcpy(table[counter].qty, qty);
}
else
{
strcpy(table[counter].sku, "\0");
strcpy(table[counter].plant, "\0");
strcpy(table[counter].qty, "\0");
}
}
// Prove that the process worked
for (int printCounter = 0; printCounter < rowNum; printCounter++)
{
printf("Row %d: column 1 = %s, column 2 = %s, column 3 = %s\n",
printCounter + 1, table[printCounter].sku,
table[printCounter].plant, table[printCounter].qty);
}
// Wait for keypress to exit
getchar();
}

There are multiple problems in your code:
In the second loop, you do not stop reading the file after 10 lines, so you would try and store elements beyond the end of the A array.
You do not reset j to 0 at the start of the while (j < 10) loop. j happens to have the value 10 at the end of the initialization loop, so you effectively do not store anything into the matrix.
The matrix A should be a 2D array of char *, not int, or potentially an array of structures.
Here is a simpler version with an allocated array of structures:
#include <stdio.h>
#include <stdlib.h>
typedef struct item_t {
char SKU[20];
char Plant[20];
char Qty[20];
};
int main(void) {
FILE *stream = fopen("input/input.csv", "r");
char line[200];
int size = 0, len = 0, i, c;
item_t *A = NULL;
if (stream) {
while (fgets(line, sizeof(line), stream)) {
if (len == size) {
size = size ? size * 2 : 1000;
A = realloc(A, sizeof(*A) * size);
if (A == NULL) {
fprintf(stderr, "out of memory for %d items\n", size);
return 1;
}
}
if (sscanf(line, "%19[^,\n],%19[^,\n],%19[^,\n]%c",
A[len].SKU, A[len].Plant, A[len].Qty, &c) != 4
|| c != '\n') {
fprintf(stderr, "invalid format: %s\n, line);
} else {
len++;
}
}
fclose(stream);
//print matrix
for (i = 0; i < len; i++) {
printf("%s,%s,%s\n", A[i].SKU, A[i].Plant, A[i].Qty);
}
free(A);
}
return 0;
}

Related

My matrix vector multiplication is returning incorrect values

After digging deep into the internet I managed to read all the numbers in my csv to a matrix vector and also for the other single dimension vector from its related csv. The matrix csv file contains a matrix in the following format
91,86,94
12,54,88
79,58,66
The other input vector file contains the members of the one dimension vector as follows
14
20
22
So I expect the output Vector as a result of this multiplication to be for the first row as
91*14+86*20+94*22=5062
Instead of the above my C code is giving me an insane -1469150284 as the member of the first row of the resultant Vector, I suspected the initialization of the two dimension matrix at first but then even after using memset() to set all elements in the array to 0, I still get the same incorrect values.
The complete code on how I read the csvs and how I load each number into the arrays and how I multiply is provided below, help me trace the bug that is causing the multiplication error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
//define the three files for reading
FILE *matFile = fopen("test1_input_mat.csv", "r");
FILE *vecFile = fopen("test1_input_vec.csv", "r");
//we are writing to the below file
FILE *outFile = fopen("test1_out_vec.csv", "w");
//make sure the file exists
if (matFile == NULL) {
printf("%s","File does not exist");
//break and return an exit code to the operating system
return 99;
}
//define the dimensions of the matrix
int x = 3;
int y = 3;
//allocate memory to the matrix dynamically
int (*matrix_array)[x] = malloc(sizeof(int[x][y]));
//initialize all the members to zero
memset(matrix_array, 0, sizeof(matrix_array));
//read from the matFile and assign to the vector
char *r, l;
//create a buffer variable for the read file process
char buffer[255];
char line[255] = "";
char *replaced = NULL;
while (fgets(buffer, sizeof(buffer), matFile)) {
strncat(line, buffer, 255);
}
// printf("%s",line);
replaced = replaceWord(line, "\n", ",");
//printf("%s", replaced);
//now that we have the elements of the file in a line
//separated by commas
char delim[] = ",";
char *token;
//get the first token
token = strtok(replaced, delim);
//walk through other tokens
while (token != NULL) {
//parse this and add it to the array
int sub = atoi(token);
//assign the number to th array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
matrix_array[i][j] = sub;
}
}
token = strtok(NULL, delim);
}
//allocate memory to one dimension array
int *vec = (int *)malloc(3 * sizeof(int));
//section below handles the parsing of numbers from the vector file
char vline[255] = "";
char vbuffer[255];
char concatenated[255];
char *replacing;
//read the vector file
while (fgets(vbuffer, 255, vecFile)) {
strncat(concatenated, vbuffer, sizeof(vbuffer));
}
//replace the new line characters with commas
replacing = replaceWord(concatenated, "\n", ",");
//now parse that into the one dimension vector
char *vtoken;
//get the first token
vtoken = strtok(replacing, delim);
//get the rest of the tokens
while (vtoken != NULL) {
int no = atoi(vtoken);
//append the numbers to the one dimension vector
for (int i = 0; i < 3; i++) {
vec[i] = no;
}
vtoken = strtok(NULL, delim);
}
//this is the section where we do the multiplication of the two
int *out_vec = (int *)malloc(3 * sizeof(int));
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//assign the product of the multiplication to the right index in the vector
out_vec[j] += matrix_array[i][j] * vec[j];
}
}
//write the integers in the second to the out file
char str[255];
char fin[255];
for (int i = 0; i < 3; i++) {
printf("%d\n", out_vec[i]);
}
//close the matFile
fclose(matFile);
}
//method to replace the newline characters with commas
This code helped me replace the new line characters with commas in the single line comprised of all lines in the file
//this method replaces a string in the target string with another string
char *replaceWord(const char *s, const char *oldW,
const char *newW)
{
char *result;
int i, cnt = 0;
int newWlen = strlen(newW);
int oldWlen = strlen(oldW);
// Counting the number of times old word
// occur in the string
for (i = 0; s[i] != '\0'; i++) {
if (strstr(&s[i], oldW) == &s[i]) {
cnt++;
// Jumping to index after the old word.
i += oldWlen - 1;
}
}
// Making new string of enough length
result = (char *)malloc(i + cnt * (newWlen - oldWlen) + 1);
i = 0;
while (*s) {
// compare the substring with the result
if (strstr(s, oldW) == s) {
strcpy(&result[i], newW);
i += newWlen;
s += oldWlen;
} else
result[i++] = *s++;
}
result[i] = '\0';
return result;
}
I have tried to simplify and clean up your code as much as possible.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 3
#define COLS 3
int main(int argc, char* argv[])
{
FILE* matFile = fopen("test1_input_mat.csv", "r");
if (!matFile) {
puts("File does not exist");
return 99;
}
int (*matrix_array)[ROWS] = malloc(sizeof(int[ROWS][COLS]));
char buffer[255];
for (int row = 0; row < ROWS; row++) {
if (fgets(buffer, sizeof(buffer), matFile)) {
char *p = strtok(buffer, ",");
for (int col = 0; col < COLS; col++) {
if (!p) return 99;
matrix_array[row][col] = atoi(p);
p = strtok(NULL, ",");
}
}
}
fclose(matFile);
FILE* vecFile = fopen("test1_input_vec.csv", "r");
if (!vecFile) {
puts("File does not exist");
return 99;
}
int* vec = malloc(ROWS * sizeof(int));
for (int row = 0; row < ROWS; row++) {
if (fscanf(vecFile, "%d", &vec[row]) != 1) return 99;
}
fclose(vecFile);
int* out_vec = calloc(ROWS, sizeof(int));
for (int row = 0; row < ROWS; row++){
for (int col = 0; col < COLS; col++){
out_vec[row] += matrix_array[row][col] * vec[col];
}
}
for (int row = 0; row < ROWS; row++){
printf("%d\n", out_vec[row]);
}
free(matrix_array);
free(vec);
free(out_vec);
return 0;
}
One thing still to do is check the return values from malloc and calloc. Though it is unlikely in a small program like this, they can return NULL
Also, since you have hard-coded the size to be 3x3, there is no need for malloc/calloc.
#define ROWS 3
#define COLS 3
...
int matrix_array[ROWS][COLS];
int vec[ROWS];
int out_vec[ROWS] = {0}

C programming: Check that each character is a valid number between 0 and 9, ignoring formatting characters

I am a beginner at coding and am currently in a course for this. I have been asked to produce a program that has a special function to convert the timestamps in a file into something that can be sorted from earliest to latest based on a numerical value. These would be imported from a file into an array. Some points of the assignment are:
The array of strings should be allocated dynamically to minimise the amount of memory used.
Create a function called timeStampToSeconds() that converts a timestamp string to a long int, which represents the number of seconds elapsed since 01/01/2000 00:00:00.
Your code will need to check that each character is a valid number between 0 and 9, ignoring formatting characters ('/', ' ', ':', '-') and convert the characters to their equivalent integers before being used to calculate the number of seconds elapsed since the above starting point.
I have included my code but am wondering if anyone has any pointers to help me on point 2 & 3? I have started with trying to implement point 3 with the strtok function, but I think I may be way off on this.Curently my function prototype is not doing what I had hoped for this.
Any advice would be much appreciated.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 50
void timeStampToSeconds(char array[]);
int main(void)
{
char array[50][20];
char input[10], filename[] = "Timestamps", outputfile[40], file_ext[4] = ".dat";
int i = 0, n = 0, j, x = 0, y = 0, o = 0;
double datetime = 0;
while (*input != *filename) {
printf("\nPlease enter the names of the required Input file: \n");
scanf("%s", input);
if (*input == *filename) {
printf("Input accepted!\n");
}
else printf("File name not found.Please try again!\n");
}
printf("Please enter the name of the sorted Output file to be created: \n");
scanf("%s", &outputfile);
strncat(&outputfile, &file_ext, 4); /*appends file extension characters to outputfile
variable characters*/
FILE* Ptr = NULL;
FILE* cfPtr = (char*)malloc(100 * sizeof(char));
if ((cfPtr = fopen("Timestamps.dat", "r")) == NULL) {
printf("File could not be opened\n");
}
while (!feof(cfPtr))
{
for (i = 0; i < 50; ++i)
{
for (j = 0; j < 20; ++j)
{
array[x][j] = fgetc(cfPtr);
y++;
}
x++;
}
}
fclose(cfPtr);
timeStampToSeconds(array);
if ((Ptr = fopen(outputfile, "w")) == NULL) {
printf("File could not be opened\n");
}
fwrite(array, sizeof(char), sizeof(array), Ptr);
fclose(Ptr);
return 0;
}
void timeStampToSeconds(char array[])
{
array;
long int n = 0, j = 0;
const char a[2] = "/"; const char b[2] = "-";
const char c[2] = ":";
char* token; char* token2; char *token3;
for (int i = 0; i < SIZE - 1; ++i) {
token = strtok(array, a);
while (token != NULL) {
token = strtok(NULL, a);
}
token2 = strtok(token, b);
while (token2 != NULL) {
token2 = strtok(NULL, b);
}
token3 = strtok(token2, c);
while (token3 != NULL) {
token3 = strtok(NULL, c);
}
token3 = array;
}
for (int i = 0; i < SIZE - 1; ++i) {
n = atol(array[i]);
array[i] = n;
}
}

Read adjacency matrix from file - Competitive programming

I have to do an assignment where I have to read a file that contains an adjacency matrix and later do some stuff.
I have all working but my code is very slow, at least for the benchmarking system.
I'm reading all the file rows in this code snippet below:
while (fgets(buf, sizeof(buf), stdin) != NULL) {
parse(buf);
i++;
}
and then I initialize my 2d array with all the values using strtok and atoi:
void parse(char *str, int count, char *sep) {
//char *aux = malloc(count * sizeof(char*));
char *aux;
aux = strtok(str, sep);
int j = 0;
while (aux) {
array[(i*DIM) + j] = atoi(aux);
j++;
aux = strtok(NULL, sep);
}
//free(aux);
}
Arrays are DIM*DIM size and each INT is separated by a comma.
Sample input for a 3*3 matrix:
1,20,1
0,111,3
4,7,10
How can I improve this for better performances?
EDIT:
array definition:
array = malloc(DIM*DIM*sizeof(int));
The malloc part makes no sense since you just need one single character pointer for strtok. Similarly, functions like strtol or atoi already parse the data, so you don't even need strtok - it just takes up extra time in this case. Furthermore, atoi doesn't have any error handling so it should never be used.
So you can just call strtol in a loop and it will do what you want. By checking the endptr argument you can see if each read was successful or not (man strtol). And then next lap in the loop, start over from endptr + 1.
If combining this with your 2D int array requirement, the function might look like this:
#include <stdio.h>
#include <stdlib.h>
void csv_to_int (size_t col, size_t row, int dst[col][row], const char* str)
{
const char* ptr = str;
char* end;
for(size_t c=0; c<col; c++)
{
for(size_t r=0; r<row; r++)
{
int val=strtol(ptr,&end,10);
if(ptr==end)
{
return ;
}
dst[c][r]=val;
ptr = end+1;
}
}
}
int main (void)
{
const char* input = "1,20,1\n0,111,3\n4,7,10\n";
int arr[3][3];
csv_to_int(3, 3, arr, input);
for(size_t i=0; i<3; i++)
{
for(size_t j=0; j<3; j++)
{
printf("%3d ", arr[i][j]);
}
puts("");
}
}
Output:
1 20 1
0 111 3
4 7 10
This is of course assuming that the input suits the 3x3 format - this code has almost no error handling.
How can I improve this for better performances?
So do not use these functions, if you think they are slow. Limit your requirements - do not handle locale specific digits. So read and convert it yourself. Blatantly disregard error checking. Something along:
#define _GNU_SOURCE 1
#include <stdio.h>
int main() {
char data[] ="1,20,1\n0,111,3\n4,7,10\n";
FILE *f = fmemopen(data, sizeof(data), "r");
int i = 0, j = 0;
#define DIM 3
int array[20];
// this reading part
int buf = 0;
for (int c; (c = fgetc(f)) != EOF; ) {
if (c == '\n') {
array[i * DIM + j] = buf;
buf = 0;
++i;
j = 0;
} else if (c == ',') {
array[i * DIM + j] = buf;
buf = 0;
++j;
} else {
buf *= 10;
buf += (c - '0');
}
}
array[i * DIM + j] = buf;
++j;
// checking
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
printf("%d %d = %d\n", i, j, array[i * DIM + j]);
}
}
}
Even further, ignore portability, and use system calls (on unix - read(STDIN_FILENO)) instead of C API.

Import a CSV of strings into a multi-dimensional array in C

I am trying to input a text file, in a similar format to a CSV, into a multi-dimensional array, where every element of the array is an array of words for each line. Any help would be much appreciated!
For example, the file input.txt could contain:
Carrot, Potato, Beetroot, Courgette, Broccoli
Dad's oranges, Apple, Banana, Cherry
Pasta, Pizza, Bread, Butter
The structure of the outputted array I am hoping to get from that would be in the form:
[[Carrot, Potato, Beetroot, Courgette, Broccoli], [Dad's oranges, Apple, Banana, Cherry], [Pasta, Pizza, Bread, Butter]]
So you the line:
printf("%s", inputArray[1][0]);
Would print:
Dad's oranges
I am not sure what the question here is. However, looking at your problem statement, and code I see few issues (note that I did not run the code, it is meant to give you an idea):
Your varCount will start from 1, as you increment before you put the first word.
You are storing an inherently 2-dimensional data into a single dimensional array. That is normally fine, but you need to encode where a line starts, and where it ends. That is missing. If all works, you will get an array of words, with no knowledge of where lines start/end. One way to deal with it is to create a 2D array. Another, is to insert a pointer to known word between the lines. Below is a code snippet that shows inserting a separator
char *knownWord = "anyword";
...
while (fgets(line, maxLineLength, inputFile))
{
token = strtok(&line[0], ",");
while (token) {
inputArray[varCount] = token;
varCount++;
token = strtok(NULL, ",");
}
inputArray[varCount] = knownWord;
varCount ++;
}
For this the print will happen with something like
bool atKnownWord = 0;
printf("[");
for (i = 0; i < maxWords; i++) {
if (inputArray[i] == NULL) {
break;
}
if (inputArray[i] == knownWord) {
atKnownWord = 1;
printf("]");
continue;
}
if (atKnownWord) {
atKnownWord = 0;
printf(", [");
}
printf("%s", inputArray[i]);
}
printf("]");
You have not allocated the memory to store the token.
Also you should increment varCount after storing the token in an array.
The code can be written as:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define maxLineLength 1000 //Maximum length of a line
#define wordsPerLine 200 //Maximum words in a line
#define maxLines 200 //Maximum lines in an input
int main(int argc, char *argv[])
{
char line[maxLineLength] = {0};
char *inputArray[maxLines][wordsPerLine] = {};
char *ptr, *token;
int i, j, lines, maxWords = 0;
FILE *inputFile = fopen("input.txt", "r");
if (inputFile)
{
i = j = 0;
while (fgets(line, maxLineLength, inputFile))
{
token = strtok(&line[0], ",\n");
while(token)
{
if(ptr = malloc(sizeof(char) * (strlen(token)+1))) //whether malloc succeeded
{
if(token[0] == ' ')
strcpy(ptr, token+1);
else
strcpy(ptr, token);
inputArray[i][j++] = ptr;
token = strtok(NULL, ",\n");
}
else
{
printf("malloc failed!\n");
exit(1);
}
}
if(maxWords < j)
maxWords = j;
i++;
j = 0;
}
lines = i;
fclose(inputFile);
for(i = 0; i < lines; i++)
{
for(j = 0; (j < maxWords) && inputArray[i][j]; j++)
printf("%s | ", inputArray[i][j]);
printf("\n");
}
}
return 0;
}

How can i use input data from a file in C programming?

I have a program that uses word search. I have a data file which contains the puzzle and the words. What can i implement into my program so that it reads the file and stores the letters present in it as an array?
Example of the data file (it is called testdata):
h e l l o a c d
f g b w o r l d
h a c c v b n a
e q b x n t q q
y e h n c a q r
hello
world
hey
I want to store all the letters in a 2-d array.
Also, I need to store all the words in a 1-dimensional array.
The maximum number of rows of columns or rows that AxA square of letters that is possible in a data file is 25. So, I believe that I should declare an array of that size for the letter and then write them into that array.
I just can't figure out how to read them into that array. There is a space after each letter in the array and no spaces in the words so I think that might be helpful when putting the letters in one array and words in another.
Given your question, and your input, there are a few questions, but in the interest of time, for now, I have made some assumptions about the dimensions of the array, i.e. that it is not necessarily square (as implied by columns or rows that AxA square). The actual data sample disagrees, so I wrote a routine that counts everything as it goes. The letter array is simply an array of arrays, but since it is stored in sequential memory, it just looks like one long array. The strings are each in there own location as well. In any case, this code should illustrate enough to get you on the right track...
#include <ansi_c.h>
#include <stdio.h>
void GetFileContents(char *file, int *nWords, int *lw, int *r, int *c);
void allocMemoryStr(int numStrings, int max);
void allocMemoryLtr(int numStrings, int max);
void freeMemoryStr(int numStrings);
void freeMemoryLtr(int numletters);
#define FILENAME "c:\\dev\\play\\_puzzle.txt"
char **letters;
char **strings;
int main()
{
int longest, cnt, wCount, rows, cols, i;
char line[260];
FILE *fp;
char *buf=0;
GetFileContents(FILENAME, &wCount, &longest, &rows, &cols);
allocMemoryStr(wCount, longest); //for strings
allocMemoryLtr(rows*cols, 1); //for strings
//read file into string arrays
fp = fopen(FILENAME, "r");
cnt=0;
for(i=0;i<rows;i++)
{
fgets(line, 260, fp);
buf = strtok(line, " \n");
while(buf)
{
strcpy(letters[cnt], buf);
buf = strtok(NULL, " \n");
cnt++; //use as accurate count of words.
}
}
cnt=0;
while(fgets(line, 260, fp)) //get remainder of lines into strings
{
//[EDIT]removed fgets()
buf = strtok(line, " \n");
while(buf)
{
strcpy(strings[cnt], buf);
buf = strtok(NULL, " \n");
cnt++; //use as accurate count of words.
}
}
fclose(fp);
freeMemoryStr(wCount);
freeMemoryLtr(rows*cols);
return 0;
}
void GetFileContents(char *file, int *nWords, int *lw, int *r, int *c)
{
char line[260];
FILE *fp;
char *buf=0;
char temp[80];
int wc=0, rc=0, cc=0, ck=0;
fp = fopen(FILENAME, "r");
while(fgets(line, 260, fp))
{
rc++;
buf = strtok(line, " \n");
while(buf)
{
strcpy(temp, buf); // word handler
if(strlen(temp) > 1)
{
wc++;
rc--; //
}
else if(strlen(temp) == 1) //leter handler
{
cc++;
(cc>ck)?(ck=cc):(cc=cc);
}
buf = strtok(NULL, " \n");
}
cc = 0;
}
fclose(fp);
*nWords = wc;
*r = rc;
*c = ck;
}
void allocMemoryStr(int numStrings, int max)
{
int i;
strings = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
strings[i] = calloc(sizeof(char)*max + 1, sizeof(char));
}
}
void allocMemoryLtr(int numletters, int max)
{
int i;
letters = calloc(sizeof(char*)*(numletters+1), sizeof(char*));
for(i=0;i<numletters; i++)
{
letters[i] = calloc(sizeof(char)*max + 1, sizeof(char));
}
}
void freeMemoryStr(int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(strings[i]) free(strings[i]);
free(strings);
}
void freeMemoryLtr(int numletters)
{
int i;
for(i=0;i<numletters; i++)
if(letters[i]) free(letters[i]);
free(letters);
}
I would parse the file line by line and char by char looking for what i need. In the example (which is untested), i hold three counters to help filling the arrays correctly.
char letters[25][25];
char words[10][25]
int letters_x_pos = 0; // Row counter
int letters_y_pos = 0; // Column counter
int words_pos = 0;
for (int i = 0; i < 25; i++) {
for (int j = 0; j < 25; j++) {
letters[i][j] = '\0';
}
}
const char *line;
while (line = some_read_function()) {
if (!(strlen(line) > 1)) {
continue;
}
if (line[1] == ' ') {
// Line contains letters
const char *letter = line;
while (*letter != '\0') {
if (*letter == ' ' || *letter == '\n' || *letter == '\r') {
continue;
}
else {
letters[letters_x_pos][letters_y_pos++] = *letter;
}
if (letters_y_pos == 25) {
// Maximum reached
break;
}
letter++;
}
// Increment row counter and reset column counter
letters_x_pos++;
letters_y_pos = 0;
if (letters_x_pos == 25) {
// Maximum reached
break;
}
}
else {
// Line contains word
strncpy(words[words_pos++], line, 25);
if (words_pos == 25) {
// Maximum reached
break;
}
}
}

Resources