Why am i getting a segmentation fault in Page Rank code? - c

I'm trying to read a file containing wikipedia pages and turning them into a matrix of 0 and 1 depending on whether there is an arc between them. So that we call a function using this matrix to sort their [PageRank.][1] but it says segmentation fault. Any help would be much appreciated.
#include <stdlib.h>
#include <string.h>
#define SIZE 10000
int main(int argc, char
const * argv[]) {
int graphe[SIZE][SIZE] = {0};
FILE * file = NULL;
char chaine[SIZE] = "";//the line from fgets
char * page = malloc(SIZE * sizeof(char));//an array with all the first pages of the file
char ** tab = malloc(SIZE * SIZE * sizeof(char));//2D array containing all the pages
file = fopen("wiki-zulu.txt", "r");
if (file != NULL) {
int i = 0, j = 0, cpt = 0;
while (fgets(chaine, SIZE, file) != NULL) {
char * token = strtok(chaine, "|");
page[i] = * token;
while (token != NULL) {
tab[i][j] = * token;
token = strtok(NULL, "|");
j++;
cpt++;
i++;
}
for (int i = 0; i < cpt; i++) {
for (int j = 0; j < cpt; j++) {
for (int k = 0; k < cpt; k++) {
if (tab[i][j] == page[k] && i != j) {//comparing all values in the 2D array with the array of pages
graphe[i][k] = 1;//1 if there is a link between them
}
printf("%d\t", graphe[i][j]);
}
}
printf("\n");
}
free(page);
free(tab);
fclose(file);
}
}
return 0;
}```
[1]: https://i.stack.imgur.com/eITFZ.png

Your problem is most likely the way you allocate the tab matrix.
It is 1D array not a 2D one. And you cannot access it the way you are.
More standard, safer allocation of 2D matrix (you can change calloc with malloc):
// Allocate the first dimension and check for error
char **tab = (char **) calloc(SIZE, sizeof(char*));
if (!tab) {
perror("calloc");
}
// Loop through the first dim to allocate the second one.
// Don't forget to free the allocated memory if something goes wrong
for (size_t i = 0; i < SIZE; ++i) {
tab[i] = (char*) calloc(SIZE, sizeof(char));
if (!tab[i]) {
for (size_t j = i; j >= 0; --j) {
free(tab[j]);
}
free(tab);
perror("calloc");
}
}

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}

Print last few lines of a text file

Currently, I am trying to create a C program that prints the last few lines of a text file, read in through the command line. However, it is currently causing a segmentation error when I try to copy the strings from fgets into the main array. I have been unable to fix this, and so have not been able to test the rest of my code. How would I begin to fix the segmentation error? I have posted the code below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i=1,j,printNumber;
char **arr = (char **) malloc (100 * sizeof(char *));
char *line = (char *) malloc (80 * sizeof(char));
if (argc == 1) {
printNumber = 10;
}
else {
printNumber = atoi(argv[1]);
}
while (fgets(line,80,stdin) != NULL) {
if (line != NULL) {
line[strlen(line)-1] = '\0';
strcpy(arr[i],line); //SEGMENTATION ERROR!!!!
}
else {
free(line);
strcpy(arr[i],NULL);
}
i++;
printf("%d ",i);
}
free(arr);
for (j = i-printNumber-1; j < i-1; j++) {
printf("%s ", arr[j]);
}
printf("\n");
return 0;
}
You are allocating space for arr, which is a pointer to a pointer to char, but not allocating any individual char * pointers within arr.
Since you allocated arr with the size of 100 * sizeof(char *), I assume you want 100 sub-entries in arr. Sure:
for(i = 0; i < 100; i++)
arr[i] = malloc(80 * sizeof(char));
Then, when you free arr:
for(i = 0; i < 100; i++)
free(arr[i]);
free(arr);
Note that it is good practice to always check malloc for failure (return value of NULL) and handle it, and to set pointers to NULL after freeing them once to avoid double-free bugs.
You don't always know the length of the longest line (not until you try to read) OR how many last lines you are expected to keep track of (but is given at runtime). Thus, both of these values need to be known before you allocate memory or delegated to a function that does it for you.
#include <stdio.h>
#include <stdlib.h>
struct Line {
char *line; // content
size_t storage_sz; // allocation size of line memory
ssize_t sz; // size of line, not including terminating null byte ('\0')
};
int main(int argc, char *argv[]) {
int max_lines = 10;
if (argc > 1) {
max_lines = atoi(argv[1]);
}
if (max_lines < 0) {
fprintf(stderr, "%s\n", "Sorry, no defined behaviour of negative values (yet)\n");
return EXIT_FAILURE;
}
// keep an extra slot for the last failed read at EOF
struct Line *lines = (struct Line *) calloc(max_lines + 1, sizeof(struct Line));
int end = 0;
int size = 0;
// only keep track of the last couple of lines
while ((lines[end].sz = getline(&lines[end].line, &lines[end].storage_sz, stdin)) != -1) {
end++;
if (end > max_lines) {
end = 0;
}
if (size < max_lines) {
size++;
}
}
// time to print them back
int first = end - size;
if (first < 0) {
first += size + 1;
}
for (int count = size; count; count--) {
// lines might contain null bytes we can't use printf("%s", lines[first].line);
fwrite(lines[first].line, lines[first].sz, 1u, stdout);
first++;
if (first > size) {
first = 0;
}
}
// clear up memory after use
for (int idx = 0; idx <= max_lines; idx++) {
free(lines[idx].line);
}
free(lines);
return EXIT_SUCCESS;
}

How can I change an array of string pointers in another function?

I have been trying to figure out how to modify an array of char pointers but no matter what I do there appears to be no change below are the three arrays I'm trying to change including the call to the function I'm using.
char*cm1[5];
char*cm2[5];
char*cm3[5];
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);
The code below is the function itself.I was thinking that maybe it involves a double pointer but if I try *cmd to change the array I get a segmentation fault.
void setupCommands(char **cmd[], char* commands[],char file[],int index){
char str1[255];
strcpy(str1,commands[index]);
char newString [5][255];
int j = 0;
int ctr = 0;
int i;
//printf("str1 %s\n" ,str1);
for(i = 0; i <= strlen(str1); i++){
if(str1[i] == ' '|| str1[i] =='\0'){
newString[ctr][j] = '\0';
ctr++;//next row
j=0;// for next word, init index to 0
}else{
newString[ctr][j]=str1[i];
j++;
}
}
for(i = 0; i < ctr; i++){
//printf(" test2 %s \n", newString[i]);
cmd[i] = newString[i];
//printf(" test2 %d %s \n", i,cmd[i]);
}
//printf("index %d", i);
cmd[i]= file;
cmd[i + 1] = NULL;
//execvp(cmd[0],cmd);
//cmd
}
There are a few issues with your code:
you are trying to return references to the local 'char newString [5][255]' when the function exits. In simple worlds - never return anything locally allocated on the stack. This is the reason you are getting the segmentation fault.
char **cmd[] must be declared char *cmd[] - even though you will get a warning from the compiler assignment from incompatible pointer type, the code would run and execute correctly(essentially **cmd[] would do the same work as *cmd[], even though it's not of correct type) if you didn't return references to the local object;
Easy and simple optimization is just to remove the array str1 and directly operate on the array commands.
Apart from this simple optimization I have changed your code to overcome the segmentation fault, by allocating on the heap, instead on stack(will live until the program terminates) the multidimensional array, and I also calculate it's size so I will know how much memory to allocate. Now it's safe to return references to it.
Note that more optimizations could be made, but for the sake of the simplicity this is the bare minimal for this code to work.
int setupCommands(char *cmd[], char *commands[], char file[], int index)
{
int j = 0;
int ctr = 0;
int i = 0;
int rows = 0;
int cols = 0;
char **newString = NULL;
while(commands[index][i])
{
if (commands[index][i] == ' ')
{
++rows;
}
++i;
}
++rows;
cols = strlen(commands[index]) + 1;
newString = malloc(rows * sizeof(*newString));
if (newString == NULL)
{
return -1;
}
for (i = 0; i < rows; ++i)
{
newString[i] = malloc(cols * sizeof(*newString));
if (newString[i] == NULL)
{
return -1;
}
}
for(i = 0; i <= strlen(commands[index]); i++){
if(commands[index][i] == ' '|| commands[index][i] =='\0'){
newString[ctr][j] = '\0';
ctr++;//next row
j=0;// for next word, init index to 0
}else{
newString[ctr][j]=commands[index][i];
j++;
}
}
for(i = 0; i < ctr; i++){
cmd[i] = newString[i];
}
cmd[i]= file;
cmd[i + 1] = NULL;
return 0;
}
First of all - being the three stars pointer programmer is not good :)
You assign it with pointer to the local variable which is not longer available after the function return
But if you still want the three stars pointers:
char **cm1;
char **cm2;
char **cm3;
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);
#define MAXWORD 256
int setupCommands(char ***cmd, const char *commands,const char *file,int index){
char str1[255];
strcpy(str1,commands[index]);
int j = 0;
int ctr = 0;
int i;
//printf("str1 %s\n" ,str1);
*cmd = malloc(sizeof(char *));
**cmd = malloc(MAXWORD);
if(!*cmd || !**cmd)
{
/* do spmething if mallocs failed*/
return -1;
}
for(i = 0; i <= strlen(str1); i++){
if(str1[i] == ' '|| str1[i] =='\0'){
(*cmd)[ctr][j] = '\0';
ctr++;//next row
*cmd = realloc((ctr + 1) * sizeof(int));
(*cmd)[ctr] = malloc(MAXWORD);
if(!*cmd || !*cmd[ctr])
{
/* do spmething if mallocs failed*/
return -1;
}
j=0;// for next word, init index to 0
}else{
(*cmd)[ctr][j]=str1[i];
j++;
}
}
*cmd = realloc(sizeof(char *) * ctr + 2)
(*cmd)[ctr - 2] = malloc(MAX);
if(!*cmd || !*cmd[ctr - 2])
{
/* do spmething if mallocs failed*/
return -1;
}
strcpy((*cmd)[ctr - 2], file);
(*cmd)[ctr - 1] = NULL;
return 0;
//execvp(cmd[0],cmd);
//cmd
}
you can improve many things (for example do not realloc every time but in the larger chunks) and I did not change anything in your code logic.

Error freeing memory after sorting the array pointer

How will I be able to maintain the position of the allocated memory so that freeing memory of a sorted array will not be affected?
I am trying to sort the pointer array. I noticed that when I free the words double pointer variable it will give an error HEAP CORRUPTION DETECTED. The input I entered was "f ff 1".
Unsorted: f ff 1
Sorted: 1 f ff
I noticed that when I sort and free it will expect the same order which is "f ff 1". That is why I got some error.
Any suggestion on how will be able to free the sorted pointer array?
#include <stdio.h>
/*
A logical type
*/
typedef enum {
false,
true,
} bool;
/*
Bubble Sort
*/
void sort(char *myargv[], int n)
{
int i, j, cmp;
char tmp[256];
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++)
{
for (j = 0; j < n-1; j++)
{
cmp = strcmp(myargv[j], myargv[j+1]);
if (cmp > 0)
{
strcpy(tmp, myargv[j+1]);
strcpy(myargv[j+1], myargv[j]);
strcpy(myargv[j], tmp);
}
}
}
}
void printArray(char *myargv[], int myargc)
{
int i = 0;
for (i = 0; i < myargc; ++i) {
printf("myargc[%d]: %s\n",i , myargv[i]);
}
}
int main (int argc, char *argv[])
{
char text[256];
char *myargv[256];
char *myargvTemp[256];
int myargc;
int i = 0;
int text_len;
bool new_word = false;
int index_start_word = 0;
char **words; //this will store the found word
int count = 0;
while(1){
printf( "Enter text:\n");
gets(text); //get the input
text_len = strlen(text); //get the length of the text
words = (char **) malloc(text_len * sizeof(char));
if (strlen(text) == 0 || text == '\0') exit(0); //exit if text is empty
for (i = 0; i < text_len ; ++i){
if(text[i] != ' '){ //if not space
if(new_word == false){
new_word = true;
index_start_word = i;
}
} else {
if (new_word == true) {
words[count] = (char *)malloc(i - index_start_word * sizeof(char)+1); //memory allocation
strncpy(words[count], text + index_start_word, i - index_start_word);
words[count][i - index_start_word] = '\0'; //place NULL after the word so no garbage
myargv[count] = words[count];
new_word = false;
count++;
}
}
if (new_word == true && i == text_len-1){
words[count] = (char *)malloc(i - index_start_word * sizeof(char)+2);
strncpy(words[count], text + index_start_word, (i+1) - index_start_word);
words[count][(i+1) - index_start_word] = '\0';
myargv[count] = words[count];
new_word = false;
count++;
}
}
myargc = count;
//not sorted
printf("myargc is: %d\n", myargc);
printArray(myargv, myargc);
//sorting happen
sort(&myargv, myargc);
printf("-----sorted-----\n");
printf("myargc is: %d\n", myargc);
printArray(myargv, myargc);
memset(myargv, 0, 255);
count = 0;
i = 0;
//free the memory of words
for (i=0; i<myargc; ++i) {
free(words[i]);
}
}
return 0;
}
There are at least 2 problems in your code:
you do not allocate enough space for the array of pointers: change the words = (char **) malloc(text_len * sizeof(char)); to this:
words = malloc(text_len * sizeof(char *));
This allocation is actually incorrect: you should compute the number of words and allocate the correct size for the pointer array, or use a fixed size array.
you swap the contents of the strings instead of swapping the pointers. This is incorrect as the various strings do not have the same lengths.
Here is a corrected version of the sorting function:
void sort(char *myargv[], int n) {
int i, j, cmp;
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++) {
for (j = 0; j < n-1; j++) {
cmp = strcmp(myargv[j], myargv[j+1]);
if (cmp > 0) {
char *tmp = myargv[j+1];
myargv[j+1] = myargv[j];
myargv[j] = tmp;
}
}
}
}
You want words to hold pointers to char so you need to change
words = (char **) malloc(text_len * sizeof(char)); //will allocate array of single byte
to
words = (char **) malloc(text_len * sizeof(char *));// will allocate array of pointers

Parsing .csv file into 2D array in 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;
}

Resources