Taking arbitrary length input from stdin using scanf - c

So one of the ways to take user-keyboard input in C I know is as follows:
char buffer[LENGTH_KNOWN] = "";
scanf("%s",buffer);
I was wondering if there is any way to take arbitrary length user input. I tried something as follows but I ended up getting a segfault.
char* buffer = "";
scanf("%s",buffer);
printf("%s",buffer);
However this seems to work:
char* buffer = "TEST........keeps going....................."
scanf("%s",buffer);
printf("%s",buffer);
Can anybody explain why I am getting this error and is there any easy way out to scanf arbitrary user input without using malloc and checking buffer overflow?
Thanks in advance!

Actually both are wrong since you can't write to a string literal (in both your examples buffer points to a string literal).
It's impossible to get arbitrarily-long input via a single scanf. You need to get input in a loop and keep adding to a real buffer.
is there any easy way out to scanf arbitrary user input without using
malloc and checking buffer overflow
Use a ready-made function that does it for you. Something like getline(3) (non-standard unfortunately).
ssize_t getline (char **lineptr, size_t *n, FILE *stream)
This function reads an entire line from stream, storing the text
(including the newline and a terminating null character) in a buffer
and storing the buffer address in *lineptr.

char* buffer = "";
scanf("%s",buffer);
printf("%s",buffer);
In the above your code you are not allocating memory for the buffer, so allocate memory for the buffer and read the values into buffer.

char *buffer = "..."; is totally wrong. It is not how you allocate memory because the thing in double quotes is a string literal and it is read-only. You can allocate memory like this:
char buffer[1024];
or dynamically using malloc:
char *buffer = malloc(1024);
/* .... */
free(buffer);

You Never know how much bytes you might read and hence allocate the memory accordingly. So I guess you need to get input in a loop and add in into buffer.

char* buffer;
buffer = malloc(sizeof(char) * 1024); // 1024 is max user input length, or use whatever you want..
scanf("%s", buffer);
buffer = realloc (buffer, strlen(buffer) + 1); // re-allocating the buffer according to user input..( + 1 for counting NULL character)
printf("%s",buffer);

Related

C redirect fprintf into a buffer or char array

I have the following function and I am wondering if there is a way to pass string or char array instead of stdout into it so I can get the printed representation as a string.
void print_Type(Type t, FILE *f)
{
fprintf(f,"stuff ...");
}
print_Type(t, stdout);
I have already tried this:
int SIZE = 100;
char buffer[SIZE];
print_Type(t, buffer);
But this is what I am seeing:
�����
Something like this
FILE* f = fmemopen(buffer, sizeof(buffer), "w");
print_Type(t, f);
fclose(f);
The fmemopen(void *buf, size_t size, const char *mode) function opens a stream. The stream allows I/O to be performed on the string or memory buffer pointed to by buf.
Yes there is sprintf() notice the leading s rather than f.
int SIZE = 100;
char buffer[SIZE];
sprintf(buffer, "stuff %d", 10);
This function prints to a string s rather than a file f. It has exactly the same properties and parameters to fprintf() the only difference is the destination, which must be a char array (either statically allocated as an array or dynamical allocated (usually via malloc)).
Note: This function is dangerous as it does not check the length and can easily overrun the end of the buffer if you are not careful.
If you are using a later version of C (c99). A better function is snprintf this adds the extra buffer length checking.
The problem with fmemopen is that it cannot resize the buffer. fmemopen did exist in Glibc for quite some time, but it was standardized only in POSIX.1-2008. But that revision included another function that handles dynamic memory allocation: open_memstream(3):
char *buffer = NULL;
size_t size = 0;
FILE* f = open_memstream(&buffer, &size);
print_Type(t, f);
fclose(f);
buffer will now point to a null-terminated buffer, with size bytes before the extra null terminator! I.e. you didn't write null bytes, then strlen(buffer) == size.
Thus the only merit of fmemopen is that it can be used to write to a fixed location memory buffer or fixed length, whereas open_memstream should be used everywhere else where the location of the buffer does not matter.
For fmemopen there is yet another undesired feature - the writes may fail when the buffer is being flushed and not before. Since the target is in memory, there is no point in buffering the writes, so it is suggested that if you choose to use fmemopen, Linux manual page fmemopen(3) recommends disabling buffering with setbuf(f, NULL);

Issue in filling up dynamic array from keyboard input[C]

I've implemented my own dynamic array data structure in c and now i am looking for a way to fill them up without losing their dynamicity.
If i write something like
char str[ANY_CONSTANT];
fgets(str, ANY_CONSTANT, stdin);
The number of elements i can pass to my program is defined at compilation time, which is exactly what i do not want to happen.
If i write something like
char str[ANY_CONSTANT];
scanf("%s", &str)
I have the same situation. Is there any function that i can use to input data from the keyboard without any fixed dimension? Thanks in advance!
You can try the POSIX getline function:
char *buf = NULL;
size_t buflen = 0;
ssize_t readlen = getline(&buf, &buflen, stdin);
/* buf points to the allocated buffer containing the input
buflen specifies the allocated size of the buffer
readlen specifies the number of bytes actually read */
getline reads an entire line from the console, reallocating the buffer as necessary to store the whole line.

read function: copying buffer, reallocating memory

I'm trying to read from a text file using the read function and store to a buffer. I then have to check the file again to see if any changes were made, and if there are, to reallocate memory and store contents to the same buffer (appending), character by character until EOF is reached. My code looks like this so far:
int fileSize=0;
fileSize=fileStat.st_size; /*fileSize is how many bytes the file is, when read initially*/
char buf[fileSize];
read(0, buf, fileSize);
/*now, I have to check if the file changed*/
int reader;
void *tempChar;
int reader=read(0, tempChar, 1);
while(reader!=0){
/*this means the file grew...I'm having trouble from here*/
I tried a lot of things, but always end up having problems when I try to append the contents from "tempChar" to "buf". I know to use the realloc function..but I'm still having problems. Any help would be appreciated.
Thanks!
You cannot use realloc() for statically allocated memory.
If you wan to do that, you have to use pointers and allocate the memory dynamically.
Example:
char *buf;
buf = malloc(fileSize);

Sprintf Segmentation Fault

numCheck is number between 1-1000. This code gives me a segfault only when I collect the results of sprintf in charcheck. If I simply use sprintf without using the results, I don't get a seg fault. What's happening here?
char * numString;
int charcheck = sprintf(numString, "%d", numCheck);
You need to provide your own memory for sprintf. Also, don't use sprintf, but rather snprintf:
char buf[1000] = {0};
snprintf(buf, 999, ....);
Alternatively you can allocate memory dynamically:
char * buf = new char[BUFSIZE];
snprintf(buf, BUFSIZE-1, ...);
/* ... */
delete[] buf;
The pointer given as the first parameter to sprintf is expected to point to a memory location where sprintf should write the formatted string.
In this case you didn't initialize numString to point to some memory you allocated for the formatted string. Since numString isn't initialized it might point anywhere, and in your case trying to write the formatted output to that location results in a segmentation fault.
The first argument to sprintf must point to a valid buffer. You have a char* but it points to garbage.
Change your code to:
char numString[80] = { };
int charcheck = sprintf(numString, "%d", numCheck);
So that numString actually points to a valid buffer (of 80 characters in this example, all elements of which are initialised to 0).
It would also be good to use snprintf so you can pass the size of your buffer to it, which will help prevent buffer overflows:
const int bufsize = 80;
char numString[bufsize] = { };
int charcheck = snprintf(numString, bufsize - 1, "%d", numCheck);
Notice that you subtract one from the buffer size that you pass to snprintf because you don't want it to use the very last slot, which you want to make sure is NULL to denote the end of the string.
You need to allocate space for the result such as
char numString[50];
int charcheck = sprintf(numString, "%d", numCheck);
In your case the interal workings of sprintf are trying to reference NULL which is the default value for a pointer in your case.
The most straightforward thing to do is to use an array as above, e.g.,
char numString[80] = { };
suggested by Seth, Jesus and Kerrek.
I think the last answer from sth is a good explanation: "the first parameter to sprintf is expected to point to a memory location where sprintf should write the formatted string." So apart from using an array of characters, which would force the allocation of memory for the string, you can also use this:
char *numstring = (char*) malloc(80);
This should let you explicitly free the allocated memory when it is no longer needed.

How to read the standard input into string variable until EOF in C?

I am getting "Bus Error" trying to read stdin into a char* variable.
I just want to read whole stuff coming over stdin and put it first into a variable, then continue working on the variable.
My Code is as follows:
char* content;
char* c;
while( scanf( "%c", c)) {
strcat( content, c);
}
fprintf( stdout, "Size: %d", strlen( content));
But somehow I always get "Bus error" returned by calling cat test.txt | myapp, where myapp is the compiled code above.
My question is how do i read stdin until EOF into a variable? As you see in the code, I just want to print the size of input coming over stdin, in this case it should be equal to the size of the file test.txt.
I thought just using scanf would be enough, maybe buffered way to read stdin?
First, you're passing uninitialized pointers, which means scanf and strcat will write memory you don't own. Second, strcat expects two null-terminated strings, while c is just a character. This will again cause it to read memory you don't own. You don't need scanf, because you're not doing any real processing. Finally, reading one character at a time is needlessly slow. Here's the beginning of a solution, using a resizable buffer for the final string, and a fixed buffer for the fgets call
#define BUF_SIZE 1024
char buffer[BUF_SIZE];
size_t contentSize = 1; // includes NULL
/* Preallocate space. We could just allocate one char here,
but that wouldn't be efficient. */
char *content = malloc(sizeof(char) * BUF_SIZE);
if(content == NULL)
{
perror("Failed to allocate content");
exit(1);
}
content[0] = '\0'; // make null-terminated
while(fgets(buffer, BUF_SIZE, stdin))
{
char *old = content;
contentSize += strlen(buffer);
content = realloc(content, contentSize);
if(content == NULL)
{
perror("Failed to reallocate content");
free(old);
exit(2);
}
strcat(content, buffer);
}
if(ferror(stdin))
{
free(content);
perror("Error reading from stdin.");
exit(3);
}
EDIT: As Wolfer alluded to, a NULL in your input will cause the string to be terminated prematurely when using fgets. getline is a better choice if available, since it handles memory allocation and does not have issues with NUL input.
Since you don't care about the actual content, why bother building a string? I'd also use getchar():
int c;
size_t s = 0;
while ((c = getchar()) != EOF)
{
s++;
}
printf("Size: %z\n", s);
This code will correctly handle cases where your file has '\0' characters in it.
Your problem is that you've never allocated c and content, so they're not pointing anywhere defined -- they're likely pointing to some unallocated memory, or something that doesn't exist at all. And then you're putting data into them. You need to allocate them first. (That's what a bus error typically means; you've tried to do a memory access that's not valid.)
(Alternately, since c is always holding just a single character, you can declare it as char c and pass &c to scanf. No need to declare a string of characters when one will do.)
Once you do that, you'll run into the issue of making sure that content is long enough to hold all the input. Either you need to have a guess of how much input you expect and allocate it at least that long (and then error out if you exceed that), or you need a strategy to reallocate it in a larger size if it's not long enough.
Oh, and you'll also run into the problem that strcat expects a string, not a single character. Even if you leave c as a char*, the scanf call doesn't make it a string. A single-character string is (in memory) a character followed by a null character to indicate the end of the string. scanf, when scanning for a single character, isn't going to put in the null character after it. As a result, strcpy isn't going to know where the end of the string is, and will go wandering off through memory looking for the null character.
The problem here is that you are referencing a pointer variable that no memory allocated via malloc, hence the results would be undefined, and not alone that, by using strcat on a undefined pointer that could be pointing to anything, you ended up with a bus error!
This would be the fixed code required....
char* content = malloc (100 * sizeof(char));
char c;
if (content != NULL){
content[0] = '\0'; // Thanks David!
while ((c = getchar()) != EOF)
{
if (strlen(content) < 100){
strcat(content, c);
content[strlen(content)-1] = '\0';
}
}
}
/* When done with the variable */
free(content);
The code highlights the programmer's responsibility to manage the memory - for every malloc there's a free if not, you have a memory leak!
Edit: Thanks to David Gelhar for his point-out at my glitch! I have fixed up the code above to reflect the fixes...of course in a real-life situation, perhaps the fixed value of 100 could be changed to perhaps a #define to make it easy to expand the buffer by doubling over the amount of memory via realloc and trim it to size...
Assuming that you want to get (shorter than MAXL-1 chars) strings and not to process your file char by char, I did as follows:
#include <stdio.h>
#include <string.h>
#define MAXL 256
main(){
char s[MAXL];
s[0]=0;
scanf("%s",s);
while(strlen(s)>0){
printf("Size of %s : %d\n",s,strlen(s));
s[0]=0;
scanf("%s",s);
};
}

Resources