Reputation: 11
So I'm trying to program a function which allows the user to enter an unlimited amount of chars. For example this:
char string[100]
limits the input to 100 characters.
The code i have so far is:
#include<stdio.h>
char* uinput(){
char *string, *current;
int counter = 0;
string = (char *) malloc(10 * sizeof(char));
do{
realloc(string, counter * sizeof(char));
current = string + counter;
*current = getchar();
counter++;
}while(*current != '\n');
return string;
}
int main(){
char *s;
s = uinput();
printf("\nYou entered: %s", *s);
return 0;
}
I'm new to pointers, so I'm not sure why this doesn't work(Program crashes). What I'm trying to do is keep reading a character and keep relocating the string pointer so the amount of bytes keeps increasing until the user presses enter ('\n').
Thanks ~Raf
Upvotes: 0
Views: 3882
Reputation: 133988
The approach is sane, but there are minor details that are wrong. If you compile with warnings enabled, you'd notice that you're missing <stdlib.h>
; also you're giving the first character to printf
instead of the pointer to the buffer.
Then there is the obvious bug that your size is reset to 0, and you're casting the return value of malloc, using char
to store the result of getchar()
which is also wrong because you cannot check against EOF
. You're not saving the realloc
ed pointer; and you're not terminating the string properly. On minor detail, you'd want to double the size of buffer in each realloc
, because realloc
needs to potentially copy the whole line, so it becomes slower and slower over time as the line grows in length.
Thus we get:
#include <stdio.h>
#include <stdlib.h>
char* uinput() {
char *string;
// number of characters in the buffer
size_t counter = 0;
// size of allocated buffer
size_t allocated = 16;
int c;
string = malloc(allocated); // sizeof(char) is 1
do {
c = getchar();
if (c == EOF) {
break;
}
// if our buffer is too small, double the allocation
if (counter + 2 <= allocated) {
size_t new_size = allocated * 2;
char *new_buffer = realloc(string, new_size);
if (! new_buffer) {
// out of memory? try smaller increment
new_size = allocated + 16;
new_buffer = realloc(string, new_size);
if (! new_buffer) {
// really out of memory: free old block
free(string);
return NULL;
}
}
allocated = new_size;
string = new_buffer;
}
// store the character
string[counter++] = c;
} while (c != '\n');
// terminate the buffer properly
string[counter - 1] = '\0';
return string;
}
int main() {
char *s = uinput();
if (!s) {
// possibly out of memory in uinput
perror("Error reading input");
exit(EXIT_FAILURE);
}
printf("\nYou entered: %s", s);
free(s);
return EXIT_SUCCESS;
}
Upvotes: 1
Reputation: 19
use getchar
, malloc
and realloc
for reading the unlimited input string
Declare String type, you can also use char *
// String type
typedef char *String;
I write this function for joining the char in the end of string
/**
* Join the Char into end of String
*
* @param string - String
* @param c - joined char
*/
void String_joinChar(String *string, const char c)
{
const size_t length = strlen(*string);
(*string) = (String)realloc((*string), sizeof(char) * (length + 2));
(*string)[length] = c;
(*string)[length + 1] = '\0';
}
This function for inputting string, which read the char from keyboard by using getchar
and join it in the end of current string.
/**
* Input String
*
* @return Inputed String
*/
String String_input()
{
String string = (String)malloc(sizeof(char));
strcpy(string, "");
char cursor;
fflush(stdin);
while ((cursor = getchar()) != '\n' && cursor != EOF)
{
String_joinChar(&string, cursor);
}
return string;
}
Cause of using char *
, malloc
and realloc
, we must free it
/**
* Destroy String
*
* @param string - Destroyed String
*/
void String_destroy(String string)
{
free(string);
}
And now we just use it !!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
String string = String_input();
printf("\n%s\n", string);
String_destroy(string);
return 0;
}
Hope useful to you!
Upvotes: 0
Reputation: 328
Another approach is to use fgets()
, which gets a string into a sized buffer from the input stream; if it has the complete input then the string ends with \n
; if it doesn't then it doesn't. So you can loop calling fgets until there is an EOL character at the end, then depending on what your program does with the input you can decide whether to keep realloc-ing or to process the input a bit at a time.
Upvotes: 0
Reputation: 5307
You could try something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person{
char *name;
}pers;
void addMem(void);
int main(void){
addMem();
printf("\nYour name is:> %s\n",pers.name);
free(pers.name);
pers.name = NULL;
return 0;
}
void addMem(void){
unsigned int length = 6;
size_t newLength = 0;
unsigned int newSize = 0;
unsigned int i =0;
char *name;
int c;
name = malloc(length);
if(name == NULL){
exit(1);
}
newSize = length;
printf("Enter your name:> ");
while ((c = getchar()) != '\n' && c!=EOF){
name[i++]=(char)c;
if(i == newSize){
newSize = i+length;
name = realloc(name, newSize);
}
}
name[i] = '\0';
newLength = strlen(name)+1;
pers.name = malloc(newLength);
memcpy(pers.name, name, newLength);
free(name);
name = NULL;
}
Upvotes: 0
Reputation: 2153
Ok I think this is the problem
you are re-allocing
realloc(string, counter * sizeof(char));
The what will be the size of string in first iteration? It will be 0
.
Now you are writing to a pointer which has 0 bytes allocated and hence segfault.
Changing it to a while loop
can help to fix it. You can also change the initial value of counter to fix it
Upvotes: 2