Cannot print array of strings without getting garbage characters - c

int main(int argc, char** argv) {
char *test[5][20];
char *input[20];
int i;
for(i=0;i<5;i++){
printf("enter> ");
fflush ( stdout );
fgets(input,20,stdin);
*test[i] = *input;
}
for(i=0;i<5;i++)
printf("%d | %s\n",i,test[i]);
return 0;
}
Output:
enter> pwd
enter> pathd
enter> ls
enter> echo $path
enter> pwd 0 | pwd
1 | path▒] a▒▒a▒▒#a▒▒ 2 | ls
3 | echo▒▒( 4 | pwd
Press [Enter] to close the terminal
...
I also need to be able to read in input that has spaces. Thanks!

Use memcpy(). And you need to strip trailing newlines. Here:
#include <stdio.h>
#include <string.h>
void chopnl(char *s) { //strip '\n'
s[strcspn(s, "\n")] = '\0';
}
int main() {
char test[5][20];
char input[20];
int i;
for(i=0;i<5;i++){
printf("enter> ");
fflush ( stdout );
fgets(input, 20, stdin);
chopnl(input);
memcpy(test[i], input, strlen(input)+1);//test[i] = input;
}
for(i=0;i<5;i++)
printf("%d | %s\n",i,test[i]);
return 0;
}

Your types are all messed up. A string in C is essentially a pointer to a character which begins a sequence of characters that ends with a null byte.
Input is an array of pointers to characters--or in this purpose, an array of strings. What you're doing is reading 20 characters into input, where input in that fgets expression acts as the address of the first element of the array. So you're reading 20 characters from stdin into input's 20 pointers to characters. This is not what you want. You want to read the characters into space for a string.
I assume you are compiling using GCC--consider using -Wall so GCC warns you about the type issues.
Another issue is
*test[i] = *input;
Since this seems like homework, I feel like I have given enough details.

I know this question is answered and is very old, but the accepted solution is actually wrong. If you enter more than 19 characters stdin will be left with bytes that will be read on the next fgets() and it will find the newline and the next entry will be incorrect.
See the following code and notice a few things:
-- You don't need a separate buffer to read your input into. Just read directly into the array.
-- After reading into the array, remove the '\n'
-- If need be, flush stdin
#include <stdio.h>
#include <string.h>
int main()
{
char test[5][20+1] = {{0}}; // extra space for NULL
int i;
int c;
char *ptr = NULL;
for(i=0;i<5;i++){
printf("enter> ");
fgets(test[i], 20+1, stdin); // fgets read n-1 characters so we add 1 since our buffer has space for null already
if( (ptr = strrchr(test[i], '\n') ) )
{
*ptr = 0x00;
}
else
{
// need to flush stdin since '\n' wasn't found fgets() didn't read all of input
while( (c = getchar()) != '\n' && c != EOF );
}
}
for(i=0;i<5;i++)
printf("%d | %s\n",i,test[i]);
return 0;
}

Related

Why doesn't it wait for me to input string after I exit the loop using CTRL+D

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char c, char_array[100];
int i = 0;
printf("Enter characters (press CTRL+D to end):\n");
while(fgets(char_array+i,sizeof(char_array)-i,stdin)) {
i = i + strlen(char_array+i);
if(char_array[i-1] == EOF)
break;
}
char_array[i-1] = '\0';
strtok(char_array,"\n");
printf("\nEnter a string:\n");
char string[100];
fgets(string,sizeof(string),stdin);
printf("\nCharacter Array: %s\n", char_array);
printf("String: %s\n", string);
return 0;
}
This is the code and I have tried many different variations(simpler) but it always has the same problem... I enter the characters, press CTRL+D and it ends without waiting for me to input a string. please help
I tried everything I could but I just cant make it work and my friends cant too... I have and exam and I need this to be done in 3 days max so I need all the help I can get.
fgets() returns NULL when the stream is closed. On Linux Ctrl-D will flush the terminal buffer if it's not empty (but fgets() will not return as it remains line buffered), and a 2nd Ctrl-D is required to trigger the EOF state of the stream.
You also want to terminate the loop if the array is full otherwise it's an infinite loop:
#define ARRAY_LEN 100
//...
while(i < ARRAY_LEN - 1 && fgets(char_array + i, ARRAY_LEN - i,stdin)) {
fgets() will not emit EOF as part of the string being read, so this is simply incorrect, and as stdin is line buffered the last character is either \n or whatever if the last character was read if the buffer is full which could be -1 or 0xff (whatever char is signed or not but that's still wrong):
if(char_array[i-1] == EOF)
break;
The next line:
char_array[i-1] = '\0';
strips the last character which is either \n or whatever we read last if the array is full (i.e. data loss).
As the input stream is in the EOF state the 2nd fgets() will return NULL. You can clear that state with clearerr(stdin) before calling fgets() to get the 2nd string. If the stream indeed ended, as in, echo "hello world" | ./your_program, the 2nd fgets() with return NULL again of course.
I suggest you use a blank line to signify end of input:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_LEN 100
int main() {
printf("Enter characters (empty line to end):\n");
char char_array[ARRAY_LEN];
for(size_t i = 0; i < ARRAY_LEN - 1; i += strlen(char_array)) {
if(!fgets(char_array + i, ARRAY_LEN - i, stdin)) {
printf("fgets() failed\n");
return 1;
}
if(char_array[i] == '\n') {
char_array[i] = '\0';
break;
}
}
strtok(char_array, "\n");
printf("Enter a string:\n");
char string[ARRAY_LEN];
char *rv = fgets(string,sizeof(string),stdin);
printf("Character Array: %s\n", char_array);
printf("String: %s\n", string);
}
and example session:
Enter characters (empty line to end):
hello
world
Enter a string:
friend
Character Array: hello
String: friend
With stdio streams, error/eof is sticky -- that is, once an error or eof condition has occurred, further operations on the FILE * will continue to return EOF or NULL (depending on the function), rather than trying to read or write anything further.
To reset the eof state on the FILE *, you need to call clearerr(stdin). Once you do that, you can read additional input from the terminal.

C reading lines from stdin

My goal is to read every line from a piped .txt file with the getline() function, but I somehow get a error every time I use this function:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
int Chars;
int size = 10;
char *string;
printf("Please enter a string: ");
string = (char*) malloc(size);
Chars = getline(&string, &size, stdin);
if (Chars == -1)
{
puts("ERROR!");
}
else
{
puts("You entered the following string: ");
puts(string);
printf("\nCurrent size for string block: %d", Chars);
}
return 0;
}
I always get the errorcode: [Error] Id retruned 1 exit status
I've reproduced the linking error on DevC++, in which getline() seems to be missing even after forcing recent C revisions with gcc compiler options such as -std=c11.
So I've rewritten your code using fgets():
char *fgets(char *s, int size, FILE *stream);
It is for sure more portable than getline but has a few differences:
It reads up to size-1 characters if the newline is not encountered before this limit (it automatically appends the string terminator). So it doesn't manage buffer reallocation
The resulting string contains the '\n' character, if found
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STR_SIZE 32
int main( void )
{
int len = 0;
char *str;
printf("Please enter a string: ");
str = malloc(MAX_STR_SIZE); /* (1) */
while( 1 )
{
size_t newline_pos;
fgets( str, MAX_STR_SIZE, stdin );
/* (2) */
if( len == 0) /* (3) */
{
puts("You entered the following string: ");
}
newline_pos = strcspn(str, "\n" );
str[newline_pos] = '\0';
len += strlen(str); /* (4) */
fputs(str, stdout);
if(newline_pos < MAX_STR_SIZE-1) /* (5) */
break;
}
printf("\n\nCurrent size for string block: %d", len);
free( str ); /* (6) */
return 0;
}
So, basically, I just use fgets to read from stdin, iterating until the '\n' character is found. In order to understand is this condition is met, I use strcspn() function, and I use the same function to remove the newline from the resulting string.
A few notes/assumptions (check the corresponding number in code section):
Casting the result of malloc is required only if you are compiling with a C++ compiler. It can be omitted in C
Removed fgets error check: it returns NULL in case of error (no chars read before EOF is found. It won't happen reading from stdin)
Checking for len==0 we make sure that the "You entered the following string: " is printed only once
The length of the string is calculated by summing the length of the strings read in every iteration
The break condition is met when the string contains '\n'. Otherwise strcspn's return value will be MAX_STR_SIZE
Even if the OS will release all the dynamic memory used by the program, on return, it is a good habit always freeing it anyway

how to take input till "only" newline character or a space is inputted ?Basically how to run loop till you enter nothing as input?

i am trying to create a looping which keeps looping till "only" newline charater is inputted or maybe just a space (until nothing is entered to the input line).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
while(1)
{
scanf("%d",&num);
if(num==NULL)
break;
printf("%d",num);
}
return 0;
}
You can't do that with scanf (at least not easily). If you want to process user input, scanf is a bad choice (in fact, in all my years of developing in C, I've never used scanf; I recommend you avoid it altogether).
num==NULL makes no sense: num is a number, but NULL is a pointer value. If you want to check whether scanf was successful, you need to check its return value.
I'd do something like:
char line[100];
while (fgets(line, sizeof line, stdin)) { // read input line by line
int num;
if (sscanf(line, "%d", &num) != 1) { // the line didn't start with a valid integer
break;
}
printf("%d\n", num);
}
If you want to check specifically for an empty string, not just something that doesn't look like a number, you could use strspn:
if (line[strspn(line, " \t\n")] == '\0') {
// line contains spaces / tabs / newlines only
There are other things that can be on a line other than an integer. Your code indicates an integer expected, but your text only indicates the line is blank or only contains a space.
Given your text in the question:
#include <stdio.h>
#include <string.h>
int main( void )
{
char line[1024];
while( fgets( line, sizeof( line ), stdin ) )
{
if( (strlen( line ) == 1 )
|| (strlen( line ) == 2 && line[0] == ' '))
{
// all done
break;
}
else
{
// process line
}
} // end while
}

Extreme troubles with full line input. C Programming Language

I am having the absolute craziest time getting full line input to work. I will explain my problem. I need to get a full line of input, including a space, from the user entered at the keyboard. Simple right? Wrong!
MY GOAL
Store multiple strings, with spaces, into variables. If it makes a difference, I want to make the variables equal to a char pointer. So once I get the input from tempString, I want to set it to a char pointer. Like so:
char *variable1, *variable2;
//get user input
variable1 = tempString;
//get more user input
variable 2 = tempString;
//etc etc etc
Here's what I've tried.
First try
char tempString[100];
scanf("%s", &tempString);
printf("%s", tempString);
Invalid: scanf will stop reading at a white space, so "Example String" would just end up being "Example".
Second try
So I do more research. I thought I found the magic fix.
char tempSTring[100];
fgets(tempString, 100, stdin);
printf("%s", tempString);
Originally this works. However there is a massive problem. I need to get the user to enter about 8 inputs. Meaning I have to use a command like this 8 times. The problem is the program often skips over the fgets command. If I use a scanf previously, somehow the \n character is stuck in the input stream, and automatically feeds into fgets, satisfying its stdin input, and then does not prompt the user for input.
Third try
After thinking fgets was maybe my solution with a work around, I tried some tricks.
char tempSTring[100];
getc(stdin);
fgets(tempString, 100, stdin);
printf("%s", tempString);
I tried adding this getc(stdin) line. It worked for much of my program. It absorbs the \n character left behind in the stream. When it does so, great, it works. But sometimes, for some reason, the \n is NOT left in the stream, and when debugging, it looks like getc(stdin) is requesting input from the user, so it pauses my program to ask for input.
Question
These don't work for me.
How should I be doing this easy task?
To read (up to) 8 lines from a file, you can use either of these solutions. I decline to use variables char *variable1, *variable2, …; — that is an array seeking to escape.
POSIX getline()
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
enum { MAX_LINES = 8 };
char *lines[MAX_LINES];
int index = 0;
char *buffer = 0;
size_t buflen = 0;
while (index < MAX_LINES && getline(&buffer, &buflen, stdin) != -1)
{
lines[index++] = buffer;
buffer = 0;
buflen = 0;
}
free(buffer); // Space may be allocated before EOF is detected
for (int i = 0; i < index; i++)
printf("%d: %s", i, lines[i]);
return 0;
}
If getline() fails to allocate memory, it will report an error, so there is no need to do an explicit error check.
Standard C fgets()
Code using strdup(), another POSIX function. It isn't a part of standard C (though it is widely available). It is trivial to implement.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
enum { MAX_LINES = 8 };
char *lines[MAX_LINES];
int index = 0;
char buffer[4096];
while (index < MAX_LINES && fgets(buffer, sizeof(buffer), stdin) != 0)
{
if ((lines[index] = strdup(buffer)) == 0)
break;
index++;
}
for (int i = 0; i < index; i++)
printf("%d: %s", i, lines[i]);
return 0;
}
The test in the loop allows for the possibility of strdup() failing to allocate memory.
Notes
Both the solutions above keep the newline at the end of the input string. If you don't want that, you can zap it with:
lines[i][strcspn(lines[i], "\r\n")] = '\0';
This overwrites a carriage return or newline with a null byte, transforming DOS or Unix line endings. You then need to adjust the printing which assumes the string includes a newline. Note that the expression shown works correctly even if there is no carriage return or newline in the string.
The fgets() solution will break lines at 4095 characters, leaving the rest to be read as 'the next line'. If that's not acceptable, you have a variety of strategies open to you.
You can detect whether there is a newline and arrange to allocate more memory and read the next section of the line into the extra memory, repeating until you come across a newline or EOF.
You can read the remaining characters up to the newline or EOF:
int c;
while ((c = getchar()) != EOF && c != '\n')
;
Implementing strdup()
If for some reason your system doesn't have an implementation of strdup(), you can create a surrogate with:
#include <assert.h>
#include <stdlib.h>
#include <string.h>
char *strdup(const char *old_str)
{
assert(old_str != 0);
size_t old_len = strlen(old_str) + 1;
char *new_str = malloc(old_len);
if (new_str != 0)
memmove(new_str, old_str, old_len);
return new_str;
}
Here's how we old fart C programmers would do it:
#include <stdio.h>
#define MAX_LEN 100
int main( )
{
int c;
char input[MAX_LEN+1];
int i = 0;
while ( (c=getchar()) != '\n' && c != EOF && i < MAX_LEN)
input[i++] = c;
if (c == EOF || c =='\n') {
/* received input that terminated within buffer limit */
input[i] = '\0';
printf("read in your input string of: %s\n", input);
}
else {
printf("don't buffer overflow me dude!\n");
return -1;
}
return 0;
}
But nowadays people will tell you to use one of the library functions. I'm still an old fart though.
EDIT: Fixed my embarrassing mistakes pointed out by the helpful comments below.
You can take care of '\n' left by previous scanf by writing it like this -
scanf("%d%*c", &x); //<-- example to take int input
%*c will read from stdin and then discard it, thus '\n' would be removed from stdin.
You can achieve with scanf like this (a way for your previous attempt)-
char tempString[100];
/* As suggested by chqrile it is essential to check return of scanf */
if(scanf("%99[^\n]", tempString)!=1){
// ^^ & not required
tempString[0]='\0';
}
%99[^\n] this will read 99 characters and will stop only after encountering '\n' , thus would read input with spaces.

A random text as output

My goal is a function that returns the same text as I wrote in stdin.
As a result of compilation of the code below:
#include <stdio.h>
char chain[990];
int znaki()
{
scanf("%s", chain);
int i=0;
do{
putchar(chain[i]);
i++;
}
while(chain[i]!=10);
return 0;
}
int main(int argc, char **argv)
{
znaki();
return 0;
}
I get:
MyOwnText
MyOwnText
and
many
lines
of
some
random text just like cat /dev/random in linux
The first line is my input.
Why?
do {
putchar(chain[i]);
i++;
} while(chain[i]!=10);
This code prints characters from chain (and further) until finds a char with code 10. As the buffer is uninitialized, it is filled with some random data from other programs. And you see that data.
Probably, you wanted to write something like
do {
putchar(chain[i]);
i++;
} while(i != 10);
which would print first 10 chars from the array.
And by the way, the code seems to be vulnerable to a buffer overflow.
You have an array.
You asked the user for a word, and you stored it in the beginning of that array.
You then printed the array.
It's pretty obvious to me why the input you wrote was printed out.
chain[] does not have the value of 10.
chain is filled with non-white-space characters - that is what "%s" directs scanf() to do: scan and save non-white-space char. 10 is typically '\n', a white-space.
char chain[990];
scanf("%s", chain);
...
while(chain[i]!=10);
Instead use fgets() to read lines.
int znaki(void) {
char chain[990];
while (fgets(chain, sizeof chain, stdin) != NULL) {
int i=0;
while (chain[i] != '\n' && chain[i] != '\0') {
putchar(chain[i]);
i++;
}
return 0;
}

Resources