Unnecessary newlines using function 'printf' - c

When allocating Strings on the heap (with 'malloc'),
and initializing them with the standard input (using 'fgets),
an unnecessary newline appears between them when trying to print them (with 'printf' and %s formatting).
for example:
main()
{
char *heap1;
char *heap2;
heap1=malloc(10);
heap2=malloc(10);
fgets(heap1,10,stdin);
fgets(heap2,10,stdin);
printf("%s%s",heap1,heap2);
}
with input "hi1\nhi2" produces "hi1\nhi2".
compiled using gcc 4.3.4 for Debian.

fgets also reads the '\n' (newline) character. You should remove it if you don't want it to print like that.
heap1[strlen(heap1) - 1] = '\0';
after you read the contents of heap1.

fgets returns the newline as part of the string.
See man 3 fgets. Specifically:
fgets() reads in at most one less
than size characters from stream and
stores them into the buffer pointed
to by s. Reading stops after an
EOF or a newline. If a newline is
read, it is stored into the buffer.
A '\0' is stored after the last
character in the buffer.

fgets is probably appending the newline. Try trimming the string you get back from fgets.

Related

How Can I Scan a File in a Way That Doesn't Discard Newlines

I am relatively new to C programming, but, from what I understand, fscanf skips any whitespace when scanning input for every type beside characters. What other means do I have to scan integers while keeping any newline character that may be attached to them within the file (as I actually want to do something with these newline characters)?
You can use fgets in the following format:
char *fgets(char *s, int size, FILE *stream);
and as it's man page says:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is
stored after the last character in the buffer.
It will read a newline character, however it will stop reading after that and terminate with the null character.
You could use fcanf(file,"%[^\n]") which takes everything up to user hit enter.

Why fgets takes cursor to next line?

I have taken a string from the keyboard using the fgets() function. However, when I print the string using printf(), the cursor goes to a new line.
Below is the code.
#include<stdio.h>
int main()
{
char name[25];
printf("Enter your name: ");
fgets(name, 24, stdin);
printf("%s",name);
return 0;
}
And below is the output.
-bash-4.1$ ./a.out
Enter your name: NJACK1 HERO
NJACK1 HERO
-bash-4.1$
Why is the cursor going to the next line even though I have not added a \n in the printf()?
However, I have noticed that if I read a string using scanf(), and then print it using printf() (without using \n), the cursor does not go to next line.
Does fgets() append a \n in the string ? If it does, will it append \0 first then \n, or \n first and then \0?
The reason printf is outputting a newline is that you have one in your string.
fgets is not "adding" a newline --- it is simply reading it from the input as well. Reading for fgets stops just after the newline (if any).
Excerpt from the manpage, emphasis mine:
The fgets() function reads at most one less than the number of characters specified by size from the given stream and stores them in the string str. Reading stops when a newline character is found, at end-of-file or error. The newline, if any, is retained. If any characters are read and there is no error, a `\0' character is appended to end the string.
An easy way to check if there's a newline is to use the help of one of my favorite little-known functions --- strcspn():
size_t newline_pos = strcspn(name, "\r\n");
if(name[newline_pos])
{
/* we had a newline, so name is complete; do whatever you want here */
//...
/* if this is the only thing you do
you do *not* need the `if` statement above (just this line) */
name[newline_pos] = 0;
}
else
{
/* `name` was truncated (the line was longer than 24 characters) */
}
Or, as an one-liner:
// WARNING: This means you have no way of knowing if the name was truncated!
name[strcspn(name, "\r\n")] = 0;
Because if there is a '\n' in the read text it will be taken by fgets(), the following was extracted from the 1570 draft §7.21.7.2 ¶ 2
The fgets function reads at most one less than the number of characters specified by n
from the stream pointed to by stream into the array pointed to by s. No additional
characters are read after a new-line character (which is retained) or after end-of-file. A
null character is written immediately after the last character read into the array.
I highlighted by making bold the part which says that the '\n' is kept by fgets().

Difference between fgets and fscanf?

I have a question concerning fgets and fscanf in C. What exactly is the difference between these two? For example:
char str[10];
while(fgets(str,10,ptr))
{
counter++;
...
and the second example:
char str[10];
while(fscanf(ptr,"%s",str))
{
counter++;
...
when having a text file which contains strings which are separated by an empty space, for example: AB1234 AC5423 AS1433. In the first example the "counter" in the while loop will not give the same output as in the second example. When changing the "10" in the fgets function the counter will always give different results. What is the reason for this?
Can somebody please also explain what the fscanf exactly does, how long is the string in each while loop?
The function fgets read until a newline (and also stores it). fscanf with the %s specifier reads until any blank space and doesn't store it...
As a side note, you're not specifying the size of the buffer in scanf and it's unsafe. Try:
fscanf(ptr, "%9s", str)
fgets reads to a newline. fscanf only reads up to whitespace.
In your example, fgets will read up to a maximum of 9 characters from the input stream and save them to str, along with a 0 terminator. It will not skip leading whitespace. It will stop if it sees a newline (which will be saved to str) or EOF before the maximum number of characters.
fscanf with the %s conversion specifier will skip any leading whitespace, then read all non-whitespace characters, saving them to str followed by a 0 terminator. It will stop reading at the next whitespace character or EOF. Without an explicit field width, it will read as many non-whitespace characters as are in the stream, potentially overruning the target buffer.
So, imagine the input stream looks like this: "\t abcdef\n<EOF>". If you used fgets to read it, str would contain "\t abcdef\n\0". If you usedfscanf, str could contain "abcdef\0" (where \0 indicates the 0 terminator).
fgets read the whole line. fscanf with %s read a string, separate by space (or \n,\t,etc...).
Anyway, you should not use them unless you sure that the array you read to is big enough to contain the input.
You wrote When changing the "10" in the fgets function the counter will always give different results. Note that fgets and scanf don't know how much bytes to read. you should tell them. changing the "10" just enlarge the buffer these functions write to.

Why is my output formatted, i.e. '\n' automatically in fgets?

Here is my code
#include<stdio.h>
int main()
{
FILE* fp;
int i;
fp=fopen("newfile","r");
if(fp==NULL)
{
printf("hhaha");
return 0;
}
char str[20];
for(i=0;i<2;i++)
{
fgets(str,20,fp);
printf("%s",str);
}
return 0;
}
Now if my newfile has text
my name
is xyz
then how come when i print the two lines are printed in two newlines?
where does the newline character come from?
fgets sets the pointer to a char * representing the line of the file including the \n at the end of the line. (As is the case with most strings, it will also be '\0' terminated)
A file with this:
Thisismyfile
Will have this from fgets:
This\n\0,is\n\0,my\n\0,file\n\01
1The final value may not be include \n. That will depend on whether it is a \n terminated file.
from man fgets
gets() reads a line from stdin into the buffer pointed to
by s until either a terminating newline or EOF, which it replaces with
'\0'. No check for buffer overrun is performed
(see BUGS below).
fgets() reads in at most one less than size characters from
stream and stores them into the buffer pointed to by s. Reading stops
after an EOF or a newline. If a newline is read,
it is stored into the buffer. A '\0' is stored after the last
character in the buffer.
and thus fgets behaviour is different from what you might expect
From the linux man page for fgets():
fgets() reads in at most one less than size characters from
stream and stores them into the buffer pointed to by s. Reading stops
after an EOF or a newline. If a newline is read, it is stored into
the buffer. A '\0' is stored after the last character in thebuffer.
fgets() includes the newline when reading into the string - that's how fgets() is defined to work. From the standard:
No additional characters are read after a new-line character (which is retained) or after end-of-file.

c, gets(),fgets()

char s1[100];
char s2[100];
gets(s1);
fgets(s2,sizeof(s2),stdin);
printf("%d,%d\n",strlen(s1),strlen(s2));
after run, I input "abcd" two times,
and the result i got is : 4,5
why is that?
From the gets / fgets man page:
The fgets() function reads at most one less than the number of characters
specified by n from the given stream and stores them in the string s.
Reading stops when a newline character is found, at end-of-file or error.
The newline, if any, is retained. If any characters are read and there
is no error, a `\0' character is appended to end the string.
The gets() function is equivalent to fgets() with an infinite n and a
stream of stdin, except that the newline character (if any) is not stored
in the string. It is the caller's responsibility to ensure that the
input line, if any, is sufficiently short to fit in the string.
fgets keeps the newline, which is character number 5, but gets doesn't.
Also, get into a habit of using fgets always, as it is impossible to prevent buffer overflows when using gets.
Because fgets returns the string with '\n' at the end while gets not.
From the gets() man page:
The gets() function is equivalent to fgets() with an infinite n and a stream of stdin, except that the newline character (if any) is not stored in the string.

Resources