Link to home
Start Free TrialLog in
Avatar of bsarvanikumar
bsarvanikumar

asked on

use C to create a runtime array of strings

hi
I want to create an array of strings in C. I want to use a pointer to char pointer (char **).
The no. of strings will known at runtime only. The length of each strings is also known at runtime only. How can i go about it?

I tried the following


//Create a zagged array of strings based on user input
//USE C ONLY

#include<stdio.h>
#include<string.h>
int main()
{
int i=0,n,m;
char **str_array;
char *temp;
printf("\n Enter the number of strings : ");
scanf("%d",&n);

if(!(str_array =  (char**)malloc(n*sizeof(char*))))
        {
        printf("incorrect memory allocation");
        return;
        }

while(i<n)
        {
        temp="\0";
        scanf("%s",&temp);
        str_array[i]=(char*)malloc((strlen(temp))*sizeof(char));  //str_array[i] = "string i" works
        strcpy(str_array[i++],temp);
        str_array[i++]="hello";
        printf("\t%d\n",scanf("%s",&str_array[i++]));i
        }

for(i=0;i<n;i++)
        printf("%s\n",str_array[i]);
for(i=0;i<n;i++)
      free(str_array[i]);
free(str_array);


but somewhere segmentation fault occurs.

Within the while loop if i use
str_array[i] = "some stirng"

i.e., hard coding the strings, it works. But it doesn;t work for user input. I think i am not able to pass the addresses correctly. Can some one help me do it. A little explanaation will be greatly appreciated.


please do not give me examples with integer pointers. I know the solution for them. I am having trouble in understanding how the char* pointer to array works.
Thanks
K
Avatar of Dexstar
Dexstar

bsarvanikumar:

> How can i go about it?

You're doing a couple of things wrong, but they are all minor.

Change this:
> char *temp;

To this:

     char temp[1024];

Otherwise you won't allocate enough memory to hold the user's input.

>         strcpy(str_array[i++],temp);

For this part, do not use i++ ... Just use i, and then put one i++ at the end.  You need to only work with one string at a time.

>         str_array[i++]="hello";
>         printf("\t%d\n",scanf("%s",&str_array[i++]));i

Do you even need this part?  I don't think you do.

> Within the while loop if i use
> str_array[i] = "some stirng"

> i.e., hard coding the strings, it works. But it doesn;t work for user input.
> I think i am not able to pass the addresses correctly. Can some one help me
> do it. A little explanaation will be greatly appreciated.

I think it is mostly the i++ issues.  If you use i++, it increments the value of i, so now you're dealing with the next item in the array, and you haven't allocated any memory for it yet.

Hope that helps,
Dex*
bsarvanikumar:

> A little explanaation will be greatly appreciated.

This site offers a very good explanation that will help you:
http://www-ee.eng.hawaii.edu/Courses/EE150/Book/chap7/subsection2.1.1.2.html

Dex*
Avatar of bsarvanikumar

ASKER

hi

I made a couple of mistakes in my question. Here is an updated one. Thanks to Dex* for pointed them out. Guess i was trying out different option and forgot to remove the debugging stuff.


I want to create an array of strings in C. I want to use a pointer to char pointer (char **).
The no. of strings will known at runtime only. The length of each strings is also known at runtime only. How can i go about it?

I tried the following


//Create a zagged array of strings based on user input
//USE C ONLY

#include<stdio.h>
#include<string.h>
int main()
{
int i=0,n,m;
char **str_array;
char *temp;
printf("\n Enter the number of strings : ");
scanf("%d",&n);

if(!(str_array =  (char**)malloc(n*sizeof(char*))))
        {
        printf("incorrect memory allocation");
        return;
        }

while(i<n)
        {
        temp="\0";
        scanf("%s",temp);
        str_array[i]=(char*)malloc((strlen(temp))*sizeof(char));  //str_array[i] = "string i" works
        strcpy(str_array[i++],temp);
        printf("\t%d\n",scanf("%s",str_array[i]));i
        }

for(i=0;i<n;i++)
        printf("%s\n",str_array[i]);
for(i=0;i<n;i++)
      free(str_array[i]);
free(str_array);


but somewhere segmentation fault occurs.

Within the while loop if i use
str_array[i] = "some stirng"

i.e., hard coding the strings, it works. But it doesn;t work for user input. I think i am not able to pass the addresses correctly. Can some one help me do it. A little explanaation will be greatly appreciated.


please do not give me examples with integer pointers. I know the solution for them. I am having trouble in understanding how the char* pointer to array works.
Thanks
K
Hi,

i think you should use a linked list for it.

#include <stdio.h>
#include <string.h>

typedef struct _ll_ {
      char *text;
      struct _ll_ *next;
    } *stringList, sL;

stringList addString(char *str, stringList sl)
{
    stringList temp, i = sl;
    temp = (stringList) malloc(sizeof(sL));
    temp->text = strdup(str);
    temp->next = NULL;
    if (sl) {
          while (i->next)
              i = i->next;
          i->next = temp;
      return (sl);
    } else
      return (temp);
}

char *elementAt(int pos, stringList sl)
{
    int i = 0;
    stringList temp = sl;
    while (temp && i < pos) {
          temp = temp->next;
        i++;
    }
    if (temp)
      return (temp->text);
    else
      return (NULL);
}

// Example

int main()
{
    stringList l = NULL;

    l = addString("s0", l);
    l = addString("s1", l);
    printf("%s", elementAt(0, l));      // this should print s0
    printf("%s", elementAt(1, l));      // this should print s1
}

i think this will suit your needs.

Cheers,
  Bruno
bsarvanikumar:

> Thanks to Dex* for pointed them out.
First of all, you didn't make the change for "char *temp;".  So start with that.

Secondly, change this:
        strcpy(str_array[i++],temp);
        printf("\t%d\n",scanf("%s",str_array[i]));i

To this:
        strcpy(str_array[i],temp);
        printf("\t%d\n",scanf("%s",str_array[i]));
        i++;

Also, I don't know why you need that 2nd scanf.  If you scanf into temp, and then copy temp into your string, what do you need the 2nd scanf for?

Also, change this:
        str_array[i]=(char*)malloc((strlen(temp))*sizeof(char));

To this:
        str_array[i]=(char*)malloc((strlen(temp)+1)*sizeof(char));

You need to +1 to allocate space for the NULL at the end.


Dex*
     int i=0,n,m;
      char **str_array;
      char temp[MAX_LEN]; //define max_len to something big
      printf("\n Enter the number of strings : ");
      scanf("%d",&n);
      
      if(!(str_array =  (char**)malloc(n*sizeof(char*))))
      {
            printf("incorrect memory allocation");
            return;
      }

      fflush(stdin);
               //this will make the first gets in the next loop work, otherwise the first
              //gets will get the newline of the first input. I use gets because if you use
              //scanf, whitespace will also be considered as an input separator so putting "hello there" will be taken into two strings instead of one

      while(i<n)
      {
            gets(temp);
            str_array[i]=(char*)malloc((strlen(temp))*sizeof(char));  
            strcpy(str_array[i++],temp);
      }
changes I made

in the declaration part

char *temp;
to
char temp1[1024];
char *temp=temp1;

in the while loop

while(i<n)
        {
        temp="\0";
        scanf("%s",temp);
        str_array[i]=(char*)malloc((strlen(temp))*sizeof(char));  //str_array[i] = "string i" works
        strcpy(str_array[i++],temp);
        printf("\t%d\n",scanf("%s",str_array[i]));i
        }

to

while(i<n)
        {
        temp="\0";
       
        printf("\n %d",scanf("%s",temp)); //this doesn;t get printed
        printf("\n %d\t", strlen(temp));  //this doesn't get printerd
        str_array[i]=(char*)malloc((strlen(temp)+1)*sizeof(char));
        strcpy(str_array[i++],temp);
        }


it still gives a seg fault at  
printf("\n %d",scanf("%s",temp));


Please bear with me while I used temp pointer to temp1. I want to understand pointers and hence am tryint to use them a lot.

Thanks
K
>>> str_array[i] = "some stirng"

When you assign a string you are doing two things:
- allocating a block of memory (11 bytes in this case)
- setting str_array[i] to point to that block.

scanf() (or gets()) does not allocate memory...it must be given a place to put the input.  hence:
char temp[1024]

The following code fragment is probably what you are looking for

char linebuf[1024];
:
gets(linebuf);
str_arry[i] = strdup(linebuf);
:

first allocate a buffer.  We only need to do this once because we will reuse it forever.
Load a line of input into the buffer.
Allocate a memory block exactly the right size for the line we just read and copy the string into it.

E.
Finally my own solution

#include<stdio.h>
#include<string.h>
int main()
{
int i=0,n,m;
char **str_array;
char temp1[1024];
char *temp=temp1;

printf("\n Enter the number of strings : ");
scanf("%d",&n);

//alloc memory for no of strings / char pointers
if(!(str_array =  (char**)malloc(n*sizeof(char*))))
        {
        printf("incorrect memory allocation");
        return;
        }

//read the strings
while(i<n)
        {
        scanf("%s",temp);
        //allocate memory for each string
        str_array[i]=(char*)malloc((strlen(temp)+1)*sizeof(char));
        strcpy(str_array[i++],temp);
        }

//print array
for(i=0;i<n;i++)
        printf("string %d = %s\n",i+1,str_array[i]);

//free memory
//for each string
for(i=0;i<n;i++)
        free(str_array[i]);
//for string array
free(str_array);
return;
}
ASKER CERTIFIED SOLUTION
Avatar of ee_ai_construct
ee_ai_construct
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial