9

I need to do some manipulation on a string (like adding letters at certain places). I don’t know what its size will be, it depends on the input.

How can I define a string without specifying its size? I want it to adapt to any contents I put inside.

And why can’t I just pass an empty char * to a method? The compiler doesn’t allow that.

According to the answers, I understand that I can’t create an unlimited size string. But e.g. when I tried to create char arr[100] and my string’s length was only 8 characters, when I printed arr I got more letters then I wanted. Some of them weren’t even part of the string. How is that possible?

Palec
  • 12,743
  • 8
  • 69
  • 138
Michael
  • 427
  • 1
  • 3
  • 13
  • Can you be more specific? You can increment a `char *` until it `== '\0'` – Elliott Frisch Jan 04 '14 at 07:40
  • What do you mean by an "empty" `char*`? – merlin2011 Jan 04 '14 at 07:41
  • Easiest way would be to pass a pointer to that string. It can then be reallocated if the string needs to grow. As for the input, you could probably set a maximum size an use something like fgets. If you memset to 0 before fgets and the string is too long, the last character after fgets won't be null. – cup Jan 04 '14 at 07:43
  • 1
    @sefi - But where is the code? – Ed Heal Jan 04 '14 at 08:23
  • @EdHeal sorry that I didn't post it earlier:void convertWord(char* word,char tav,char* newword,int wordlength) , and by some manipulation I build the newword character by character like this: newword[i]. I created the array like this: newword[100] – Michael Jan 04 '14 at 08:54
  • I provided additional details in my answer to make it absolutely clear and to address all your issues. Did I guess right that by empty `char *` you mean uninitialized `char *`? You need to allocate storage for your `char *` before passing it to a function like `fgets`. As far as short string printed as long, I noticed you already discovered the missing `\0`. However, I wrote a more detailed explanation on that. – Palec Jan 05 '14 at 21:27

4 Answers4

23

Short answer

You cannot define a string with unknown size. But you may make the string larger and larger when needed. All string and I/O functions need to get an already allocated string to work with, so you have to play with allocation a little bit and be careful not to exceed the allocated capacity.

However, when you have a constant upper bound on string length, just allocate string of that length and you’ll be safe. Resizing is more complex so avoid it if you don’t need it.

What is a string in C

String is a part of char array, terminated by \0. String functions stop reading the array when they encounter the first \0 character. Remember that strlen returns the number of characters before the first \0, so even if the array ends immediately after the first \0, string length is strictly less than the underlying array length. Specifically in that case array length is strlen + 1. This is important when allocating a string; always allocate space for the terminating \0!

E.g.

char w[7] = "Hello";

is the same as

char w[7] = {'H', 'e', 'l', 'l', 'o', '\0', '\0'};

When used as a string, the first \0 is end of string and anything after it is ignored (not read by string functions). Even if you rewrite the last element of the example char array by a printable character (e.g. w[6] = '!'; resulting in having {'H', 'e', 'l', 'l', 'o', '\0', '!'}), puts(w); will print Hello (not Hello! or anything alike).

When playing with strings as with char arrays, be sure to always include \0 at its end as otherwise potentially unallocated memory after the array is read by string functions which results in segfault.

Why string with unknown size cannot be defined

As I already wrote, string is part of array of char. Each array must have a fixed size. You can use just a part of it (effectively making it smaller), but it has to be allocated and allocator (malloc, calloc) needs to know how much memory is wanted.

If you use an array as bigger than allocated, you program is likely to crash with segfault in the better case. If you are extremely unlucky, you program will not crash and will just use the part of memory right after the array, producing weird results.

Since C99, you can omit array length specification if it can be inferred from initializer: char w[] = "Hello"; is the same result as char w[6] = "Hello";. However this will not help you because you specify initializer at compile time and you need to dynamically change the string length at run time.

How to simulate arbitrary length string

To handle strings of unlimited length, you can create array of a fixed length and every time its length is too low, allocate a new array twice as long and copy the original contents to the new one. (And free the old one.) You can use realloc to do this work for you, with additional benefit of higher speed when the array does not need to be moved and can just be made longer in-place.

Community
  • 1
  • 1
Palec
  • 12,743
  • 8
  • 69
  • 138
  • 1
    well, there's also `realloc` that will do it for you, more efficiently, avoiding copying when possible. – user4815162342 Jan 04 '14 at 07:56
  • I can find out what is the maximum length of that string, but when I created for example arr[100] and used it, when i printed it, I got more letters then i wanted. – Michael Jan 04 '14 at 07:58
  • @Sefi: That's because you forgot to add the '\0' to mark the end of the string. – Thomas Padron-McCarthy Jan 04 '14 at 08:15
  • In programming languages like Ruby, Python you can create a string, and increase the length to whatever you want. In Ruby for example `a = '' ; a.concat(?. * 100_000_000)` will create a 100 MB string. You can use `a.chop!` to just chop off the last character. The question is why isn't it possible in C when Ruby is written in C? – 15 Volts Sep 25 '19 at 22:43
  • 1
    Anything can be written in C. It does not mean that C itself has to have all features of all applications possible. @S.Goswami No idea how strings are actually implemented in Ruby, but my answer could serve as a very simplistic implementation of Ruby strings. All the allocation logic is just hidden inside the implementation of Ruby and does not leak to the language itself. – Palec Sep 27 '19 at 06:49
3

A string in C is nothing more than a character array with the character \0 to define the end of it.

Since it is an array, it requires storage and therefore you cannot "define" it without storage.

merlin2011
  • 71,677
  • 44
  • 195
  • 329
0

You can allocate memory for your string using malloc():

int n = 100;
char * str = malloc(n);
// assign characters to your string, finish last one with 0.
// ...

However, do not forget to free allocated memory using free():

free(str);
mvp
  • 111,019
  • 13
  • 122
  • 148
-6

Try a char string as a pointer.

char *strng ;

I think this will solve the problem

Ime94
  • 9
  • 4