how to sort a 2D char array - c

I am writing a program that opens a file (input.txt) and reads the lines into a 2D array so I can sort the lines by length.
These are my created sentences for testing (input.txt)
1. hello world
2. john Jones at Brook Mountains
3. Frozen Styx
4. altair
5. John Doe and Jane Doe
6. Cranium
my source.c
#define MAX_LINES 100
#define MAX_LEN 1000
int main(void) {
char data[MAX_LINES][MAX_LEN];
FILE* fread = fopen("C:\\Users\\EXAMPLE\\desktop\\input.txt", "r");
if (fread == NULL) {
printf("ERROR\n");
return 1;
}
int line = 0;
while (!feof(fread) && !ferror(fread)) {
if (fgets(data[line], MAX_LEN, fread) != NULL) {
line++;
}
}
fclose(fread);
for (int i = 0; i < line; i++) {
printf("%s", data[i]);
}
return 0;
}
I managed to copy those lines and input them into a 2D array and am able to print it for testing, but I don't know how to go about sorting them by length. I found some close ideas but the first option didn't work for me. the second option is close but that sorts it's alphabetically.
option 1
option 2

The first attempt doesn't work because you don't have an array of pointers, but an array of arrays. Also it's bad practice to allocate such huge arrays locally, since that may lead to stack overflow.
You could fix the code like this:
Change it to char* data [MAX_LINES];
Do fgets into a temporary buffer of MAX_LEN size.
Assign read strings to data with for example data[i] = strdup(tmpbuf);.
Now you can use the qsort and comparison callback function posted in your first attempt, because it assumes an array of character pointers and that's what you have now.
Remember to free() every data[i] when done using them.

Here's a possible implementation using hardcoded data and featuring qsort; note that I also added lexicographic ordering in case two strings have the same length.
The user will have to make the necessary edits to implement import from file. I am just showing one possible implementation of the sorting function.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_LINES 6
int compare_lengths(const void *a, const void *b)
{
const char* str1 = *(const char* const*)a; // proper casting is crucial!
const char* str2 = *(const char* const*)b;
size_t len1 = strlen(str1);
size_t len2 = strlen(str2);
if (len1 < len2)
return -1;
if (len2 < len1)
return +1;
return strcmp(str2, str1); // same length -> sort lexicographically
}
int main(void) {
char *data[MAX_LINES] = {0};
data[0] = "hello world";
data[1] = "john Jones at Brook Mountains";
data[2] = "Frozen Styx";
data[3] = "altair";
data[4] = "John Doe and Jane Doe";
data[5] = "Cranium";
qsort(data, sizeof(data)/sizeof(char*), sizeof(char*), compare_lengths);
for (int i=0; i<MAX_LINES; ++i)
printf("%s -> %ld\n", data[i], strlen(data[i]));
return 0;
}
Code in action here.

Related

Keep getting segmentation fault and malloc error for reading stdin

I tried to run a C program that reads from stdin and stores them in char**, but I keep getting either malloc: Incorrect checksum for freed object or segmentation fault errors whenever realloc is used to increase the size of the pointer. Can anyone point out what I did wrong? The program is example 7_14 from beginning C 5th ed. Below is the code I ran without using C11 optional string functions because my clang complier doesn't seem to support them.
// Program 7.14 Using array notation with pointers to sort strings
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define BUF_LEN 100
#define COUNT 5
int main(void)
{
char buf[BUF_LEN]; // Input buffer
size_t str_count = 0; // Current string count
size_t capacity = COUNT; // Current maximum number of strings
char **pS = calloc(capacity, sizeof(char *)); // Pointers to strings
char **psTemp = NULL; // Temporary pointer to pointer to char
char *pTemp = NULL; // Temporary pointer to char
size_t str_len = 0; // Length of a string
bool sorted = false; // Indicated when strings are sorted
printf("Enter strings to be sorted, one per line. Press Enter to end:\n");
// Read in all the strings
char *ptr = NULL;
while (*fgets(buf, BUF_LEN, stdin) != '\n')
{
if(str_count == capacity)
{
capacity += capacity/4;
if (!(psTemp = realloc(pS, capacity))) return 1;
pS = psTemp;
}
str_len = strnlen(buf, BUF_LEN) + 1;
if (!(pS[str_count] = malloc(str_len))) return 2;
strcpy(pS[str_count++], buf);
}
// Sort the strings in ascending order
while(!sorted)
{
sorted = true;
for(size_t i = 0; i < str_count - 1; ++i)
{
if(strcmp(pS[i], pS[i + 1]) > 0)
{
sorted = false;
pTemp = pS[i];
pS[i] = pS[i+1];
pS[i+1] = pTemp;
}
}
}
// Output the sorted strings
printf("Your input sorted in ascending sequence is:\n\n");
for(size_t i = 0; i < str_count; ++i)
{
printf("%s", pS[i]);
free(pS[i]);
pS[i] = NULL;
}
free(pS);
pS = NULL;
return 0;
}
Example execution result:
Enter strings to be sorted, one per line. Press Enter to end:
Many a mickle makes a muckle.
A fool and your money are soon partners.
Every dog has his day.
Do unto others before they do it to you.
A nod is as good as a wink to a blind horse.
The bigger they are, the harder they hit.
[1] 82729 segmentation fault ./7_14

Character alignment weird output

My code is at the bottom. I'm trying to take two strings and change them as per the edit transcript that I receive. I wrote my code but I don't understand why I'm getting such a weird output. My goal is to first store the values of the two strings then make them into a 2D array afterwards, but I'm failing on part one of that goal. Here's the problem:
Create a function that meets the following:
Input: an edit transcript, and 2 original strings (3 strings)
Output: a 2 d array containing the two alignments post edit
Example:
s1 = “vintner”
s2 = “writers”
trans = “RIMDMDMMI”
R stands for "replace"
I stands for "insert"
M stands for "match"
D stands for "delete"
Answer:
alignment={“v_intner_”,
“wri_t_ers”}; //return a 2d array
Function prototype:
char** getAlignment(char* s1, char* s2, char* s3);
Here's my code below:
char TestS1[] = "vintner";
char TestS2[] = "writers";
char TestS3[] = "RIMDMDMMI";
char twoDarray[2][10];
char** getAlignment(char* s1, char* s2, char* s3){
char transTemp[n];
char s1Temp[n];
char s2Temp[n];
char sOne[n];
char sTwo[n];
strcpy(sOne, s1);
strcpy(sTwo, s2);
int jj;
strcpy(transTemp, s3);
int kk;
for(jj=0, kk=0; jj<n, kk<n; jj++, kk++){
if(transTemp[jj]=='R')
{
s1Temp[kk] = sOne[jj];
s2Temp[kk] = sTwo[jj];
}
if(transTemp[jj]=='I'){
s1Temp[kk] = '_';
s1Temp[kk+1] = sOne[jj];
s2Temp[kk] = sTwo[jj];
kk++;
}
if(transTemp[jj] == 'M'){
s1Temp[kk] = sOne[jj];
s2Temp[kk] = sTwo[jj];
}
if(transTemp[jj] == 'D'){
s2Temp[kk] = '_';
s2Temp[kk+1] = sTwo[jj];
s1Temp[kk] = sOne[jj];
kk++;
}
}
printf("\ns1Temp = %s\n", s1Temp);
printf("\ns2Temp = %s\n", s2Temp);
return 0;
}
main()
{
printf("The new method returns: ", getAlignment(TestS1,TestS2,TestS3));
return 0;
}
Your question really has two parts: How can I return two strings? And why don't I get the desired output?
Strings in C are character arrays. You seldom return strings. It is more common to pass a character array to a function, together with its maximum length, and fill that array. The functions in <string.h> do that. A good design model is, in my opinion, snprintf: It fills the buffer, takes care not to overflow it, ensures that the result is properly null-terminated and returns the number of characters written had the buffer been big enough. That last property allows you to pass a length of null (and as a special case the NULL pointer) to find out how many chars you need and allocate memory as appropriate.
So the prototype for your function could look like this:
int getAlignment(char *res1, char *res2, size_t n,
const char* s1, const char* s2, const char* trans);
Except that the resulting strings could be of different length in your case.
You can also return strings, but you'll either have to return new memory allocated with malloc on the heap, which means the client code must explicitly free it, or pointers into already existing memory. You can, of course, only return one string.
You can return multiple values from a function as a struct. Structs do not decay into pointers when passing them to or returning them from functions. I'll use that approach in my example below.
As for the second question: Your main problem is that you have three strings - two source strings and one translation string - but keep only two indices. All strings are traversed independently; there is no synchronisation between the strings' indices.
You append to the result strings as you go. The "driving" string is the trenslation string, so you should traverse only that with the main loop.
Another thing to note is that you don't need to make copies of the source strings. This is not only inneccessary, it is also dangerous, because strcpy could overflow the buffers. Taking care of overflow with strncpy couldtruncate the input strings.
I've updated your implementation:
#include <stdio.h>
#include <string.h>
#define N 10
struct Result {
char res1[N];
char res2[N];
};
struct Result getAlignment(const char* s1, const char* s2, const char* trans)
{
struct Result res;
int j1 = 0; // index into s1
int j2 = 0; // index into s2
int n = N - 1; // leave 1 char for null terminator
while (*trans) {
if (*trans == 'R') {
if (j1 < n) res.res1[j1++] = *s1++;
if (j2 < n) res.res2[j2++] = *s2++;
}
if (*trans == 'I'){
if (j1 < n) res.res1[j1++] = '_';
if (j1 < n) res.res1[j1++] = *s1++;
if (j2 < n) res.res2[j2++] = *s2++;
}
if (*trans == 'M') {
if (j1 < n) res.res1[j1++] = *s1++;
if (j2 < n) res.res2[j2++] = *s2++;
}
if (*trans == 'D') {
if (j1 < n) res.res1[j1++] = *s1++;
if (j2 < n) res.res2[j2++] = '_';
if (j2 < n) res.res2[j2++] = *s2++;
}
trans++;
}
// null-terminate strings
res.res1[j1] = '\0';
res.res2[j2] = '\0';
return res;
}
int main()
{
char *str1 = "vintner";
char *str2 = "writers";
char *trans = "RIMDMDMMI";
struct Result res = getAlignment(str1, str2, trans);
printf("%s\n%s\n\n", res.res1, res.res2);
return 0;
}
Things to note:
The translation string is traversed via pointer, which saves an index.
The result strings are appended to only if there is enough space. You can change N to 5 and see how the result strings are truncated after 4 characters, thus losing information, but preventing buffer overflows.
Both result-string indices and source string pointers are incrementes as you go.
The source strings are only read from. (That's why copying doesn't make sense.) So they should be const char * in the function signature.

How to dynamically allocate a two dimensional array of pointers ? (C)

I have an assignment to make a dictionary.
It will contain an x amount of words and their definitions (input by user).
Instructions say that the dictionary should be of type char*** (2D array of pointers=arrays=strings), but I've got absolutely no idea of how to dynamically allocate the size of the array. it should have 2 lines, 1 for words and another 1 for their definitions, and the number of columns is decided by how many words are in the dictionary. While looking for help online i came up with this:
char** AllocateArray(int line, int column)
{
char** pArray=(char**)malloc(line*sizeof(char*));
int i;
for(i=0;i<2;i++)
pArray[i]=(char*)malloc(column*sizeof(char));
return pArray;
}
What changes should i make in the code for it to work with my char*** ?
Using Visual studio 2012
Edit:
I have a problem with this right now:
void inputString(char* p1)
{
char buffer[80];
printf("\nEnter a word:");
scanf("%s",buffer);
p1=(char*)malloc(strlen(buffer)+1);
if(p1!=NULL)
{
strcpy(p1,buffer);
free(buffer);
}
}
it crashes right after i input a word. the char* that the function receives is dictionary[i][j]. –
Don't free() anything allocated on the stack (i.e. buffer).
Also, your function inputString() will not tell its client what memory it had allocated, since p1 is local to it.
Here is an example.
char*** dictionary;
int i = 0;
int j = 0;
int lines = 10;
dictionary = (char***)malloc(sizeof(char**)*lines);
for(i=0;i<lines;i++)
{
dictionary[i] = (char**)malloc(sizeof(char*)*4);
for(j=0;j<4;j++)
dictionary[i][j] = (char*)malloc(sizeof(char)*25);
}
You have to modify the malloc's parameters in order to adapt to your problem/ or modify them when you need more memory for your strings.
Also it might be a good idea to try and free memory when you do not need it
Don't forget to malloc like this...
dictionary[i][j] = (char*)malloc(sizeof(char)*strlen(word_to_insert)+1);
...because each word end with a supplementary byte filled with 0 "null terminate string".
a sample
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char ***dictionary;
const char *words[] = { "ASEAN", "United Nations", "OPEC" };
size_t howManyWords = sizeof(words)/sizeof(*words);
int i;
dictionary = malloc(howManyWords*sizeof(char**));
printf("Please enter the definition of this word\n");
for(i = 0; i < howManyWords; ++i){
char buff[80];
char **keyValue;
printf("%s : ", words[i]);
fgets(buff, sizeof(buff), stdin);
keyValue = malloc(2*sizeof(char*));
keyValue[0] = (char*)words[i];
keyValue[1] = malloc(strlen(buff)+1);
strcpy(keyValue[1], buff);
dictionary[i] = keyValue;
}
//print
for(i=0;i<howManyWords;++i){
printf("%s : %s", dictionary[i][0], dictionary[i][1]);
}
//release
for(i=0;i<howManyWords;++i){
free(dictionary[i][1]);
free(dictionary[i]);
}
free(dictionary);
return 0;
}

String (array) capacity via pointer

I am tring to create a sub-routine that inserts a string into another string. I want to check that the host string is going to have enough capacity to hold all the characters and if not return an error integer. This requires using something like sizeof but that can be called using a pointer. My code is below and I would be very gateful for any help.
#include<stdio.h>
#include<conio.h>
//#include "string.h"
int string_into_string(char* host_string, char* guest_string, int insertion_point);
int main(void) {
char string_one[21] = "Hello mother"; //12 characters
char string_two[21] = "dearest "; //8 characters
int c;
c = string_into_string(string_one, string_two, 6);
printf("Sub-routine string_into_string returned %d and creates the string: %s\n", c, string_one);
getch();
return 0;
}
int string_into_string(char* host_string, char* guest_string, int insertion_point) {
int i, starting_length_of_host_string;
//check host_string is long enough
if(strlen(host_string) + strlen(guest_string) >= sizeof(host_string) + 1) {
//host_string is too short
sprintf(host_string, "String too short(%d)!", sizeof(host_string));
return -1;
}
starting_length_of_host_string = strlen(host_string);
for(i = starting_length_of_host_string; i >= insertion_point; i--) { //make room
host_string[i + strlen(guest_string)] = host_string[i];
}
//i++;
//host_string[i] = '\0';
for(i = 1; i <= strlen(guest_string); i++) { //insert
host_string[i + insertion_point - 1] = guest_string[i - 1];
}
i = strlen(guest_string) + starting_length_of_host_string;
host_string[i] = '\0';
return strlen(host_string);
}
C does not allow you to pass arrays as function arguments, so all arrays of type T[N] decay to pointers of type T*. You must pass the size information manually. However, you can use sizeof at the call site to determine the size of an array:
int string_into_string(char * dst, size_t dstlen, char const * src, size_t srclen, size_t offset, size_t len);
char string_one[21] = "Hello mother";
char string_two[21] = "dearest ";
string_into_string(string_one, sizeof string_one, // gives 21
string_two, strlen(string_two), // gives 8
6, strlen(string_two));
If you are creating dynamic arrays with malloc, you have to store the size information somewhere separately anyway, so this idiom will still fit.
(Beware that sizeof(T[N]) == N * sizeof(T), and I've used the fact that sizeof(char) == 1 to simplify the code.)
This code needs a whole lot more error handling but should do what you need without needing any obscure loops. To speed it up, you could also pass the size of the source string as parameter, so the function does not need to calculate it in runtime.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
signed int string_into_string (char* dest_buf,
int dest_size,
const char* source_str,
int insert_index)
{
int source_str_size;
char* dest_buf_backup;
if (insert_index >= dest_size) // sanity check of parameters
{
return -1;
}
// save data from the original buffer into temporary backup buffer
dest_buf_backup = malloc (dest_size - insert_index);
memcpy (dest_buf_backup,
&dest_buf[insert_index],
dest_size - insert_index);
source_str_size = strlen(source_str);
// copy new data into the destination buffer
strncpy (&dest_buf[insert_index],
source_str,
source_str_size);
// restore old data at the end
strcpy(&dest_buf[insert_index + source_str_size],
dest_buf_backup);
// delete temporary buffer
free(dest_buf_backup);
}
int main()
{
char string_one[21] = "Hello mother"; //12 characters
char string_two[21] = "dearest "; //8 characters
(void) string_into_string (string_one,
sizeof(string_one),
string_two,
6);
puts(string_one);
return 0;
}
I tried using a macro and changing string_into_string to include the requirement for a size argument, but I still strike out when I call the function from within another function. I tried using the following Macro:
#define STRING_INTO_STRING( a, b, c) (string_into_string2(a, sizeof(a), b, c))
The other function which causes failure is below. This fails because string has already become the pointer and therefore has size 4:
int string_replace(char* string, char* string_remove, char* string_add) {
int start_point;
int c;
start_point = string_find_and_remove(string, string_remove);
if(start_point < 0) {
printf("string not found: %s\n ABORTING!\n", string_remove);
while(1);
}
c = STRING_INTO_STRING(string, string_add, start_point);
return c;
}
Looks like this function will have to proceed at risk. looking at strcat it also proceeds at risk, in that it doesn't check that the string you are appending to is large enough to hold its intended contents (perhaps for the very same reason).
Thanks for everyone's help.

Copying a file line by line into a char array with strncpy

So i am trying to read a text file line by line and save each line into a char array.
From my printout in the loop I can tell it is counting the lines and the number of characters per line properly but I am having problems with strncpy. When I try to print the data array it only displays 2 strange characters. I have never worked with strncpy so I feel my issue may have something to do with null-termination.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
FILE *f = fopen("/home/tgarvin/yes", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);
char *bytes = malloc(pos); fread(bytes, pos, 1, f);
int i = 0;
int counter = 0;
char* data[counter];
int length;
int len=strlen(data);
int start = 0;
int end = 0;
for(; i<pos; i++)
{
if(*(bytes+i)=='\n'){
end = i;
length=end-start;
data[counter]=(char*)malloc(sizeof(char)*(length)+1);
strncpy(data[counter], bytes+start, length);
printf("%d\n", counter);
printf("%d\n", length);
start=end+1;
counter=counter+1;
}
}
printf("%s\n", data);
return 0;
}
Your "data[]" array is declared as an array of pointers to characters of size 0. When you assign pointers to it there is no space for them. This could cause no end of trouble.
The simplest fix would be to make a pass over the array to determine the number of lines and then do something like "char **data = malloc(number_of_lines * sizeof(char *))". Then doing assignments of "data[counter]" will work.
You're right that strncpy() is a problem -- it won't '\0' terminate the string if it copies the maximum number of bytes. After the strncpy() add "data[counter][length ] = '\0';"
The printf() at the end is wrong. To print all the lines use "for (i = 0; i < counter; i++) printf("%s\n", data[counter]);"
Several instances of bad juju, the most pertinent one being:
int counter = 0;
char* data[counter];
You've just declared data as a variable-length array with zero elements. Despite their name, VLAs are not truly variable; you cannot change the length of the array after allocating it. So when you execute the lines
data[counter]=(char*)malloc(sizeof(char)*(length)+1);
strncpy(data[counter], bytes+start, length);
data[counter] is referring to memory you don't own, so you're invoking undefined behavior.
Since you don't know how many lines you're reading from the file beforehand, you need to create a structure that can be extended dynamically. Here's an example:
/**
* Initial allocation of data array (array of pointer to char)
*/
char **dataAlloc(size_t initialSize)
{
char **data= malloc(sizeof *data * initialSize);
return data;
}
/**
* Extend data array; each extension doubles the length
* of the array. If the extension succeeds, the function
* will return 1; if not, the function returns 0, and the
* values of data and length are unchanged.
*/
int dataExtend(char ***data, size_t *length)
{
int r = 0;
char **tmp = realloc(*data, sizeof *tmp * 2 * *length);
if (tmp)
{
*length= 2 * *length;
*data = tmp;
r = 1;
}
return r;
}
Then in your main program, you would declare data as
char **data;
with a separate variable to track the size:
size_t dataLength = SOME_INITIAL_SIZE_GREATER_THAN_0;
You would allocate the array as
data = dataAlloc(dataLength);
initially. Then in your loop, you would compare your counter against the current array size and extend the array when they compare equal, like so:
if (counter == dataLength)
{
if (!dataExtend(&data, &dataLength))
{
/* Could not extend data array; treat as a fatal error */
fprintf(stderr, "Could not extend data array; exiting\n");
exit(EXIT_FAILURE);
}
}
data[counter] = malloc(sizeof *data[counter] * length + 1);
if (data[counter])
{
strncpy(data[counter], bytes+start, length);
data[counter][length] = 0; // add the 0 terminator
}
else
{
/* malloc failed; treat as a fatal error */
fprintf(stderr, "Could not allocate memory for string; exiting\n");
exit(EXIT_FAILURE);
}
counter++;
You are trying to print data with a format specifier %s, while your data is a array of pointer s to char.
Now talking about copying a string with giving size:
As far as I like it, I would suggest you to use
strlcpy() instead of strncpy()
size_t strlcpy( char *dst, const char *src, size_t siz);
as strncpy wont terminate the string with NULL,
strlcpy() solves this issue.
strings copied by strlcpy are always NULL terminated.
Allocate proper memory to the variable data[counter]. In your case counter is set to 0. Hence it will give segmentation fault if you try to access data[1] etc.
Declaring a variable like data[counter] is a bad practice. Even if counter changes in the subsequent flow of the program it wont be useful to allocate memory to the array data.
Hence use a double char pointer as stated above.
You can use your existing loop to find the number of lines first.
The last printf is wrong. You will be printing just the first line with it.
Iterate over the loop once you fix the above issue.
Change
int counter = 0;
char* data[counter];
...
int len=strlen(data);
...
for(; i<pos; i++)
...
strncpy(data[counter], bytes+start, length);
...
to
int counter = 0;
#define MAX_DATA_LINES 1024
char* data[MAX_DATA_LINES]; //1
...
for(; i<pos && counter < MAX_DATA_LINES ; i++) //2
...
strncpy(data[counter], bytes+start, length);
...
//1: to prepare valid memory storage for pointers to lines (e.g. data[0] to data[MAX_DATA_LINES]). Without doing this, you may hit into 'segmentation fault' error, if you do not, you are lucky.
//2: Just to ensure that if the total number of lines in the file are < MAX_DATA_LINES. You do not run into 'segmentation fault' error, because the memory storage for pointer to line data[>MAX_DATA_LINES] is no more valid.
I think that this might be a quicker implementation as you won't have to copy the contents of all the strings from the bytes array to a secondary array. You will of course lose your '\n' characters though.
It also takes into account files that don't end with a new line character and as pos is defined as long the array index used for bytes[] and also the length should be long.
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_LINE_ARRAY_DIM 100
int main(int argc, char* argv[])
{
FILE *f = fopen("test.c", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);
char *bytes = malloc(pos+1); /* include an extra byte incase file isn't '\n' terminated */
fread(bytes, pos, 1, f);
if (bytes[pos-1]!='\n')
{
bytes[pos++] = '\n';
}
long i;
long length = 0;
int counter = 0;
size_t size=DEFAULT_LINE_ARRAY_DIM;
char** data=malloc(size*sizeof(char*));
data[0]=bytes;
for(i=0; i<pos; i++)
{
if (bytes[i]=='\n') {
bytes[i]='\0';
counter++;
if (counter>=size) {
size+=DEFAULT_LINE_ARRAY_DIM;
data=realloc(data,size*sizeof(char*));
if (data==NULL) {
fprintf(stderr,"Couldn't allocate enough memory!\n");
exit(1);
}
}
data[counter]=&bytes[i+1];
length = data[counter] - data[counter - 1] - 1;
printf("%d\n", counter);
printf("%ld\n", length);
}
}
for (i=0;i<counter;i++)
printf("%s\n", data[i]);
return 0;
}

Resources