Program is not accepting second string and giving output directly - c

Here I want to compare two strings in case2. case 1 works well but when I go to case 2 it's not asking for second string input and directly prints "Both strings are different"[1]
[1]: https://i.stack.imgur.com/l2J6L.jpg
#include <stdio.h>
#include <stdlib.h>
#define size 20
int main ()
{
char str1[size],str2[size];
int operation,error=0,i=0;
printf("Enter String: ");
fgets(str1, size, stdin);
do {
printf("1.Copy\n2.Compare\n3.Exit\nWhich operation you want to do:");
scanf("%d",&operation);
switch (operation) {
case 1:
for (int i=0; str1[i] != '\0'; i++) {
str2[i] = str1[i];
}
printf("First string: %s\n",str1);
printf("Second string: %s\n",str2);
break;
default:
printf("Error");
break;
case 2:
printf("Enter second string: "); // it's not executing (Not takin input) and directly i get o/p of line 39
fgets(str2, size, stdin);
for (i=0; str2[i] != '\0'; i++) {
if (str1[i] != str2[i]) {
error++;
}
}
if (error == 0) {
printf("Both strings are same.\n");
}
else
printf("Both strings are not same.\n");
break;
}
} while (operation != 3);
}

As scanf leaves behind a dangling newline character \n it causes the fgets to not wait for the input from the user. Try flushing the input buffer by using getchar.
Update: Added loop to remove all the characters which are skipped by the scanf but can be entered by the user like extra white spaces after the number.
...
do {
printf("1.Copy\n2.Compare\n3.Exit\nWhich operation you want to do:");
scanf("%d",&operation);
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
switch (operation) {
...
Reference: faq.cprogramming.com

Since your strings are lines, scanf() is not a good choice except for getting the integer value, and to clean the buffer of everything after that (might be all sorts of junk, never trust a user), do a fgets into str2. Your new lines will compare, too, if they are identical. You should also test the return from scanf is 1, saying you got a number! What if a user types in 'x' as the number? If you want to ask again, you need to clean the junk out of the buffer. Remember that, since you have 'cooked' input, nothing is sent until the user hits enter, so you always need to deal with the new line character. If all you do is scanf in numbers, scanf will got through an new line as white space seeking a digit, but you are doing mixed string and number input.
You need to compare a null to mis-compare if one string is a prefix of the other, so in 'for' test 'i < size' but break out of the loop if both strings have a null at the same point ( !str1[i] && !str2[i] ) or on the first miscompare (setting error). There is no point in comparing past the first miss! In the prefix case, the null mis-compares some other char value.
Since trailing spaces are part of your string, you might print them in single quotes (after removing the new line).

Related

Issues with scanf() and accepting user input

I am trying to take in user input with spaces and store it in an array of characters.
After, I want to take in a single character value and store it as a char.
However, when I run my code, the prompt for the character gets ignored and a space is populated instead. How can I take in an array of chars and still be allowed to prompt for a single character after?
void main()
{
char userIn[30];
char findChar;
printf("Please enter a string: ");
scanf("%[^\n]s", userIn);
printf("Please enter a character to search for: ");
scanf("%c", &findChar);
//this was put here to see why my single char wasnt working in a function I had
printf("%c", findChar);
}
scanf("%c", &findChar); reads the next character pending in the input stream. This character will be the newline entered by the user that stopped the previous conversion, so findChar will be set to the value '\n', without waiting for any user input and printf will output this newline without any other visible effect.
Modify the call as scanf(" %c", &findChar) to ignore pending white space and get the next character from the user, or more reliably write a loop to read the read and ignore of the input line.
Note also that scanf("%[^\n]s", userIn); is incorrect:
scanf() may store bytes beyond the end of userIn if the user types more than 29 bytes of input.
the s after the ] is a bug, the conversion format for character classes is not a variation of the %s conversion.
Other problems:
void is not a proper type for the return value of the main() function.
the <stdio.h> header is required for this code.
Here is a modified version:
#include <stdio.h>
int main() {
char userIn[30];
int c;
char findChar;
int i, found;
printf("Please enter a string: ");
if (scanf("%29[^\n]", userIn) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
/* read and ignore the rest of input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("Please enter a character to search for: ");
if (scanf("%c", &findChar) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
printf("Searching for '%c'\n", findChar);
found = 0;
for (i = 0; userIn[i] != '\0'; i++) {
if (userIn[i] == findChar) {
found++;
printf("found '%c' at offset %d\n", c, i);
}
}
if (!found) {
printf("character '%c' not found\n", c);
}
return 0;
}
scanf("%[^\n]s", userIn); is a bit weird. The s is guaranteed not to match, since that character will always be \n. Also, you should use a width modifier to avoid a buffer overflow. Use scanf("%29[^\n]", userIn); That alone will not solve the problem, since the next scanf is going to consume the newline. There are a few options. You could consume the newline in the first scanf with:
scanf("%29[^\n]%*c", userIn);
or discard all whitespace in the next call with
scanf(" %c", &findChar);
The behavior will differ on lines of input that exceed 29 characters in length or when the user attempts to assign whitespace to findChar, so which solution you use will depend on how you want to handle those situations.

How to take input until enter is pressed twice?

I want to break this loop when the user press enters twice. Meaning, if the user does not enter a character the second time, but only presses enter again, the loop must break.
char ch;
while(1) {
scanf("%c",&ch);
if(ch=='') { // I don't know what needs to be in this condition
break;
}
}
It is not possible to detect keypresses directly in C, as the standard I/O functions are meant for use in a terminal, instead of responding to the keyboard directly. Instead, you may use a library such as ncurses.
However, sticking to plain C, we can detect newline characters. If we keep track of the last two read characters, we can achieve similar behavior which may be good enough for your use-case:
#include <stdio.h>
int main(void)
{
int currentChar;
int previousChar = '\0';
while ((currentChar = getchar()) != EOF)
{
if (previousChar == '\n' && currentChar == '\n')
{
printf("Two newlines. Exit.\n");
break;
}
if (currentChar != '\n')
printf("Current char: %c\n", currentChar);
previousChar = currentChar;
}
}
Edit: It appears that the goal is not so much to detect two enters, but to have the user:
enter a value followed by a return, or
enter return without entering a value, after which the program should exit.
A more general solution, which can also e.g. read integers, can be constructed as follows:
#include <stdio.h>
#define BUFFER_SIZE 64U
int main(void)
{
char lineBuffer[BUFFER_SIZE];
while (fgets(lineBuffer, BUFFER_SIZE, stdin) != NULL)
{
if (lineBuffer[0] == '\n')
{
printf("Exit.\n");
break;
}
int n;
if (sscanf(lineBuffer, "%d", &n) == 1)
printf("Read integer: %d\n", n);
else
printf("Did not read an integer\n");
}
}
Note that there is now a maximum line length. This is OK for reading a single integer, but may not work for parsing longer input.
Credits: chux - Reinstate Monica for suggesting the use of int types and checking for EOF in the first code snippet.
You can store the previous character and compare it with the current character and enter, like this:
char ch = 'a', prevch = '\n';
while(1){
scanf("%c",&ch);
if((ch=='\n') && (ch == prevch)){// don't know what needs to be in this condition
break;
}
prevch = c;
}
Note that the previous character by default is enter, because we want the program to stop if the user hits enter at the very start as well.
Working like charm now
char ch[10];
while(1){
fgets(ch, sizeof ch, stdin);
if(ch[0]=='\n'){
break;
}
}

How to check if the user input an integer using scanf

I created a program to make a diamond out of *'s. I am looking for a way to check if the type of input is an integer in the C language. If the input is not an integer I would like it to print a message.
This is what I have thus far:
if(scanf("%i", &n) != 1)
printf("must enter integer");
However it does not display the message if it's not an integer. Any help/guidance with this issue would be greatly appreciated!
you can scan your input in a string then check its characters one by one, this example displays result :
0 if it's not digit
1 if it is digit
you can play with it to make your desired output
char n[10];
int i=0;
scanf("%s", n);
while(n[i] != '\0')
{
printf("%d", isdigit(n[i]));
i++;
}
Example:
#include <stdio.h>
#include <string.h>
main()
{
char n[10];
int i=0, flag=1;
scanf("%s", n);
while(n[i] != '\0'){
flag = isdigit(n[i]);
if (!flag) break;
i++;
}
if(flag)
{
i=atoi(n);
printf("%d", i);
}
else
{
printf("it's not integer");
}
}
Use fgets() followed by strtol() or sscanf(..."%d"...).
Robust code needs to handle IO and parsing issues. IMO, these are best done separately.
char buf[50];
fgets(buf, sizeof buf, stdin);
int n;
int end = 0; // use to note end of scanning and catch trailing junk
if (sscanf(buf, "%d %n", &n, &end) != 1 || buf[end] != '\0') {
printf("must enter integer");
}
else {
good_input(n);
}
Note:
strtol() is a better approach, but a few more steps are needed. Example
Additional error checks include testing the result of fgets() and insuring the range of n is reasonable for the code.
Note:
Avoid mixing fgets() and scanf() in the same code.
{ I said scanf() here and not sscanf(). }
Recommend not to use scanf() at all.
strtol
The returned endPtr will point past the last character used in the conversion.
Though this does require using something like fgets to retrieve the input string.
Personal preference is that scanf is for machine generated input not human generated.
Try adding
fflush(stdout);
after the printf. Alternatively, have the printf output a string ending in \n.
Assuming this has been done, the code you've posted actually would display the message if and only if an integer was not entered. You don't need to replace this line with fgets or anything.
If it really seems to be not working as you expect, the problem must be elsewhere. For example, perhaps there are characters left in the buffer from input prior to this line. Please post a complete program that shows the problem, along with the input you gave.
Try:
#include <stdio.h>
#define MAX_LEN 64
int main(void)
{ bool act = true;
char input_string[MAX_LEN]; /* character array to store the string */
int i;
printf("Enter a string:\n");
fgets(input_string,sizeof(input_string),stdin); /* read the string */
/* print the string by printing each element of the array */
for(i=0; input_string[i] != 10; i++) // \0 = 10 = new line feed
{ //the number in each digits can be only 0-9.[ASCII 48-57]
if (input_string[i] >= 48 and input_string[i] <= 57)
continue;
else //must include newline feed
{ act = false; //0
break;
}
}
if (act == false)
printf("\nTHIS IS NOT INTEGER!");
else
printf("\nTHIS IS INTEGER");
return 0;
}
[===>] First we received input using fgets.Then it's will start pulling each digits out from input(starting from digits 0) to check whether it's number 0-9 or not[ASCII 48-57],if it successful looping and non is characters -- boolean variable 'act' still remain true.Thus returning it's integer.

Tokenizing a string

I am in the process of writing a C program that parses a string and tokenizing it by breaking the string characters into words that are seperated by white space. My question is when i run my current program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input[20];
printf("Please enter your word:\n");
scanf("%c", &input);
printf("%c", input[1]);
return 0;
}
If i was to enter the word "This", i would expect to get back "h" when i run the program but instead i get a downwards pointing arrow. However, when the input is set to print out input[0] i get back a "T".
Edit: I have modified my code so that it prints out the whole string now which i will show below
int main()
{
char input[20];
printf("Please enter your words:\n");
scanf("%s", input);
printf("%s", input);
return 0;
}
My goal is to be able to break that string into chars that i can search through to find whitespace and thus being able to isolate those words for example, if my input was "This is bad" i'd like the code to print out
This
is
bad
Edit:
I have modified my code to fit one of these answers but the problem i run into now is that it won't compile
int main()
{
char input[20];
printf("Please enter your words:\n");
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
}
printf("%c", input[]);
return 0;
Problems:
1) scanf("%c", input); only set the first element of the array input.
2) printf("%c", input[1]); prints the second element of the array input, which has uninitialized data in it.
Solution:
Small state machine. No limit on string size like 20.
#include <ctype.h>
#include <stdio.h>
int main() {
int ch = fgetc(stdin);
while (ch != EOF) {
while (isspace(ch)) {
// If only 1 line of input allowed, then add
if (ch == '\n') return 0;;
ch = fgetc(stdin);
}
if (ch != EOF) {
do {
fputc(ch, stdout);
ch = fgetc(stdin);
} while (ch != EOF && !isspace(ch));
fputc('\n', stdout);
}
}
return 0;
}
scanf("%c", &input); does not do what you think it does.
First of all, %c scans only a single character: http://www.cplusplus.com/reference/cstdio/scanf/
Second, array's name is already a pointer to it's first element, so stating &input you make a pointer to a pointer, so instead of storing your character in array's first element you store it in pointer to the array which is a very bad thing.
If you really want to use scanf, I recommend a loop:
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
Using scanf("%s", input") leaves you vulnerable to buffer overflow attacks if the word is longer than 20 characters http://en.wikipedia.org/wiki/Buffer_overflow
In my example I assumed, that you want to finish your word with a newline character.
EDIT: In scanf documentation is also a good example:
scanf("%19s", input);
It scans no more than 19 characters, which also prevent buffer overflow. But if you want to change input size, you have to change it two places.
You can use
char * strtok ( char * str, const char * delimiters );
to tokenize your string. If you have your input in input[] array and want to tokenize the string accoring to whitespace character, you can do the following :
char *ptr;
ptr = strtok(input, " ");
while(ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
Only the first call to strtok() requires the character array as input. Specifying NULL in the next calls means that it will operate on the same character array.
Your scanf only picks up the first character, input[1] contains random garbage. Use scanf("%19s", input) instead.

C - Return the first non-whitespace character

I have been asked to write a function that returns the first non-whitespace character in an inputted string.
It's working when I enter something like "hello" or anything that does not begin with a white space. But when I enter something like " hello", it returns a white space.
Here is my code:
int question6()
{
printf("Start typing stuff in \n");
char myChar = returnFirstNonWhite();
printf("First non-white space character is: %c",myChar);
}
int returnFirstNonWhite()
{
int ch,temp;
ch = getchar();
while (ch != 32)
{
temp = ch;
printf("Found first success %c\n", ch);
}
return temp;
}
ch = getchar();
while (ch == 32)
{
ch = getchar();
}
return ch;
One easy option would be to use scanf() instead of getchar(). scanf() will take a string (so there's no need to loop getting chars) and it will strip off any starting white space, so you just need to grab the first character it has.
int returnFirstNonWhite()
{
char str[50];
memset(str, '\0', 50);
scanf("%s", str);
return str[0];
}
so
>> hello
will return 104 (ascii 'h')
At first you are taking only one character input. And if it is not equal to 32 int value, the program should be in a infinite loop!!!! This is a nothing code.
Everything here appears to be okay, except in your while loop you don't continue to fetch the next character. In other words, it fetches the initial character, let's say a whitespace, and then continues in that while loop forever since the ch variable is never changed.
Try adding ch = getchar(); within your while loop so it continually fetches the next character to check. Also, I just realized you need to check that the character is equal to 32, not not equal so that if the character is a whitespace it continues to fetch the next character.

Resources