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
?
You can use the following methods to read numbers, strings, and booleans from standard input one at a time: isEmpty() readInt() readDouble()
EOF is just a macro with a value (usually -1). You have to test something against EOF , such as the result of a getchar() call. One way to test for the end of a stream is with the feof function. Note, that the 'end of stream' state will only be set after a failed read.
Use the sys. stdin. readlines() method to read user input until EOF. The readlines() method will return a list containing the lines.
The End of the File (EOF) indicates the end of input. After we enter the text, if we press ctrl+Z, the text terminates i.e. it indicates the file reached end nothing to read.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With