5

I want to store lines of strings dynamically using C language.

for e.g

sadasdasda5245sdf

fadfa6456

fasdf90-70=790

the number of such lines and the length of each line can be anything.Is there any way to store the whole thing dynamically.

2
  • A classic question for tests. Commented Jul 25, 2009 at 20:15
  • Yes, it smells a bit like homework, too. If it was a question for a test, I would not hire someone who starts to reimplement from scratch a dynamic string library instead of using an already existing and debugged one. Commented Jul 25, 2009 at 20:41

6 Answers 6

7

There are several data structures that allow you to add items dynamically, without having to know in advance what the maximum number of elements required are. There are linked lists, binary search trees, balanced trees, tries, heaps and many more.

Similarly, there are lots of ways of dynamically allocating strings of different lengths.

The easiest way would probably be to use a simple linked list:

typedef struct _node {
    struct _node *next;
    char *value;
} node_t;

You keep track of the head, the first item in the list, and each next field points to the next node in the list. For example, to traverse the list, you would write something like this:

currentNode = head;
while(currentNode != NULL) {
    /* do something with currentNode->value */
    currentNode = currentNode->next;
}

Without knowing what you want to do, specifically, I can't really offer any better suggestions.

What operations do you want to carry out on your data structure often? Are you going to simply be iterating through the strings, searching for strings, adding and removing strings?

Sign up to request clarification or add additional context in comments.

4 Comments

What's wrong with an array of character pointers? Your answer doesn't really address the string storage, and the trivial way of adding nodes to a list means that the list stores the values in reverse order (which might be helpful, but probably isn't). If the string pointers are separately allocated from the array of pointers, then you can realloc() the array when necessary to grow it.
There's absolutely nothing wrong with a dynamically growing array of character pointers if that suits your needs. You must, however, recognise the advantages and disadvantages it has and what those give you over other data structures. Furthermore, there's no reason a linked list has to give you values in reverse order. If you keep a note of the tail in your linked list data structure, it's trivial to add nodes on to the end rather than the beginning, or use a doubly linked list to traverse in either direction.
The reason I didn't address the string storage is because I don't believe there is enough information in the question to really do so.
I think the OP is looking for the C equivalent of std::vector<std::string>. See my answer: stackoverflow.com/questions/1182534/…
3

There are several data structures that allow you to grow dynamically. As the 2 previous replies suggest, you can use an array of pointers, a linked-list etc.

It all depends on the requirements of your implementation:

  1. Will you be accessing those strings more than once?
  2. Once you obtain them, do you intend to access them all (for some calculation) or one at a time (i.e. a dictionary)?
  3. What are your space/memory consideration?
  4. Is there any importance to the order in which you get them (suggesting a queue or a stack implementation)?
  5. Is there an inherent connection between the strings (suggesting a tree or tree-like structure)?

etc. I suggest reading a bit about data structures and deciding what suits you best. They can all be implemented in C.
Look at this Wikipedia article (go to the 'Examples' section for a list of options, if you want to skip the theory)

Comments

3

If you know at some initialization time the number of strings and will not need to allocate for more, you could just use a:

char **myStrings = (char **)malloc(numStrings*sizeof(*myStrings);

and then allocation for each string:

for(int i=0; i<numStrings; i++)
    myStrings[i] = (char *)malloc(stringLength[i] + 1);

You could still allocate more dynamically if needed, though.

If you need to dynamically reallocate the array of strings:

myStrings = (char **)realloc(myStrings, numStringsNew*sizeof(myStrings));

or if a particular string needs to change its length, just realloc that particular string:

myStrings[the_one_to_realloc] = (char *)realloc(myStrings[the_one_to_realloc], stringLengthNew + 1);

3 Comments

O(1) to fetch a specific line, better than linked list.
Yeah, this is essentially the manual equivalent to std::vector<std::string> in C++ using the STL.
x = realloc(x, ...); may leak memory. Better use a temporary variable.
2

Run, don't walk, to the Princeton web site and get Dave Hanson's C Interfaces and Implementations. The data structure called Seq_T is perfect for building up a list of lines dynamically. Dave doesn't provide a buffering reader, but you can read lines into a finite buffer, convert the result using Text_put, and if a line is too big for one buffer, join the results using Text_cat. The CII code manages all the dynamic growth for you.

4 Comments

Ouch. Your recommendation uses arrays that get realloc'ed with growth and whatnot. Not to mention that the code is not that commented (maybe because they want to sell the book) ? That data structure would be ok for a small number of strings, but it has poor performance characteristics.
@njsf: As long as the dynamic array is doubled in size at each reallocation the mean insertion time remains O(1) for each item. The cost of this approach is, of course, indeterminate latency on any given insert. This is a popular approach which compares well with lists or trees for some applications because is has O(1) access time for reads and changes.
@njsf: the comments are indeed in the book. But there's no performance problem; I've used this library for many applications and have always had excellent results. If you find a performance problem, I want to know about details, with measurements.
All arrays get realloc'ed with growth. Even the C++ std library for vector does the same thing internally. Without knowing ahead of time how many items in an array you will have, there is no CPU magic other than to realloc with growth or initially allocate an array so huge, there is no way you will need more entries (I mean, who needs more than 640k anyway? :) ).
2

There is little reason to reinvent the wheel, unlike what some answers suggest.

Do not develop your own library, while there are several free software libraries which implement such abstractions. One example, among others, is glib which has many types such as dynamically growing strings and dynamically growing lists.

1 Comment

Yes, it's a good idea to use an existing implementation, but it never hurts to understand the underlying algorithms that can be used to solve this kind of problem. For example, if you're going to want to process the strings in a sorted order, an underlying hash table implementation probably isn't a good idea.
0

To store dynamically, use can use the 'm' flag of %s as shown below:

char *variable;
scanf ("%ms", &variable);
/* use variable */
free(variable);

The string pointed by variable will be sufficient to hold the data.

Do note, that it is your responsibility to free the variable after its use.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.