I have a file where i have some records like that:
test one; test one; test one; 1
test two; test two; test two; 2
I need to sort those records according to the last number, so in my previous example the second record should be at the first place, since 2>1. For this, i'm trying to add each record to an array and then apply an insertion sort algorithm. I have some problems adding each part to an array, here is my current effort:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 100
int main() {
char one[MAXLEN] = {};
char two[MAXLEN] = {};
char three[MAXLEN] = {};
int st[MAXLEN] = {};
int i, j;
FILE * fpointer = fopen("clients.txt", "r");
for (i = 0; i < MAXLEN; i++) {
fscanf(fpointer, "%s%s%s%d", &one[i], &two[i], &three[i], &st[i]);
}
for (j = 0; j < MAXLEN; j++) {
printf("%s", one[i]);
}
fclose(fpointer);
return 0;
}
In this example, i tried to add each field to an array, the second for loop is just a test to check whether or not data is being added to the array properly, but it's not.
you're currently scanning your data into 3 strings, shifting the offset by 1 each time, instead of 3 tables of strings.
You need to declare your data some other way. For example a 2D array of char
I suggest a structure instead, and an array of structures, so you have only one index (Here I'm assuming that max size for string is 100):
typedef struct Element
{
char one[100];
char two[100];
char three[100];
int st;
};
Element elements[MAXLEN];
now scan like this:
for (i = 0; i < MAXLEN; i++) {
Element *e = elements+i; // pointer on ith element
fscanf(fpointer, "%99s%99s%99s%d", e->one, e->two, e->three, &e->st);
}
Use & on the integer, not on the strings (already pointers, they are). Also maybe it's good to check that fscanf returns 4 (error checking). The 99s ensures that you're not overflowing your strings (max len: 100 with nul terminator)
Aside: if you have strings with spaces in it, scanf isn't going to work properly, you'll have to use fgets then strtok on the semicolons to get the items
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 100
#define MAXWORDS 50
int main() {
char one[MAXWORDS][MAXLEN] = {};
char two[MAXWORDS][MAXLEN] = {};
char three[MAXWORDS][MAXLEN] = {};
int st[MAXWORDS][MAXLEN] = {};
int i, j;
FILE * fpointer = fopen("clients.txt", "r");
for (i = 0; i < MAXWORDS; i++) {
fscanf(fpointer, "%s%s%s%d", one[i], two[i], three[i], st[i]);
}
for (j = 0; j < MAXWORDS; j++) {
printf("%s", one[j]);
}
fclose(fpointer);
return 0;
}
check this program its working...!
In this program you used the fscanf() function which can fetch data from file word by word . Here you need to take care that fscanf() wont give you the spaces as well as '\n'- line termination character .
and thanks for your time. I apologize in advance I am new to C programming and posting on stack overflow. Any information I may have left out and questions you have please ask.
I have this lab I am working on for my class and I'm having trouble understanding how the dreaded pointers operate. First I will explain the lab instructions.
First, I am to create an array of 200 words with a max length of 30+1 for null.
Next, call functions I need to create which include:
A read function which reads words from a file into the array. I must use fopen and fscanf functions.
A function to convert a string to lowercase using the ASCII codes of each character. (Must use pointers)
A function to return the length of a string.(Can't use strlen function and must use pointers)
A function with three parameters(array of words, # of words in array, and an int length). Function returns the number words in the array that match the int length.
A print function to print all the words in the array.
The IDE I am using is Dev C++ its been wonky so I have also been using netbeans.
I have only attempted to create the read, print, and converting to lowercase functions. I first tried to read the file and print the array in main. The file I'm reading is created by me it contains a short sentence which follows exactly:
There ARE so MANY words in HERE
EDIT- Updated main code to current with working lowercase loop inside main.
#define rows 200 //How many words allowed in array.
#define cols 31 //How many characters allowed for each word.
void lowercase(char* words, int count);
int read(char (*words)[cols]);
void print(char (*words)[31], int count);
int main(int argc, char *argv[]){
char words[rows][cols];
int i, j;
int count = read(words);
print(words, count);
/*
//make words lowercase
for(i = 0;i<count;i++){
for(j = 0;j<cols;j++){
if(words[i][j]!=0){
if(words[i][j]<91 && words[i][0]>64)
words[i][j] = words[i][j]+32;
}
}
}*/
for(i = 0;i < count;i++){
lowercase(*words+i, count);
}
print(words, count);
return 0;
}
The code is poorly written and managed properly I'm just trying to get everything to work first then it will be more appropriate. The first printf output comes out how it should:
Array [0]: There
Array [1]: ARE
Array [2]: so
Array [3]: MANY
Array [4]: words
Array [5]: in
Array [6]: HERE
Then the print function I have prints out the words correctly in the array but it includes all 30 spaces for each word instead of just the word. This is how it is written I need to change it.
void print(void *array, int SIZE){
int i,
j;
char *charArray = (char *) array;
for( j = 0; j < SIZE; j++ ){
for( i = 0; i < SIZE; i ++){
printf( "%c ", charArray[j*SIZE + i] );
}
printf( "\n" );
}
}
The tolower function I created was partially working converting the first letter of each word to lowercase. Now it is broke and do not remember what I have changed.
EDIT- updated lowercase function. The lowercase in main works exactly but with this function it doesn't convert all the words to lowercase it stops at the third word the rest are the same.
void lowercase(char *words, int count){
int j;
for(j = 0;j<cols;j++){
if(words[j]!=0){
if(words[j]<91 && words[j]>64)
words[j] = words[j]+32;
}
}
}
I tried to move the read code in main to its own function also trying to mimic the print code with the pointers but when I run the program it stalls and the exe file stopped working window pops up with command prompt.
No errors or warnings in IDE.
int read(void *array){
FILE *file;
int i,
j;
char *words = (char *) array;
file = fopen("words.txt", "r");
//STORE IN ARRAY
for(i=0;i<7;i++)
fscanf(file,"%s", words[i]);
}
If you have not figured out I have no idea when or how to use pointers or addresses. I have been taught basically all of C in literally 12 hours which is in my opinion not enough time to learn the language at all especially understand it efficiently. Any help will be greatly appreciated. Thank You.
By casting a 2-dimensional array down to a char*, you have lost some information. If you read the words in correctly, then in memory, your array might look like this:
0 10 20 30
|.........|.........|.........|.
There
ARE
so
MANY
words
in
HERE
To access words[1] the compiler is automatically offsetting 31 bytes from the beginning of the array.
Your problem is that after you cast words to char*, then the compiler no longer knows about the 2D structure, and words[1] will now only offset 1 byte from the beginning of the array.
A simple solution is to redefine your read function:
int read(char words[][31])
{
FILE *file;
int i, j, count = 0;
file = fopen("words.txt", "r");
for (i=0; i<7; i++)
{
count += (1 == fscanf(file, "%s", words[i]));
}
return count;
}
Now the compiler knows that the memory stride size for words[i] is 31 char values.
Similar thing with print:
void print(char words[][31], int count)
{
int i;
for( i = 0; i < count; i ++)
{
printf( "%s\n", words[i] );
}
}
fix like this:
#include <stdio.h>
#include <stdlib.h>
//Stringification
#define S_(n) #n
#define S(n) S_(n)
//Information to be shared across the whole area
#define MAX_ROWS 200
#define MAX_WORD_LENGTH 30
#define COLS (MAX_WORD_LENGTH + 1)
#define DATA_FILE "words.txt"
int read(void *array);
void print(void *array, int rows);
int main(void){
char words[MAX_ROWS][COLS];
int rows;
rows = read(words);
print(words, rows);
return 0;
}
int read(void *array){
FILE *file = fopen(DATA_FILE, "r");
if(file == NULL){
perror("fopen:");
exit(EXIT_FAILURE);
}
char *words = array;
int rows;
for(rows = 0; rows < MAX_ROWS; ++rows, words += COLS){
if(fscanf(file, "%" S(MAX_WORD_LENGTH) "s", words) == EOF)
break;
}
fclose(file);
return rows;
}
void print(void *array, int rows){
char *words = array;
for(int r = 0; r < rows; ++r, words += COLS){
printf("Array [%d]: %s\n\n", r, words);
}
}
This is in C language, I'm trying to sort the data from the 2015 population in the text file in ascending order using a function and pointers to the array that I stored the state in. I want to try use a swapping algorithm within this function.
How do I sort the data using my ascensionOrder function from the 2015 population then output it in acending order?
Here is my code: `
#include <stdio.h>
#define FILENAME "PopulationData.txt"
int main(void)
{
void acensionOrder(int *populationData);
void replace(char*s, char a, char b);
char header[3][30];
char state[51][32];
int census[51][2];
FILE *myfile;
myfile = fopen(FILENAME,"r");
int x;
if (myfile== NULL)
{
printf("Errror opening file. \n");
}
else
{
fscanf(myfile, "%s%s%s", header[0], header[1], header[2]);
for (x = 0; x < 51; x++)
{
//fscanf(myfile, "%31s%d%d", state[x], &census[x][0], &census[x][1]); //testing
fscanf(myfile, "%*2c%s %d %d", state[x], &census[x][0], &census[x][1]); //Stores the text in the data file into array
replace(state[x], '_', ' '); //Replaces the lines
replace(state[x], '.', ' '); //Replaces the periods
//printf("%s\t%d\t%d\n", state[x], census[x][0], census[x][1]);
//printf("%2d %31s %10d %10d\n", x, state[x], census[x][0], census[x][1]); //Testing of sort
}
}
acensionOrder(&census[x][1]);
fclose(myfile);
//getchar();
//getchar();
return 0;
}
void acensionOrder(int *populationData) //This function sorts the 2015 data into ascending order
{
int j,k,m;
int sorted2015;
for(k=0; k<m; k++)
{
//m=k;
for(j=0; j<(m-1); j++)
{
if(*(populationData+j)<*(populationData+m))
//m=j;
sorted2015=*(populationData+m);
*(populationData+m)=*(populationData+k);
*(populationData+k)=sorted2015;
}
}
printf("%d\n", sorted2015);
}
void replace(char*s, char a, char b) //This function uses pointers to find characters
{
for(;*s; s++)
{
if(*s==a)*s = b;
}
}
`
Here is the text file the program reads from:
Text file for US population
There was a couple of bugs in your program especially in the acensionOrder() function which I completely changed it to a bubbleSort() that keeps swapping the array elements until it is sorted. Keep in mind bubbleSort() is easy but expensive. So, you may want to change it to a o(nlogn) sorting algorithm like quicksort() or mergesort(). Now, let's see what do you need to add to make your program sort the input file.
Before reaching the main() function you need to import some standard C libraries and also declare your function signatures. Previously, you put the function signatures in the main() function which was wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILENAME "PopulationData.txt"
void bubbleSort(int arr1[][2], char arr2[][32], int len);
void replace(char *s, char a, char b);
For main(), make sure to add the argc, *argv[] arguments. Basically, in the main() function, we open the file, start parsing each line using fscanf(), trim the . and _ characters, close the file, call the bubbleSort() and finally print the sorted results.
int main(int argc, char *argv[])
{
char header[3][30];
memset(header, 0, sizeof(header[0][0]) * 3 * 30);
char state[51][32];
memset(state, 0, sizeof(state[0][0]) * 51 * 32);
int census[51][2];
memset(census, 0, sizeof(census[0][0]) * 51 * 2);
FILE *myfile;
myfile = fopen(FILENAME,"r");
int x;
if (myfile== NULL)
{
printf("Errror opening file. \n");
return(1);
}
fscanf(myfile, "%s %s %s", header[0], header[1], header[2]);
printf("%s %s %s\n",header[0], header[1], header[2]);
for (x = 0; x < 51; x++)
{
fscanf(myfile, "%*2c%s %d %d", state[x], &census[x][0], &census[x][1]);
replace(state[x], '_', ' ');
replace(state[x], '.', ' ');
printf("[%02d] %20s: %8d %8d\n", x, state[x], census[x][0], census[x][1]);
}
fclose(myfile);
bubbleSort(census, state, 51);
printf("%s %s %s\n",header[0], header[1], header[2]);
for(x = 0; x < 51; x++)
{
printf("[%02d] %20s: %8d %8d\n", x, state[x], census[x][0], census[x][1]);
}
return(0);
}
The next part is the abubbleSort() implementation. It accepts the census and state arrays along with their length and starts sorting them based on the second dimension of census (censos[j][1]) which contains the 2015 population. Each time, we want to replace an element in censos[j][1], we need to replace the corresponding elements in censos[j][0] and state[j].
void bubbleSort(int arr1[][2], char arr2[][32], int len)
{
int i;
int j;
int tmp0;
int tmp1;
char tmp2[32];
memset(tmp2, '\0',32);
for(i = len - 1; i >= 0; i--)
{
for(j = 0; j < i; j++)
{
if(arr1[j][1] > arr1[j+1][1])
{
tmp0 = arr1[j+1][0];
tmp1 = arr1[j+1][1];
strncpy(tmp2, arr2[j+1], 32);
arr1[j+1][0] = arr1[j][0];
arr1[j+1][1] = arr1[j][1];
strncpy(arr2[j+1], arr2[j], 32);
arr1[j][0] = tmp0;
arr1[j][1] = tmp1;
strncpy(arr2[j], tmp2, 32);
memset(tmp2, '\0',32);
}
}
}
}
And this is your replace() function which I'm pasting it here AS IS.
void replace(char*s, char a, char b)
{
for(;*s; s++)
{
if(*s==a)*s = b;
}
}
Finally, since you're dealing with strings, you may notice that I extensively use memset() to make the array elements NULL terminated to avoid plausible printing problems with printf() function.
I'm trying to sort the data from the 2015 population in the text file
in ascending order using a function and pointers to the array
As a number of comments have pointed out, you can accomplish your stated goal simply by using the qsort algorithm. The comparison function you write for qsort will accept a pointer to an element within any type of array of objects you pass to it. In your case, holding the data in an array of struct containing the name of the state, the census and estimate would make things quite easy. You could use a simple struct with a single character array (24-char will hold your longest name) and two integers. Adding a typedef to stcen for your state census is for convenience, e.g.
typedef struct { /* structure with name census and estimate */
char name[NMLEN];
int cen, est;
} stcen;
Using qsort, you simply want an ascending sort on an integer value, which for a standard integer array would take the form:
int cmpint (const void *a, const void *b)
{
/* (a > b) - (a < b) */
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
}
which if you prefer to cast before the return, it is just shorthand for:
const int ia = *(const int *)a; // casting pointer types
const int ib = *(const int *)b;
return (ia > ib) - (ia < ib);
(returning the difference of the comparison, avoids potential for overflow)
Using an array of struct is no different, you simply dereference the pointers passed to the comparison function until you are referencing the integer value you wish to sort by, e.g. in the case above:
/* integer comparison of struct on 'cen' */
int cmpcen (const void *a, const void *b) {
return ((((stcen *)a)->cen > ((stcen *)b)->cen) -
(((stcen *)a)->cen < ((stcen *)b)->cen));
}
The remainder is just reading your data from your data file, discarding the heading row, and storing the remaining values in your array of struct. Since you know you have 51 states, your longest state name will fit in 24-chars (and a formatting integer width of 9-chars to make printing pretty) you can use an enum to specify the constants for your program. Putting the pieces together, you can do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
enum { IWDTH = 9, NMLEN = 24, NSTATE = 51 }; /* constants used */
typedef struct { /* structure with name, census and estimate */
char name[NMLEN];
int cen, est;
} stcen;
/* integer comparison of struct on 'cen' */
int cmpcen (const void *a, const void *b) {
return ((((stcen *)a)->cen > ((stcen *)b)->cen) -
(((stcen *)a)->cen < ((stcen *)b)->cen));
}
int main (int argc, char **argv) {
int i = 0, ndx = 0; /* general i, index */
stcen census[NSTATE] = {{ .name = "" }}; /* array of struct */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "file open failed '%s'\n", argv[1]);
return 1;
}
fscanf (fp, "%*[^\n]%*c"); /* strip header line */
/* read each line, input to struct, advance index */
while (ndx < NSTATE && fscanf (fp, " %s %d %d",
census[ndx].name, &census[ndx].cen, &census[ndx].est) == 3) {
ndx++;
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
qsort (census, ndx, sizeof *census, cmpcen); /* sort on census */
for (i = 0; i < ndx; i++) /* output results */
printf (" %-*s %*d %*d\n", NMLEN, census[i].name,
IWDTH, census[i].cen, IWDTH, census[i].est);
return 0;
}
The program simply expects the name of the file to read data from as the first argument (or it will read from stdin if no argument is given). Applied to your data, you get:
Example Use/Output
$ ./bin/census < ../dat/census.txt
Wyoming 563626 586107
District_of_Columbia 601723 672228
Vermont 625741 626042
North_Dakota 672591 756927
Alaska 710231 738432
South_Dakota 814180 858469
Delaware 897934 945934
Montana 989415 1032949
Rhode_Island 1052567 1056298
New_Hampshire 1316470 1330608
Maine 1328361 1329328
Hawaii 1360301 1431603
Idaho 1567582 1654930
Nebraska 1826341 1896190
West_Virginia 1852994 1844128
<snip>
Look things over and consider the qsort approach instead of rolling-your-own sort routine. The chances are very good that qsort will be much more efficient and less prone to errors. Let me know if you have any questions.
#include <stdio.h>
#define FILENAME "C:\\PopulationData.txt"
#define NUM 51
int main(void)
{
void acensionOrder(int *populationData);
void replace(char*s, char a, char b);
char header[3][30];
char state[NUM][32];
int census[2][NUM];
FILE *myfile;
myfile = fopen(FILENAME, "r");
int x;
if (myfile == NULL)
{
printf("Errror opening file. \n");
}
else
{
fscanf(myfile, "%s%s%s", header[0], header[1], header[2]);
for (x = 0; x < NUM; x++)
{
//fscanf(myfile, "%31s%d%d", state[x], &census[x][0], &census[x][1]); //testing
fscanf(myfile, "%*2c%s %d %d", state[x], &census[0][x], &census[1][x]); //Stores the text in the data file into array
replace(state[x], '_', ' '); //Replaces the lines
replace(state[x], '.', ' '); //Replaces the periods
//printf("%s\t%d\t%d\n", state[x], census[x][0], census[x][1]);
//printf("%2d %31s %10d %10d\n", x, state[x], census[x][0], census[x][1]); //Testing of sort
}
}
acensionOrder(&census[1][0]);
fclose(myfile);
getchar();
getchar();
return 0;
}
void acensionOrder(int *populationData) //This function sorts the 2015 data into ascending order
{
int j, k, m;
m = NUM;
int sorted2015;
for (k = 0; k<m; k++)
{
//m=k;
for (j = k+1; j<m; j++)
{
if (*(populationData + j) < *(populationData + k ))
{
sorted2015 = *(populationData + j);
*(populationData + j ) = *(populationData + k);
*(populationData + k) = sorted2015;
}
//m=j;
}
}
for (k = 0; k<m; k++)
printf("%d ", *(populationData + k));
}
void replace(char*s, char a, char b) //This function uses pointers to find characters
{
for (; *s; s++)
{
if (*s == a)*s = b;
}
}
I wanted to try and copy parts of strings which are already stored in one array of strings to another empty array. (I think called array of pointers to char arrays )
I would like to copy the first 3 characters of each string and store them in the second array and then print them out - like so
AAA
BBB
CCC
DDD
EEE
FFF
Here is my code.
void main()
{
/*ARRAY 1*/
char *line1 = "AAAAA";
char *line2 = "BBBBB";
char *line3 = "CCCCC";
char *line4 = "DDDDD";
char *line5 = "EEEEE";
char *line6 = "FFFFF";
char *array1[6];
array1[0] = line1;
array1[1] = line2;
array1[2] = line3;
array1[3] = line4;
array1[4] = line5;
array1[5] = line6;
int i;
char *array_main[6];
for(i = 0; i<6 ; i++ ) {
array_main[i] = ("%*.*s\n",1,3,array1[i]);
printf("%s", array_main[i]);
printf("\n");
}
}
do i need to do a malloc here ? (for array_main[i]) from what i understand, I am basically just copying the address of the particular characters to array_main's elements.
EDIT - Sorry, I should have made this clearer, I want to collect the strings in array_main and then print them in order outside of the loop which actually copies the data.
You are copying pointers to statically declared strings to an array. That's theoretically fine. Howevery, you want to cut off the remainder of the strings, so you need to prepare memory for the target strings, because if you write to the strings you will invoke undefined behaviour.
This line:
array_main[i] = ("%*.*s\n",1,3,array1[i]);
definitely doesn't do what you want though. I think this shouldn't even compile.
You loop over the array and malloc the appropriate size of bytes (3+1), then copy over the parts of the string that you want (don't forget the 0-byte at the end).
So it should look like this:
for(i = 0; i < 6; i++)
{
array_main[i] = malloc(4);
snprintf(array_main[i], 4, "%.3s", array[i]);
printf("%s\n", array_main[i]);
free(array_main[i]);
}
A simpler version (with unneccessary memeory overhead) would be this:
for(i = 0; i < 6; i++)
{
array_main[i] = strdup(array[i]);
array_main[i][3] = 0;
printf("%s\n", array_main[i]);
free(array_main[i]);
}
#include <stdio.h>
#include <string.h>
int main(void){
const char *array1[6] = {"AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEE", "FFFFF" };
char array_main[6][4] = {{0}};//4 : 3 + 1 (+1 for End of string('\0'))
int i;
for(i = 0; i<6 ; i++ ) {
strncpy(array_main[i], array1[i], 3);
printf("%s\n", array_main[i]);
}
return 0;
}
I want to read the following lines from STDIN and save the values in c:
A:2
B:3
C:AAAA1
C:AASC2
C:aade3
D:1
D:199
Here is my c program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <sys/time.h>
int main(int argc, char **argv)
{
char buf[BUFSIZ];
short a = 0;
short b = 0;
short anzb=0;
short anza=0;
char *c
short *d;
short i;
while (fgets(buf, BUFSIZ, stdin) != NULL)
{
if (buf[strlen(buf)-1] == '\n') {
char *isa = strstr(buf, "A:");
char *isb = strstr(buf, "B:");
char *isc = strstr(buf, "C:");
char *isd = strstr(buf, "D:");
if(isa){
char *sep = substring(isa,3,strlen(isa));
a = atoi(sep);
d = malloc(a * sizeof(short));
}else if(isb){
char *sep = substring(isb,3,strlen(isb));
b = atoi(sep);
c = malloc(b * sizeof(char));
}else if(isc){
char *sep = substring(isc,3,strlen(isc));
c[anzc] = sep;
anzc++;
}else if(isd){
char *sep = substring(isd,3,strlen(isd));
d[anzd] = sep;
anzd++;
}
}
}
printf("%i\n", a);
printf("%i\n", b);
for(i=0; i<=anzc-1;i++){
printf("%c", c[i]);
}
return 0;
}
I am new in c so i dont't have much knowledge about pointers and arrays so i hope you could help me.
After the values A: and B: are read and stored in a and b i could create my array for the lines of c and d. And i think here is my problem. I dont know how i could create an array at this time in my program. I tried with malloc and other things but there is my knowledge zu small for.
I only want to create an array at the time if i have read the values (sizes) for c and d (A and B).
And then i want to save the values in the array.
I hope you could help me to fix my code. I have tried much at this day but nothing worked and i am now very helpless.
EDIT:
New try where i get an segmentation fault 11:
else if(isb){
char *sep = substring(isb,8,strlen(isb));
b = atoi(sep);
c = malloc(b * sizeof(char*));
int i;
for (i = 0; i < subst; i++)
{
c[i] = malloc(13);
}
}else if(isc){
char *sep = substring(isc,8,strlen(isc));
strcpy(c[anzc], &buf[3]);
anzc++;
}
Your allocation is more or less correct however you're overlooking some details. B provides you a value of 3, that is how many entries there are for C, not the length of each. You then allocated a single array when you in fact need a 2-D array which should be of type char* this array will point to 3 other arrays which will contain each of the values on the C lines. So;
This line c = malloc(b * sizeof(char)); needs to be c = malloc(b * sizeof(char*));
Then you need to do;
int i;
for (i = 0; i < b; i++)
{
c[i] = malloc(length); // where length is some arbitrary buffer length
// because you have no way of knowing the length of the individual strings.
}
After this you can use strcpy to copy the lines into each of the char arrays you've allocated in the for loop.
So to accomplish the copy you need to do something like this;
int iC = 0;
// outside of the while loop we need a control var track the index
// of the c array. it needs to work independent of the normal iteration.
//inside the while loop
else if(isc){
strcpy(c[iC], &buf[3])
iC++;
}