I am trying to find a way to manipulate strings in C in a more efficient way (maybe like how java does it).
One way I thought of it is to count the size of the string till the end of the line (maybe including spaces), allocate memory of this size using malloc()
and then go back to the beginning of the line and scan the string.
Is there a way to do this? I don't know if there is a way to return the "cursor" to the beginning of the line to 're'scan something.
And if you know another/better way to deal with strings in C please tell me.
Thanks
Asked
Active
Viewed 1,057 times
-2

NerdyKoala
- 25
- 6
-
You can't "go back" in a non-seekable stream (like terminal or socket). – Eugene Sh. Feb 12 '15 at 21:22
-
possible duplicate of [How can I read a an input string of unknown length?](http://stackoverflow.com/questions/16870485/how-can-i-read-a-an-input-string-of-unknown-length) – QuestionC Feb 12 '15 at 21:26
-
You could mark the current file pointer with `ftell()` and then rewind with `fseek()` to re-process, having established the string length-to-be+2, and then use `fgets()`. Although it is probably more efficient to allocate a generous buffer in the first place, and reallocate it if the input text line was truncated, and then concatenate. – Weather Vane Feb 12 '15 at 21:33
-
As was pointed out, fseek() does not work on character devices like your typical console terminal. – Lee Daniel Crocker Feb 12 '15 at 22:16
2 Answers
0
There is no way to do what you're asking directly, but there is a (in my opinion far better) alternative: fgets()
.
What it does is read the text until the end of the line, including the final line-feed. If the line is longer than the buffer, then it omits that line feed --- you can use that fact to check if the line was completed.
Something like this (UNTESTED CODE):
// WARNING: Example does not include error checking
// (check the return value of `fgets()`, `malloc()` and `realloc()`!)
size_t buflen = 64;
size_t pos = 0;
char* buf = malloc(buflen);
// `for(;;)` is an infinite loop
for(;;)
{
// read data into buf[pos..buflen] (total of `buflen-pos` bytes)
fgets(buf + pos, buflen - pos, file);
pos = pos + strcspn(buf + pos, "\r\n");
if(buf[pos]) // reached end of line; end the loop
break;
buflen += 64;
// alternative (double the size):
// buflen <<= 1;
buf = realloc(buf, buflen); // resize the buffer
}
// `buf` contains our line; `pos` contains the end of it
// optional: remove the trailing newline
// buf[pos] = 0;
Relevant documentation:

Tim Čas
- 10,501
- 3
- 26
- 32
0
You could use scanf
to read every character and then add that character into your buffer.
Your buffer initial size could be 16. And after you read every character you check if you have space for that new character. If you do not have space for your new character you double buffer size and realloc
it.
Check out the code example:
#include <stdio.h>
#include <stdlib.h>
char *str;
int main(void) {
char c = '\0';
int size = 0;
int buffer_size = 16;
str = (char *) calloc(buffer_size, sizeof(char));
while (c != '\n') {
scanf("%c", &c);
if (size + 1 == buffer_size) {
buffer_size *= 2;
str = (char *) realloc(str, buffer_size);
if (str == NULL) {
fprintf(stderr, "insufficient memory\n");
return EXIT_FAILURE;
}
}
str[size] = c;
size++;
}
printf("%s\n", str);
return EXIT_SUCCESS;
}