I am new to C and I was wondering how I can do so that when a word of X characters is entered through the console, an array of characters is created with the right memory allocation for it, for example I enter "hello" and it is saved in a string of 6-space characters.Thanks!
CodePudding user response:
There is nothing in the ISO C standard library specification or Microsoft C library that directly does what you seek.
In the C POSIX library, however (what's the difference?), the scanf
family of functions support an m
modifier for string s
inputs. When m
is used, scanf()
will allocate a buffer of an appropriate size, and assign it to the pointer that you provide:
From the Linux scanf()
man page:
An optional 'm' character. This is used with string conversions (
%s
,%c
,%[
), and relieves the caller of the need to allocate a corresponding buffer to hold the input: instead,scanf()
allocates a buffer of sufficient size, and assigns the address of this buffer to the corresponding pointer argument, which should be a pointer to achar *
variable (this variable does not need to be initialized before the call). The caller should subsequentlyfree(3)
this buffer when it is no longer required.
Here's an example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *input = NULL;
if (scanf("%ms", &input) != 1) {
fprintf(stderr, "scanf() failed\n");
return 1;
}
printf("scanf() allocated string: \"%s\"\n", input);
free(input);
return 0;
}
Supported C libraries:
- glibc -- since 2.7 (267c54dcef41)
- musl -- since 0.9.11 (16a1e036)
Unsupported C libraries:
- dietlibc -- as of at least 0.34
- Microsoft C runtime library (CRT)
CodePudding user response:
Looked interesting to try to directly meet OP's goal of <enter "hello" and it is saved in a string of 6-space character> using standard library functions, even if it took some code.
Sadly standard C does not offer the nice option as suggested with @Jonathon Reinhart good answer.
Instead, below is an approach not suited for learners, but does the job. It does not have a prior line length limit. It recursively forms a link list of characters entered (recursion not suitable for a long line), then allocates an array based on depth, and assigns the array.
#include <stdlib.h>
#include <stdio.h>
typedef struct link_s {
struct link_s *prev;
char ch;
} llink;
char* foo(llink *prior) {
int ch = fgetc(stdin);
if (ch == '\n' || ch == '\r' || ch == EOF) {
llink *ll = prior;
size_t len = 1;
while (ll) {
len ;
ll = ll->prev;
}
char *buf = malloc(len);
if (buf) {
buf[--len] = '\0';
llink *ll = prior;
while (ll) {
buf[--len] = ll->ch;
ll = ll->prev;
}
}
return buf;
}
llink node = {.prev = prior, .ch = (char) ch};
return foo(&node);
}
int main() {
char *s = foo(NULL);
printf("<%s>\n", s);
free(s);
return 0;
}
Input
Hello<enter>
Output
<Hello>
CodePudding user response:
If you only need to read until a newline, you can use getline defined in stdio.h
. It does automatic memory allocation. The function will allocate an extra character to store the newline, you can remove it using buf[strcspn(buf, '\n')] = '\0'
.
If you want it to read until a whitespace, sad to say there's no standard C library function to meet your needs for arbitrary string lengths (without writing a bunch of your own code). If you are a beginner learning C and need simple I/O, using scanf("%s", buf)
into a fixed sized buffer should be plenty.