Why is my C code skipping the next user input? - c

I'm trying to convert my Caesar Cipher code from taking a user given argument to using a user given input, but it's not going the way I've intended at all. I have this code, and it asks the first input for the ROT number, but then it skips the input for the rest of the code. Now, if I wanted to rotate by 2 and use the string bB, the output should be dD, and it is, but only if, when aksed for the input, you put "2 bB". I don't know why this is, and I've looked at other threads saying to just put scanf("%c", &blah);, but I don't know how to do this in my situation. Any help is thankful.
Edit: Changed char to int, as I did in my code just before I posted this.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(){
/**********************************************************************************************************************************/
int bytesRead;
int nbytes = 255;
char *encryptString;
encryptString = (char *) malloc (nbytes + 1);
//char encryptString[256];
char finalChar;
char finalString[256];
int rotNum;
/**********************************************************************************************************************************/
puts("Please enter the ROT (rotate) number you wish to encrypt by: ");
scanf("%d", &rotNum);
printf("Please enter the phrase you'd like to encrypt: \n");
fgets(encryptString, sizeof(encryptString), stdin);
printf("The string entered is: %s\n", encryptString);
printf("The encrypted version is: ");
int n = strlen(encryptString) - 1;
int i;
for(i = 0; i < n; i++){ //For loop to go through the entire string entered
if(isupper(encryptString[i])){
finalChar = (((encryptString[i] - 65) + rotNum) % 26) + 65;
finalString[i] = toupper(finalChar);
//printf("%c\n", finalChar);
}
else if(islower(encryptString[i])){
finalChar = (((encryptString[i] - 97) + rotNum) % 26) + 97;
finalString[i] = tolower(finalChar);
//printf("%c\n", finalChar);
}
else{
finalChar = ' ';
finalString[i] = finalChar;
}
printf("%c", finalString[i]);
}
printf("\n");
return 0;
}

You have few problems in your code:
1)
scanf("%d", &rotNum);
Here you are passing a char * to scanf(). Declare rotNum as int.
2) After reading the input rotNum, scanf() leaves a '\n' in the input buffer.fgets(); stops reading input once encounters a \n. So fgets() doesn't read at all. Use getchar(); after scanf() call to consume the newline char. Or better, read the rotNum using fgets() and parse it using sscanf().
3) Your second argument to fgets() is wrong.
fgets(encryptString, sizeof(encryptString), stdin);
Here, encryptString is a pointer. So this will give you the size of pointer on your platform, not the number of bytes (256) that it points to. Change it to:
fgets(encryptString, 256, stdin); // or whatever the bytes you allocate
Additioanlly,
1) Use a proper return type for main() such as int main(void) or int main(int argc, char **argv) or equivalent.
2) Check the return value of malloc() for NULL to see if it's failed.
3) Casting the malloc() return is unnecessary and error-prone.

I made three changes to your code and it worked without any problem:
1. Use "int rotNum" instead of "char rotNum"
2. Use "scanf("%s", encryptString)" instead of "fgets(encryptString, sizeof(encryptString), stdin)"
3. Either use "int n = strlen(encryptString)" or "for(i = 0; i <= n; i++)"
You have to make some other changes to make it work for negative rotNum.

as the man page of fgets 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.
So when you enter rotate number & then hit enter,the input buffer will contain number\n.
While number will be stored in rotNum , \n will remain in stdin.
So fgets will read it & returns without waiting for input.
Use scanf instead of fgets.
If you are using linux machine, here is the man page

Try fflush(stdin) before using fgets. This should clear the \n from stdin

Related

Program seems to be ignoring one instance of 'gets()' and show an error message when the user hasn't interacted with the program [duplicate]

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int n=1,i,cont;
char string[50];
scanf("%d",&n);
while(n!=0){
gets(string);
cont=0;
for(i=0;i<strlen(string);i++){
if(string[i]=='.'){
cont++;
}
}
if(cont%2==0){
printf("S\n");
}else{
printf("N\n");
}
scanf("%d",&n);
}
return 0;
}
My problem is quite simple but troublesome, I want to read an integer value n, and then read a string, after that read n again, but whenever I run the program, it only reads the string value... but if I digit 0 the program ends... it's like my scanf is within the gets function.
Mixing scanf with gets or fgets is troublesome because they each handle newlines differently.
Get rid of the gets call (which is unsafe anyway) and replace it with the following scanf call:
scanf("%49s", string);
This will read at most 49 characters into string (i.e. one less that its size).
From OP's comments, it sounds like the goal is to be able to read strings containing spaces. While there are ways to accomplish this using scanf(), it would be better to use fgets(), which is at the least less error-prone.
The fgets() function can be used to read input for the number into a buffer, and this buffer can then be processed by sscanf() to extract the number. Since fgets() keeps the newline character, it is not left behind to interfere with the next I/O operation.
But, when fgets() is used to get the string, since the newline is retained, it may be desirable to remove it. This can be accomplished in a number of ways, but here strcspn() is used to provide the index of the first \r or \n character encountered; a \0 character is then written to this location, removing the terminating newline from the string.
The code below illustrates these suggestions. Note that both buffer[] and string[] are generously allocated to accommodate reasonably large inputs. If a user enters a large number of characters (more than 999 in this case), the extra characters are left behind in the input stream for the next I/O function call. Also note that the main loop has been streamlined a bit; now there is a for(;;) loop that never terminates, broken out of when the user enters 0 for the number. And, there is a nested loop within the main loop that prompts the user to enter a number until a valid number is entered. Since the #include <stdlib.h> was unnecessary, it was removed. Better code would check the values returned from the calls to fgets() for possible errors.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n = 1, cont;
char buffer[1000];
char string[1000];
for (;;) {
/* Loop until user enters a number */
do {
printf("Please enter a number: ");
fgets(buffer, sizeof buffer, stdin);
} while (sscanf(buffer, "%d", &n) != 1);
/* Break on 0 */
if (n == 0) break;
/* Get a string, and remove trailing newline */
printf("Please enter a string\n");
fgets(string, sizeof string, stdin);
string[strcspn(string, "\r\n")] = '\0';
cont = 0;
for (size_t i = 0; i < strlen(string); i++) {
if (string[i] == '.') {
cont++;
}
}
if (cont % 2 == 0){
printf("S\n");
} else {
printf("N\n");
}
}
return 0;
}
When you enter 5 for an example, you hit a new line character afterwards.
So you are entering 2 characters: 5 and a new line character.
That new line character is causing your headache.
The new line character is also considered an input.
In order to ignore this new line char, simply add a new line that acts as a garbage collection:
char garbage[50];
scanf( "%d", &n);
fgets(garbage, sizeof(garbage), stdin);

How to scan input from terminal and add to array?

as a homework assignment for my computing 1 college course, my professor has given me the task of having the user input a string of characters into the terminal, taking that string, adding it into an array, then printing the array and printing the array backwards. I think that I know of a way to print the array backwards, however, I cannot come up with a way to read from the terminal and add the characters from the terminal to an array. I have tried doing the following:
char ch;
for (int i = 0; i <= 80 || str[i] == '\n'; ++i) {
scanf_s("%c", &str[i]);
}
I am wondering if someone could explain to me why this section of code does not operate as expected, and if someone could give me some other ideas to try. Thank you.
You are using scanf_s with %c specifier incorrectly.
Please take notice of compiler warnings, there is a size argument missing.
Microsoft's scanf_s is not a direct replacement for scanf.
Unlike scanf ... scanf_s ... requires the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable.
scanf_s("%c", &str[i], 1);
You might also want to filter out any newline which may have been left in the buffer, with
scanf_s(" %c", &str[i], 1);
notice the added space.
Why your code is showing this type of behaviour...
use scanf instead of scanf_s
the conditions you have provided in the for loop are wrong
#include <stdio.h>
int main()
{
char ch;
char str[1000];
int i;
for (i = 0; i <= 80 ; i++)
{
scanf("%c", &str[i]);
if(str[i]=='\n')
{
str[i]='\0';
break;
}
}
printf(str);
}
I could show you the same task in simple manner. I have tried to answer your question in your way. That's why it may seem complicated.
#include <stdio.h>
#define MAX 25
int main()
{
char buf[MAX];
fgets(buf, MAX, stdin);
printf("%s\n", buf);
return 0;
}
fgets- Reads until new line character encountered or maximum limit of character array.

Why is the first value of my char array 10?

I'm new to programming but I wanted to make a program that gets as input a number, (length) and then stores a series of a's and b's of said length. Finally it should output the numbers as the ascii numbers. (so 97 and 98)
I thought I should malloc a char array of the size length and then do a for-loop over it and print everything as an integer.
The problem is however that I get a value 10 as the value of the first letter.
Thanks a lot for any help!
int main()
{
int length;
scanf("%d", &length);
char *matrix = malloc((length + 1 ) * sizeof(char));
for (int i = 0; i < length; i++)
{
scanf("%c", &matrix[i]);
}
for (int i = 0; i < length; i++)
{
printf("\n%d", matrix[i]);
}
return 0;
}
When inputting 3 on the first line and aba on the next line, I get 10 97 98.
However I expected it to be 97 98 97. Why do I get a value of 10 in the first place of the array?
Use
scanf(" %c", &matrix[i]);
^^^^
instead of
scanf("%c", &matrix[i]);
^^
When the format starts with a blank all white spaces are skipped.
From the C Standard (7.21.6.2 The fscanf function)
5 A directive composed of white-space character(s) is executed by
reading input up to the first non-white-space character (which remains
unread), or until no more characters can be read.
10 is the ASCII code of the (white space) new line character '\n' that was present in the input buffer after you entered the length of the array.
The first scanf() with the format string %d leaves a newline in the input buffer.
What happens here, is that your terminal collects input one full line at a time, passing it to the program, and then the scanf() only reads the digits from the buffer, leaving the newline character there for the next scanf() to see. The same would happen if you entered 10 abc: the space, abc and the newline would be left there.
This mismatch is not something people usually expect, and it's one of the things that makes scanf() annoying. I would suggest using fgets() instead to first read a full line, matching what the terminal gives, and then parse the number from it with sscanf() or strtol() (or atoi()).
This cleans up the issue at the point where the first line is read, instead of passing it on to the next input function to handle. Otherwise all your input functions are tied together, if the next input would be for a whole line with possible white space, you'd need to know if you expect to clear a pre-existing newline or not. (You could also replace the later scanf("%c") with getchar(), not that that matters with buffering though.)
That said, the scanf("%c")/getchar() loop may still see newlines if you enter lines that don't have as many characters as the loop expects, so if you don't want to see them at all, filter them out.
So, something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int length;
char linebuf[100];
fgets(linebuf, 100, stdin);
length = strtol(linebuf, NULL, 10);
char *matrix = malloc(length + 1);
for (int i = 0; i < length; i++)
{
matrix[i] = getchar();
}
for (int i = 0; i < length; i++)
{
printf("\n%d", matrix[i]);
}
printf("\n");
return 0;
}
(The obvious downside of fgets() is that you have to decide on a maximum length for the input line, allocate a buffer and call another function in addition to it.)

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.

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