storing CSV file to Float Matrix in C - c

Code does not store the value after the last comma of the line into matrix...
full list.csv is like:
123456,57,45,,67,,56,,63,,,72,67,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,,,1523521
123457,57,45,,67,,56,,634,,,72,67,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,1234,,
123458,57,45,,67,,56,,63,,,724,67,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,,1234,
123459,57,45,,67,,56,,63,,,72,647,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,,,1234
123450,57,45,,67,,56,,63,,,72,67,,,,344,56,,,,,56,,,,,,,,,,,,,,45,,,,,124
123451,57,45,,67,,56,,63,,,72,67,,,,34,564,,,,,56,,,,,,,,,,,,,,45,,,,,
123452,57,45,,67,,56,,63,,,72,67,,,,34,56,,,,,564,,,,,,,,,,,,,,45,,,,,124
123453,57,45,,67,,56,,63,,,72,67,,,,34,56,,,,,56,,,,,,,,,,,,,,454,,,,,
123454,57,45,,67,,56,,63,,,72,67,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,,,124
123455,574,45,,67,,56,,63,,,72,67,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,,,
123465,57,454,,67,,56,,63,,,72,67,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,,,
123466,57,45,,674,,56,,63,,,72,67,,,,34,56,,,,,56,,,,,,,,,,,,,,45,,,,,124
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int lines_allocated = 1000;
int max_line_len = 150;
double c[42][1000];
char **words = (char **)malloc(sizeof(char*)*lines_allocated);
if (words==NULL)
{
fprintf(stderr,"Out of memory (1).\n");
exit(1);
}
FILE *fp = fopen("full list.csv", "r");
if (fp == NULL)
{
fprintf(stderr,"Error opening file.\n");
exit(2);
}
int i;
for (i=0;1;i++)
{
int j;
if (i >= lines_allocated)
{
int new_size;
new_size = lines_allocated*2;
words = (char **)realloc(words,sizeof(char*)*new_size);
if (words==NULL)
{
fprintf(stderr,"Out of memory.\n");
exit(3);
}
lines_allocated = new_size;
}
words[i] = (char*)malloc(max_line_len);
if (words[i]==NULL)
{
fprintf(stderr,"Out of memory (3).\n");
exit(4);
}
if (fgets(words[i],max_line_len-1,fp)==NULL)
break;
for (j=strlen(words[i])-1;j>=0 && (words[i][j]=='\n' || words[i][j]=='\r');j--)
words[i][j]='\0';
}
int j;
int k=i;
for(j = 0; j < k; j++)
{
printf("%s\n", words[j]);
char *pptr = words[j];
int l;
for (l = 0; l < 42; l++)
{
char *ptr = strchr(pptr, ',');
if (ptr)
{
*ptr = 0;
c[l][j] = atof(pptr);
pptr = ptr + 1;
}
}
}
int l;
for (j = 0; j < k; j++)
{
printf("\n");
for (l = 0; l < 42; l++)
{
printf("%.2f\t", c[l][j]);
}
}
for (;i>=0;i--)
free(words[i]);
free(words);
return 0;
}

I think you miss a simple case: should be
#include <ctype.h>
...
char *ptr = strchr(pptr, ',');
if (ptr)
{
*ptr = 0;
c[l][j] = atof(pptr);
pptr = ptr + 1;
}
else if (isdigit(*pptr)) {
c[l][j] = atof(pptr);
}

Related

Segmentation fault using fgets in C

My code is not working and it is when I call fgets in the commandSplit function. I figured this out by printing "Am I here" in multiple places and find that the error at fgets it seems. I may be wrong, but I am pretty sure. I get a segmentation fault and I can not figure out why. Below is my code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define MAX_CHARACTERS 512
int Execute(char *a[], int t[], int num) {
int exitShell = 0;
int l = 0;
for (int i = 0; i < num; i++) {
int status;
if (strcmp(a[0], "quit") == 0) {
exitShell = 1;
}
if (t[i] && ((strcmp(a[l], "quit") == 0))) {
exitShell = 1;
}
char *holder[t[i]+1];
for (int j = 0; j < t[i]; j++) {
holder[j] = a[l];
l++;
}
holder[t[i]] = NULL;
pid_t p = fork();
pid_t waiting;
if (p == 0) {
execvp(holder[0], holder);
fprintf(stderr, "Child process could not execvp!\n");
exit(1);
} else {
if (p < 0) {
fprintf(stderr, "Fork FAILED!\n");
} else {
waiting = wait(&status);
printf("Child %d exit with status %d\n", waiting, status);
}
}
for (int g = 0; g < t[i]; g++) {
a[g] = NULL;
}
}
for (int i = 0; i < num; i++) {
t[i] = 0;
}
return exitShell;
}
int commandSplit(char *c, FILE *f, char *a[], int t[]) {
int count = 0;
int emptyfile = 1;
int stat = 0;
int total1 = 0;
char *temp[MAX_CHARACTERS];
if (c != NULL) {
char *readCommands = strtok(c, ";");
while (readCommands != NULL) {
temp[count] = readCommands;
count++;
readCommands = strtok(NULL, ";");
}
for (int i = 0; i < count; i++) {
char *read = strtok(temp[i], " ");
int track1 = 0;
while (read != NULL) {
a[total1] = read;
track1++;
total1++;
read = strtok(NULL, " ");
}
t[i] = track1;
}
stat = Execute(a, t, count);
} else {
char *buildCommands = "";
printf("Am I here???\n");
while ((fgets(buildCommands, MAX_CHARACTERS, f) != NULL) && !stat) {
printf("Am I here???\n");
emptyfile = 0;
commandSplit(buildCommands, NULL, a, t);
stat = Execute(a, t, count);
}
if (emptyfile) {
printf("File is empty!\n");
stat = 1;
}
}
printf("Am I here???\n");
return stat;
}
int main(int argc, char *argv[]) {
int exitProgram = 0;
FILE *fileRead = NULL;
if (argc == 2) {
fileRead = fopen(argv[1], "r");
if (fileRead == NULL) {
printf("No such file exists\n");
exitProgram = 1;
}
}
if (argc > 2) {
printf("Incorrect batch mode call\n");
exitProgram = 1;
}
char *args[MAX_CHARACTERS];
int tracker[MAX_CHARACTERS];
while (!exitProgram) {
if (argc == 1) {
char *commands = (char *)(malloc(MAX_CHARACTERS * sizeof(char)));
printf("tinyshell>");
if (fgets(commands, MAX_CHARACTERS, stdin) == NULL) {
exitProgram = 1;
printf("\n");
}
int len;
len = strlen(commands);
if (len > 0 && commands[len-1] == '\n') {
commands[len-1] = '\0';
}
if (len > MAX_CHARACTERS) {
printf("TOO MANY CHARACTERS - MAX: 512\n");
continue;
}
if (strlen(commands) == 0)
continue;
exitProgram = commandSplit(commands, NULL, args, tracker);
} else {
exitProgram = commandSplit(NULL, fileRead, args, tracker);
}
}
fclose(fileRead);
return 0;
}
As commented #Jean-François Fabre , buildCommands points to insufficient space and potential const space;
char *buildCommands = "";
...
// bad code
while ((fgets(buildCommands, MAX_CHARACTERS, f) != NULL) && !stat) {
Allocate space with an array or malloc()
char buildCommands[MAX_CHARACTERS];
...
while ((fgets(buildCommands, sizeof buildCommands, f) != NULL) && !stat) {
...
}
// or
char *buildCommands = malloc(MAX_CHARACTERS);
assert(buildCommands);
...
while ((fgets(buildCommands, MAX_CHARACTERS, f) != NULL) && !stat) {
...
}
...
free(buildCommands);

reads txt from file, cut them into words, and display

#pragma warning(disable:4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
static WORDS heap[10000];
int heapSize;
void InitHeap()
{
heapSize = 0;
heap[0].words = NULL;
heap[0].count = -1;
}
void InsertHeap(char* string)
{
heapSize++;
strcpy(heap[heapSize].words, string);
int now = heapSize;
while (heap[now / 2].words > string)
{
heap[now] = heap[now / 2];
now /= 2;
}
strcpy(heap[now].words, string);
}
int DeleteHeap()
{
char* minElement, lastElement;
int child, now;
strcpy(minElement, heap[1].words);
strcpy(lastElement, heap[heapSize--].words);
for (now = 1; now * 2 <= heapSize; now = child)
{
child = now * 2;
if (child != heapSize && heap[child + 1].words < heap[child].words)
{
child++;
}
if (lastElement > heap[child].words)
{
strcpy(heap[now].words, heap[child].words);
}
else
{
break;
}
}
strcpy(heap[now].words, lastElement);
return now;
}
typedef struct _WORDS {
char words[64];
int count;
}WORDS;
char* MakeToken(void)
{
int i, j;
static char delim[256];
memset(delim, 0x0, 256);
for (i = 1, j = 0; i < 256; i++)
{
if (!isalpha(i)) delim[j++] = i;
}
return delim;
}
int main() {
int i = 0, cur = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = MakeToken();
InitHeap();
pFile = fopen("C:\\Users\\Home\\Desktop\\dataset.txt", "r");
if (pFile == NULL) {
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL) {
ptr = strtok(readLine, token);
while (ptr != NULL) {
InsertHeap(ptr);
ptr = strtok(NULL, token);
}
}
for (i = 0; i < heapSize; i++)
{
cur = DeleteHeap();
printf("%s %d\n", heap[cur].words, heap[cur].count);
}
return 0;
}
Error Message : Run-Time error #3
I want to make program that reads txt from file, cut them into words, and display on console. I make it, but it doesnt work. how to fix it?
I think static WORDS heap<- this part
or
delete part is error.
or its path is failure.
I see following errors in your code:
heap[0].words = NULL;
words is an array, not a dynamyc allocated pointer, so you cannot assign to NULL (you get a compiler error! Seems to me that the WORDS.word variable declaration is uncorrect).
strcpy(minElement, heap[1].words);
strcpy(lastElement, heap[heapSize--].words);
minElement and lastElement are not initialized and not allocated, so the strcpy function will fail.
Here is a way to correct the code, I changed the minimum possible. The following collect the words, count the number of occurences and print the result in alphabetical order:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct _WORDS {
char words[64];
int count;
} WORDS;
static WORDS heap[10000];
int heapSize;
void InitHeap()
{
heapSize = 0;
}
void InsertHeap(char* string)
{
int num = 0;
// Search string in heap array. if found, increase count.
for(num = 0; num < heapSize; ++num)
{
if(strcmp(string, heap[num].words) == 0)
{
heap[num].count++;
return;
}
}
// If not found, add it to the array.
strcpy(heap[heapSize].words, string);
heap[heapSize].count = 1;
heapSize++;
}
char* MakeToken(void)
{
int i, j;
static char delim[256];
memset(delim, 0x0, 256);
for (i = 1, j = 0; i < 256; i++)
{
if (!isalpha(i)) delim[j++] = i;
}
return delim;
}
int compare(const void* v1, const void* v2)
{
return strcmp((const char*)v1, (const char*)v2);
}
int main()
{
int i = 0, cur = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = MakeToken();
InitHeap();
pFile = fopen("C:\\Users\\Home\\Desktop\\dataset.txt", "r");
if(pFile == NULL)
{
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL)
{
ptr = strtok(readLine, token);
while (ptr != NULL)
{
InsertHeap(ptr);
ptr = strtok(NULL, token);
}
}
// Order alphabetically the heap array.
qsort(heap, heapSize, sizeof(WORDS), compare);
for (i = 0; i < heapSize; i++)
{
printf("%s %d\n", heap[i].words, heap[i].count);
}
return 0;
}
I've fixed some errors in the code and it started to produce some results. Since I do not understand completely your task, I cannot progress further. The working code is as follows:
#pragma warning(disable:4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct _WORDS { char words[64]; int count; }WORDS;
static WORDS app_heap[10000];
int heapSize;
void InitHeap()
{
heapSize = 0;
app_heap[0].words[0] = '\0';
app_heap[0].count = -1;
}
void InsertHeap(char* string)
{
heapSize++;
strcpy(app_heap[heapSize].words, string);
int now = heapSize;
while (app_heap[now / 2].words > string)
{
app_heap[now] = app_heap[now / 2];
now /= 2;
}
strcpy(app_heap[now].words, string);
}
int DeleteHeap()
{
char minElement[64], lastElement[64];
int child, now;
if(heapSize <= 0)
{
printf("Wrong call\n");
return 0;
}
strcpy(minElement, app_heap[1].words);
strcpy(lastElement, app_heap[heapSize--].words);
for (now = 1; now * 2 <= heapSize; now = child)
{
child = now * 2;
if (child != heapSize && app_heap[child + 1].words < app_heap[child].words)
{
child++;
}
if (lastElement > app_heap[child].words)
{
strcpy(app_heap[now].words, app_heap[child].words);
}
else
{
break;
}
}
strcpy(app_heap[now].words, lastElement);
return now;
}
char* MakeToken(void)
{
int i, j;
static char delim[256];
memset(delim, 0x0, 256);
for (i = 1, j = 0; i < 256; i++)
{
if (!isalpha(i)) delim[j++] = i;
}
return delim;
}
int main() {
int i = 0, cur = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = MakeToken();
InitHeap();
pFile = fopen("dataset.txt", "r");
if (pFile == NULL) {
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL) {
ptr = strtok(readLine, token);
while (ptr != NULL) {
InsertHeap(ptr);
ptr = strtok(NULL, token);
}
}
for (i = 0; i < heapSize; i++)
{
cur = DeleteHeap();
printf("%s %d\n", app_heap[cur].words, app_heap[cur].count);
}
return 0;
}

Can't free memory from 2D dynamical array

I am having problem with freeing my memory. I did this many times, and it was working fine. Now, it just stops working (no error, anything, just freeze).
How my code looks like:
void args(int argc, char** argv, int *n, int *m, int **matrix, char name[20])
{
int firstIter = TRUE;
int x;
char op;
int** second;
second = NULL;
op = argv[1][0];
for (x = 2; x < argc; x++)
{
if (!firstIter)
{
setName(name, argv[x]);
loadMatrix(*m, *n, second, *name);
opMatrix(*m, *n, matrix, second, &*matrix, op);
}
else
{
setName(name, argv[x]);
loadSizeMatrix(n, m, name);
matrix = (int **)malloc(*n * sizeof(int*));
for (int i = 0; i < *n; i++) {
matrix[i] = (int *)malloc(*m * sizeof(int));
}
second = (int **)malloc(*n * sizeof(int*));
for (int i = 0; i < *n; i++) {
second[i] = (int *)malloc(*m * sizeof(int));
}
loadMatrix(*m, *n, matrix, *name);
firstIter = FALSE;
}
}
printMatrix(*m, *n, matrix);
for (int i = 0; i < *n; i++) {
free(second[i]);
}
free(second[0]); //doesnt work too, and yes, there are data
free(second);
}
second is being filled like this (loadMatrix):
for (int c = 0; c < radky; c++) {
for (int d = 0; d < sloupce; d++) {
fscanf(fp, "%i", &second[c][d]);
// printf("%i", matice[c][d]); // dump
}
}
How can I solve this error?
my full code
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <ctype.h> //tolower
#include <string.h>
#define TRUE 1
#define FALSE !TRUE
/* konstanty */
const enum {
MAX_DELKA_SOUBORU = 10000,
MAX_SOUBOR = 20
};
const enum {
SOUBOR_NENALEZEN = 1,
SPATNE_ARGUMENTY = 2,
LIMIT_NAZEV_SOUBOR = 3,
SPATNY_OP = 4
};
void error(int type);
void zpracovaniArgumentu(int argc, char** argv, char(*nazevSouboru)[MAX_SOUBOR], char(*nazevVystupni)[MAX_SOUBOR], int *n, int *m, int **matice);
void setNazevSouboru(char(*nazev)[MAX_SOUBOR], char *argument);
void vypisMatice(int radky, int sloupce, int **matice);
int nacteniMaticeZeSouboru(int radky, int sloupce, int **matice, char nazev[MAX_SOUBOR]);
int nacteniVelikostiMatice(int *n, int *m, char nazev[MAX_SOUBOR]);
int operaceMatic(int radky, int sloupce, int **prvni, int **druha, int **vysledek, char op);
int main(int argc, char** argv)
{
int n, m; // n = sloupce, m = radky pro prvni matici
int** first;
char nazevSouboru[MAX_SOUBOR], nazevVystupni[MAX_SOUBOR];
char op;
first = NULL;
zpracovaniArgumentu(argc, argv, &nazevSouboru, &nazevVystupni, &n, &m, &*first);
/* for (int i = 0; i < m; i++) {
free(first[i]);
} */
free(first);
system("pause");
return 0;
}
void error(int type)
{
switch (type)
{
case SOUBOR_NENALEZEN: printf("Soubor nenalezen!");
break;
case SPATNE_ARGUMENTY: printf("Program spustte s argumenty [nazev souboru] *[nazev vystupniho souboru]*.\n");
break;
case MAX_DELKA_SOUBORU: printf("Prekrocen maximalni limit delky nazvu souboru (%i).\n", MAX_SOUBOR);
break;
case SPATNY_OP: printf("Program spustte s argumenty [nazev souboru] *[nazev vystupniho souboru]*.\n");
break;
default: printf("Nastala chyba!");
break;
}
system("pause");
exit(type);
}
void zpracovaniArgumentu(int argc, char** argv, char(*nazevSouboru)[MAX_SOUBOR], char(*nazevVystupni)[MAX_SOUBOR], int *n, int *m, int **matice)
{
int firstIter = TRUE;
int doSouboru = FALSE;
int x;
char op;
int** second;
second = NULL;
op = argv[1][0];
for (x = 2; x < argc; x++)
{
if (!firstIter)
{
setNazevSouboru(nazevSouboru, argv[x]);
nacteniMaticeZeSouboru(*m, *n, &*second, *nazevSouboru);
operaceMatic(*m, *n, matice, &*second, &*matice, op);
}
else if (argv[x][0] == '-')
{
switch (argv[x][1])
{
case 'n': doSouboru = TRUE;
break;
default: error(SPATNE_ARGUMENTY);
break;
}
}
else if (doSouboru)
{
setNazevSouboru(nazevVystupni, argv[x]);
}
else
{
setNazevSouboru(nazevSouboru, argv[x]);
nacteniVelikostiMatice(n, m, *nazevSouboru);
matice = (int **)malloc(*n * sizeof(int*));
for (int i = 0; i < *n; i++) {
matice[i] = (int *)malloc(*m * sizeof(int));
}
second = (int **)malloc(*n * sizeof(int*));
for (int i = 0; i < *n; i++) {
second[i] = (int *)malloc(*m * sizeof(int));
}
nacteniMaticeZeSouboru(*m, *n, &*matice, *nazevSouboru);
firstIter = FALSE;
}
}
vypisMatice(*m, *n, matice);
for (int i = 0; i < *n; i++) {
printf("%i",second[i]);
free(second[i]);
}
free(second);
}
void setNazevSouboru(char(*nazev)[MAX_SOUBOR], char *argument)
{
strcpy(*nazev, argument);
strcat(*nazev, ".txt"); //nazev souboru
}
int nacteniVelikostiMatice(int *n, int *m, char nazev[MAX_SOUBOR])
{
FILE *fp = fopen(nazev, "r"); // načtení souboru
int c;
int radky = 1;
int sloupce = 0;
if (!fp)
{
error(SOUBOR_NENALEZEN);
exit(2);
}
else
{
while ((c = fgetc(fp)) != EOF)
{
//tolower(c);
if (c == '\n')
{
radky++;
}
else if ((isdigit(c)) && (radky == 1))
{
sloupce++;
}
}
}
fclose(fp);
*n = sloupce;
*m = radky;
return 0;
}
int nacteniMaticeZeSouboru(int radky, int sloupce, int **matice, char nazev[MAX_SOUBOR])
{
int x;
FILE *fp = fopen(nazev, "r"); // načtení souboru
if (!fp)
{
error(SOUBOR_NENALEZEN);
exit(2);
}
else
{
for (int c = 0; c < radky; c++) {
for (int d = 0; d < sloupce; d++) {
fscanf(fp, "%i", &matice[c][d]);
// printf("%i", matice[c][d]); // dump
}
}
}
fclose(fp);
return 0;
}
int operaceMatic(int radky, int sloupce, int **prvni, int **druha, int **vysledek, char op)
{
int vysledekClip[10][10];
for (int c = 0; c < radky; c++) {
for (int d = 0; d < sloupce; d++) {
switch (op) {
case '+': vysledekClip[c][d] = prvni[c][d] + druha[c][d];
vysledek[c][d] = vysledekClip[c][d];
break;
case '-': vysledekClip[c][d] = prvni[c][d] - druha[c][d];
vysledek[c][d] = vysledekClip[c][d];
break;
case '/': vysledekClip[c][d] = prvni[c][d] / druha[c][d];
vysledek[c][d] = vysledekClip[c][d];
break;
case '%': vysledekClip[c][d] = prvni[c][d] % druha[c][d];
vysledek[c][d] = vysledekClip[c][d];
break;
case '*': vysledekClip[c][d] = prvni[c][d] * druha[c][d];
vysledek[c][d] = vysledekClip[c][d];
break;
default: error(SPATNY_OP);
break;
}
vysledek[c][d] = vysledekClip[c][d];
}
}
return 0;
}
void vypisMatice(int radky, int sloupce, int **matice)
{
int c;
int d;
for (c = 0; c < radky; c++) {
for (d = 0; d < sloupce; d++) {
printf("%i\t", matice[c][d]);
} printf("\n");
}
}
void vypisMaticeDoSouboru(int radky, int sloupce, int **matice, char nazevSouboru[MAX_DELKA_SOUBORU])
{
int c;
int d;
for (c = 0; c < radky; c++) {
for (d = 0; d < sloupce; d++) {
printf("%i\t", matice[c][d]);
} printf("\n");
}
}
You have a problem with the 'second' array. You allocate an array of *n pointers to int but fill *m elements in that array:
second = (int **) malloc(*n * sizeof(int*));<p>
for (int i = 0; i < *m; i++) {

char array input with space

my program works fine if i give hard code value to char *w="ls -l" but i am trying to take input form user not working help my code:: using input error occur
i don't understand the concept of fgets using fgets its gives the garbig value to execv
#include<stdio.h>
#include<sys/wait.h>
#include<stdbool.h>
void func(char **arr, char *w)
{
int i = 0, j = 0, k = 0;
char temp[100];
for (i = 0; i < 100; i++)
{
if (w[i] == '')
{
arr[k] = temp;
arr[k+1] = NULL;
break;
}
if (w[i] == ' ')
{
arr[k] = temp;
k++;
j = 0;
}
else
{
temp[j] = w[i];
j++;
}
}
}
int main()
{
char *n = "/bin/ls";
char *arr[10] = {''};
char p[100] = {''};
char *w = "ls -l";
int i = 0;
//printf("bilal-hassan-qadri $ >>");
//fgets(p, 100, stdin);
arr[2] = NULL;
bool found = false;
for (i = 0; i < sizeof(w); i++)
{
if (w[i] == ' ')
{
found=true;
func(arr,w);
break;
}
}
if (!found)
arr[0] = w;
int status;
int id = fork();
if (id == 0)
{
if (execv(n,arr) < 0)
{
printf("invalid commandn");
}
else
{
printf("ninvalid command");
}
}
else
{
wait(&status);
}
}
In the function func, You have to copy the string to elements of arr
instead of just passing the address of temp, which will vanish on leaving the function.
You can use strdup instead of copy_string if your system supports it.
You have to terminate the string in temp before copying it.
Empty string constant '' seems invalid. You shouldn't use it.
fgets stores new-line character \n if it exists. Check for it and remove if it isn't wanted.
Fixed code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<stdbool.h>
char *copy_string(const char *str) {
char *s = malloc(strlen(str) + 1);
if (s) strcpy(s, str); else {perror("malloc"); exit(1);}
return s;
}
void func(char **arr, char *w)
{
int i = 0, j = 0, k = 0;
char temp[100];
for (i = 0; i < 100; i++)
{
if (w[i] == '\0' || w[i] == '\n')
{
temp[j] = '\0';
arr[k] = copy_string(temp);
arr[k+1] = NULL;
break;
}
if (w[i] == ' ')
{
temp[j] = '\0';
arr[k] = copy_string(temp);
k++;
j = 0;
}
else
{
temp[j] = w[i];
j++;
}
}
}
int main(void)
{
char *n = "/bin/ls";
char *arr[10] = {NULL};
char p[100] = {0};
char *w = "ls -l";
int i = 0;
//printf("bilal-hassan-qadri $ >>");
fgets(p, 100, stdin);
w = p;
arr[2] = NULL;
bool found = false;
for (i = 0; w[i] != '\0'; i++)
{
if (w[i] == ' ')
{
found=true;
func(arr,w);
break;
}
}
if (!found)
arr[0] = w;
int status;
int id = fork();
if (id == 0)
{
if (execv(n,arr) < 0)
{
printf("invalid commandn");
}
else
{
printf("ninvalid command");
}
}
else
{
wait(&status);
for (i = 0; arr[i] != NULL; i++) free(arr[i]);
}
return 0;
}

Double free/corruption?

typedef struct {
int *info;
} row;
struct {
row* head;
int len;
int size;
} list;
int main{
list.len = 0;
list.size = 1;
list.head = malloc(list.size * sizeof(row));
//...... some other code that calls addRow (list.len) times
for (i = list.len - 1; i > 0; i--) {
free(list.head[i].info);/*****HERE**********/
}
free(list.head);
}
void addRow(int* data) {
int i;
if (list.len == list.size) {
row *temp = malloc(sizeof(row) * list.size * 2);
if (temp == NULL) {
fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
return;
}
for (i = 0; i < list.len; i++) {
temp[i] = list.head[i];
}
free(list.head);
list.head = temp;
}
list.head[list.len].info = malloc(sizeof(int) * numCols);
for (i = 0; i < numCols; i++) {
list.head[list.len].info[i] = data[i];
}
list.len++;
}
This is the code that I used to addRow is were I malloc all the data. and I don't see why I'm getting a double free/ corruption error. At the area I marked HERE, I believe I am malloc-ing for all instances of info in the row struct, These line are the only ones doing malloc/free.
I just want to get into the habit free-ing properly when terminating the program.
FULL PROGRAM:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
typedef struct {
int *info;
} row;
struct {
row* head;
int len;
int size;
} list;
static int sortCol, numCols;
int qSortCompare(const void*, const void*);
void printList();
int processInput();
void nullify(char*, int);
int main(int n, char **args) {
sortCol = 1;
numCols = 0;
if (n > 1 && args[1][0] == '-' && args[1][1] == 'c') {
sortCol = atoi(args[2]);
}
list.len = 0;
list.size = 1;
list.head = malloc(list.size * sizeof(row));
processInput();
if (sortCol < 1 || sortCol > numCols) {
fprintf(stderr, "Error (enter): (Line ##) Invalid column to sort.\n");
return 1;
}
printList();
qsort(list.head, list.len, sizeof(row), &qSortCompare);
printf("\n");
printList();
int i;
printf("add1:%p\nadd2:%p\n", list.head[0].info, list.head[1].info);
for (i = 0; i < list.len; i++) {
free(list.head[i].info);
}
free(list.head);
return 0;
}
void nullify(char* str, int n) {
int i;
for (i = 0; i < n; i++)
str[i] = '\0';
}
int parseInt(char *str, int index) {
int num = -1;
sscanf(str + index, "%d", &num);
return num;
}
void addRow(int* data) {
int i;
if (list.len == list.size) {
row *temp = malloc(sizeof(row) * list.size * 2);
if (temp == NULL) {
fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
return;
}
for (i = 0; i < list.len; i++) {
temp[i] = list.head[i];
}
free(list.head);
list.head = temp;
}
list.head[list.len].info = malloc(sizeof(int) * numCols);
if (list.head[list.len].info == NULL) {
fprintf(stderr, "Error (enter): (Line ##) Insufficient memory.\n");
return;
}
for (i = 0; i < numCols; i++) {
list.head[list.len].info[i] = data[i];
}
list.len++;
}
int processInput() {
int i, maxChars = 200, totalN = 0;
int *nums, curNumIndex = 0, onNum, curNum;
numCols = maxChars / 2;
nums = (int*) (malloc(sizeof(int) * numCols));
char str[maxChars], ch;
for (i = 0; i < numCols; i++) {
nums[i] = -1;
}
while (!feof(stdin)) {
nullify(str, maxChars);
fgets(str, maxChars, stdin);
onNum = isdigit(str[0]);
curNumIndex = 0;
for (i = 0; i < maxChars; i++) {
ch = str[i];
if ((!isspace(ch)) && (!isdigit(ch)) && (ch != '\0')) {
fprintf(stderr, "Error 1: (Line ##) Invalid char in input.\n");
//return 0;
}
if (isspace(ch) && onNum) {
curNum = parseInt(str, curNumIndex);
curNumIndex = i;
nums[totalN % numCols] = curNum;
totalN++;
if (totalN % numCols == 0)
addRow(nums);
} else {
onNum = isdigit(str[i]);
}
if (ch == '\n' || ch == '\0')
break;
}
if (numCols > totalN) {
if (totalN > 0) {
numCols = totalN;
addRow(nums);
} else {
fprintf(stderr,
"Error (enter): (Line ##) Invalid first line of input.\n");
}
}
if (ch != '\n' && ch != '\0') {
fprintf(stderr,
"Error (enter): (Line ##) A row from input too long.\n");
//return 0;
}
}
return 1;
}
int qSortCompare(const void *c1, const void *c2) {
row *t1, *t2;
t1 = (row*)c1;
t2 = (row*)c2;
return t1->info[sortCol - 1] - t2->info[sortCol - 1];
}
void printList() {
int i, j;
for (i = 0; i < list.len; i++) {
for (j = 0; j < numCols; j++) {
printf("%10d ", list.head[i].info[j]);
}
printf("\n");
}
}
Program needs a EOF terminated input of integer numbers. Specifically with the same number of integers before the newline.
UPDATE: I used gdb to analysis the free part i it only fails on the second iteration, using for(i = 0; i < list.len; i++) and for(i = list.len - 1; i > 0 ; i--)
Another thing is that I don't see the update to list.size (it should be updated when resizing head)
"I just want to get into the habit free-ing properly when terminating the program."
The correct way to handle things like this is to free a non-NULL pointer and then set the pointer to NULL.
For example:
int* x = malloc (sizeof (int));
if (x != NULL) {
free (x);
x = NULL;
}
/* Misc. Code ... */
/* Now for whatever reason, you want to free x again */
/* This branch is never triggered, because you were smart enough to set x to NULL
* when you freed it the first time...
*/
if (x != NULL) {
free (x);
x = NULL;
}

Resources