C , fgets() scans extra char while trying to scan a string - c

The problem is that when you enter a name such as elvis (which has 5 letters), it will print this:
Please enter your name.
elvis
Your name is elvis
and it is 6 letters long.
Press any key to continue . . .
the problem is that it makes another unnecessary line thats because after the elvis I pressed enter.
Sorry for being a new user , im new for these rules , please correct me and educate me , thanks for your time.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define STR_LEN 7
int main(void)
{
char name[10] = {0};
printf("Please enter your name.\n");
fgets(name ,10, stdin);
printf("Your name is %s and it is %d letters long.\n" , name , strlen(name));
system("PAUSE");
return 0;
}

fgets always writes that '\n' character at the end, if it fits (and, of course, sees it). So you need to manually remove it.
(I know because I've said it 20 times to my groupmates in University :/ )
You need to check if the last character is '\n' and, if so, remove it (overwrite with 0=='\0'). Some example code:
char str[256];
fgets(str, 256, stdin);
if (*str && str[strlen(str)-1] == '\n')
str[strlen(str)-1] = 0;
(note that the above code assumes GCC optimizes pure function calls. If not you should save the length in a separate variable to optimize the program)

As how the fellow mates told you already, fgets gets chars from a file pointer(stdin in your case) adding to the name an extra '\n'.
You can easly get rid of it writing something like
name[strlen(name)-1] = '\0';
Always format your printf its %lu not %d on strlen(name).
Also a good tip, please always check for errors in return of the function.
Please, after posting here, always consult the linux man (fgets stdlib func), try some examples, debug them, search and read on google even on stack overflow you have a nice search option for it.(it's not hate, just a friendly general advice).
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define STR_LEN 7
int main(void)
{
char name[10] = {0};
printf("Please enter your name.\n");
if (!fgets(name ,10, stdin)) {
printf("Error reading from stdin");
return 1;
}
size_t len = strlen(name);
if (len > 0 && name[len-1] == '\n') {
name[len-1] = '\0';
}
printf("Your name is %s and it is %lu letters long.\n" , name , strlen(name));
system("PAUSE");
return 0;
}
EDITED:(melpomene advice).

Related

How to print different strings depending on the input?

I want one message to appear if the name Emily or Jack is entered and a different message for another input.
My code:
#include <stdio.h>
#include <string.h>
int main()
{
char name;
printf("What is your name?");
gets(name);
if ((strcmp(name,"Emily") == 0) || (strcmp(name,"Jack") == 0))
{
printf("Hello %s\n", name);
} else
{
printf("Welcome Stranger!\n");
}
return 0;
}
This code will compile but won't output anything.
The first problem is that name can store exactly one char, to store a string of characters you'll need a char array.
The second problem, not causing the faulty behavior but equaly important, is the use of gets. This function was deprecated in C99 and removed from the international standard with C11, and for good reason, it's very dangerous as it can easily overflow the destination buffer, it has no control over the length of the input stream. fgets is regularly used instead.
char name[256]; //array store the name
//...
fgets(name, sizeof name, stdin); //safe, can't overflow the buffer, input size is limited
name[strcspn(name, "\n")] = '\0'; //fgets parses the newline character, it must be removed
//...

scanf read variable number of characters

I was wondering how I can get scanf to skip reading a character if I press enter... My code is the following:
#include <stdio.h>
int main(void)
{
int a, status;
char b;
printf("Please enter a positive number immediately"
"followed by at most one lower-case letter:\n\n");
status = scanf("%i%c", &a, &b);
if (status == 1 && getchar() == '\n') {
printf("\nThank you!\n");
}
return 0;
}
When I enter just a number and nothing else, I need to press enter again to trigger the %c, &b in scanf. How do I avoid that and get the program to accept just 1 number to jump to the printf?
I tried:
if (status == 1 && getchar() == '\n')
but that won't work.
As noted in the comments, your best course of action is to use fgets to just read in a string, then parse and validate it. This Thread will provide you with enough resources for you to educate yourself about the use of fgets.
Here is one approach you can take. Please note that this code does not attempt to validate every possible input a user can provide, but rather give you a reasonable direction you can take to solve your problem if the input is assumed correct. I will leave the task of validation to you. The code below should provide enough tools to accomplish the rest of your task. Look at using a for loop to step through the buffer and ensure the input is correct. Use isalpha() and isdigit() to test each character. You can also implement your own functions to test each character as is done
in this answer.
#include <stdio.h>
#include <stdlib.h> //for atoi()
#include <string.h> //for strlen()
#include <ctype.h> //for isalpha()
#define MAX_INPUTLENGTH 500
int main(void)
{
//Always a good idea to initialize variables to avoid Undefined Behaviour!
char buffer[MAX_INPUTLENGTH] = { '\0' };
int a = 0, status = 1, length = 0;
char b = '\0';
printf("Please enter a positive number immediately"
"followed by at most one lower-case letter:\n\n");
//this gets you a string you can work with
fgets(buffer, sizeof(buffer), stdin);
length = strlen(buffer);
buffer[length - 1] = '\0';//remove the trailing '\n'
length--;
//now see if last character is a letter
if (isalpha(buffer[length - 1])) {
b = buffer[length - 1];//then assign and..
buffer[length - 1] = '\0';//trim the letter
}
//this function converts the remaining string to an int
a = atoi(buffer);
//Use the debugger and observe how these functions work in order
//to validate the input. for now, status is always 1!
if (status == 1) {
printf("\nThank you!\n");
}
return 0;
}
As noted in the comments below by #Jonathan, to portably get the count of an array, one should use sizeof(buffer) / sizeof(buffer[0]). Since you are using a char[], sizeof(buffer[0]) evaluates to 1, thus can be omitted when calling fgets.

Trying to take someone's full name and return their initials in C

I am new to C and I am trying to write a program that takes an entered name, like john smith, and returns the uppercase initials, JS. I've tried using a for loop and a while loop, but my code does not seem to increment, whenever I run it all it returns is the first initial. I've searched the web for this problem, but none of the solutions worked for me. What am I doing wrong? Thanks in advance.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(void) {
// initialize variables
char name[61];
int i = 0;
// ask for user input
printf("Please enter your name: ");
scanf("%s", name);
// print first initial
printf("%c", toupper(name[0]));
// print the next ones
while (name[i] != '\0') {
if (name[i] == ' ') {
i++;
printf("%c", toupper(name[i+1]));
}
i++; // does not increment
}
return 0;
}
scanf() reads the input until a space is encountered. So writing the full name will have a space in between the first and the last name. That would stop scanf() and it would read only the first name.
To read both input with space, better use fgets(). fgets() reads the string until a newline \n is encountered.
fgets(name, 61, stdin);
scanf("%s", name) only reads the first name. You need something like scanf("%s %s", first_name, last_name)

Add two strings in C

How would I add a string to a string that I get from scanf?
Do this:
char animal[size];
scanf("%s", animal);
Then add "Is it a animal?" to whatever is input, then return the whole thing as animal again.
For example if I input 'duck' for animal, it will make animal return "Is it a duck?"
Also, should I add the ? to animal first then add "Is it a "?
Here is a quick and dirty working example of how this could be done.
However, it is not very safe/foolproof. E.g., you can easily overrun the animal buffer with scanf(). Also, if you change the format of the string in sprintf(), you'll need to make sure str has enough room.
#include <stdio.h>
int main()
{
char animal[20];
char str[29];
animal[19] = 0; /* make sure animal is 0-terminated. Well, scanf() will 0-term it in this case anyway, but this technique is useful in many other cases. */
printf("Name the beast (up to 19 characters): ");
scanf("%s", animal);
sprintf( str, "Is it a %s?", animal );
puts(str);
return 0;
}
And here is a somewhat improved version. We make sure that we don't read more characters than the animal buffer can hold, define a pre-processor macro for the maximum animal name length for easier maintenance, trap the case when the user entered more characters than asked, get rid of the newline that terminates user input.
#include <stdio.h>
#include <string.h>
#define MAX_ANIMAL_NAME_LEN 9
int main()
{
/* 1 char for 0-terminator + 1 to catch when a user enters too
many characters. */
char animal[MAX_ANIMAL_NAME_LEN + 2];
char str[MAX_ANIMAL_NAME_LEN + 11];
printf("Name the beast (up to %d characters): ", MAX_ANIMAL_NAME_LEN);
fgets( animal, MAX_ANIMAL_NAME_LEN + 2, stdin );
{
/* fgets() may include a newline char, so we get rid of it. */
char * nl_ptr = strchr( animal, '\n' );
if (nl_ptr) *nl_ptr = 0;
}
if (strlen(animal) > MAX_ANIMAL_NAME_LEN)
{
fprintf( stderr, "The name you entered is too long, "
"chopping to %d characters.\n", MAX_ANIMAL_NAME_LEN );
animal[MAX_ANIMAL_NAME_LEN] = 0;
}
sprintf( str, "Is it a %s?", animal );
puts(str);
return 0;
}
As other users have pointed out, strings in C, as the C language itself, can get fairly tricky pretty fast. Further improvements will be your homework. Search engines are your friends. Happy learning!
One treacherous pitfall you may want to beware is that there is still input to be read from STDIN if the user has typed more than fgets() wanted to accept. If you call fgets() or some other input function later on, you will read those extra characters, which is probably not what you wanted! Please see the following posts:
How to clear input buffer in C?
C: Clearing STDIN
Thanks to chux for pointing this out.
If you just want to display the message of "Is it a ___?" you can just output it like
char animal[size];
scanf("%s", animal);
printf("Is it a %s?", animal);
How would I add a string to a string that I get from a scanf?
Adding two different strings,.
#include <stdio.h>
#include <string.h>
int main(void)
{
char animal[20], text1[20] = "Is it a ";
scanf("%11s", animal);
strcat(text1, animal);
printf("%s\n", text1);
return 0;
}

Reading string from input with space character? [duplicate]

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 4 years ago.
I'm using Ubuntu and I'm also using Geany and CodeBlock as my IDE.
What I'm trying to do is reading a string (like "Barack Obama") and put it in a variable:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
scanf("%s", name);
printf("Your Name is: %s", name);
return 0;
}
Output:
Enter your name: Barack Obama
Your Name is: Barack
How can I make the program read the whole name?
Use:
fgets (name, 100, stdin);
100 is the max length of the buffer. You should adjust it as per your need.
Use:
scanf ("%[^\n]%*c", name);
The [] is the scanset character. [^\n] tells that while the input is not a newline ('\n') take input. Then with the %*c it reads the newline character from the input buffer (which is not read), and the * indicates that this read in input is discarded (assignment suppression), as you do not need it, and this newline in the buffer does not create any problem for next inputs that you might take.
Read here about the scanset and the assignment suppression operators.
Note you can also use gets but ....
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
Try this:
scanf("%[^\n]s",name);
\n just sets the delimiter for the scanned string.
Here is an example of how you can get input containing spaces by using the fgets function.
#include <stdio.h>
int main()
{
char name[100];
printf("Enter your name: ");
fgets(name, 100, stdin);
printf("Your Name is: %s", name);
return 0;
}
scanf(" %[^\t\n]s",&str);
str is the variable in which you are getting the string from.
The correct answer is this:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
// pay attention to the space in front of the %
//that do all the trick
scanf(" %[^\n]s", name);
printf("Your Name is: %s", name);
return 0;
}
That space in front of % is very important, because if you have in your program another few scanf let's say you have 1 scanf of an integer value and another scanf with a double value... when you reach the scanf for your char (string name) that command will be skipped and you can't enter value for it... but if you put that space in front of % will be ok everything and not skip nothing.
NOTE: When using fgets(), the last character in the array will be '\n' at times when you use fgets() for small inputs in CLI (command line interpreter) , as you end the string with 'Enter'. So when you print the string the compiler will always go to the next line when printing the string. If you want the input string to have null terminated string like behavior, use this simple hack.
#include<stdio.h>
int main()
{
int i,size;
char a[100];
fgets(a,100,stdin);;
size = strlen(a);
a[size-1]='\0';
return 0;
}
Update: Updated with help from other users.
#include <stdio.h>
// read a line into str, return length
int read_line(char str[]) {
int c, i=0;
c = getchar();
while (c != '\n' && c != EOF) {
str[i] = c;
c = getchar();
i++;
}
str[i] = '\0';
return i;
}
Using this code you can take input till pressing enter of your keyboard.
char ch[100];
int i;
for (i = 0; ch[i] != '\n'; i++)
{
scanf("%c ", &ch[i]);
}
While the above mentioned methods do work, but each one has it's own kind of problems.
You can use getline() or getdelim(), if you are using posix supported platform.
If you are using windows and minigw as your compiler, then it should be available.
getline() is defined as :
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
In order to take input, first you need to create a pointer to char type.
#include <stdio.h>
#include<stdlib.h>
// s is a pointer to char type.
char *s;
// size is of size_t type, this number varies based on your guess of
// how long the input is, even if the number is small, it isn't going
// to be a problem
size_t size = 10;
int main(){
// allocate s with the necessary memory needed, +1 is added
// as its input also contains, /n character at the end.
s = (char *)malloc(size+1);
getline(&s,&size,stdin);
printf("%s",s);
return 0;
}
Sample Input:Hello world to the world!
Output:Hello world to the world!\n
One thing to notice here is, even though allocated memory for s is 11 bytes,
where as input size is 26 bytes, getline reallocates s using realloc().
So it doesn't matter how long your input is.
size is updated with no.of bytes read, as per above sample input size will be 27.
getline() also considers \n as input.So your 's' will hold '\n' at the end.
There is also more generic version of getline(), which is getdelim(), which takes one more extra argument, that is delimiter.
getdelim() is defined as:
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
Linux man page
If you need to read more than one line, need to clear buffer. Example:
int n;
scanf("%d", &n);
char str[1001];
char temp;
scanf("%c",&temp); // temp statement to clear buffer
scanf("%[^\n]",str);
"%s" will read the input until whitespace is reached.
gets might be a good place to start if you want to read a line (i.e. all characters including whitespace until a newline character is reached).
"Barack Obama" has a space between 'Barack' and 'Obama'. To accommodate that, use this code;
#include <stdio.h>
int main()
{
printf("Enter your name\n");
char a[80];
gets(a);
printf("Your name is %s\n", a);
return 0;
}
scanf("%s",name);
use & with scanf input

Resources