Ignoring everything other than integers scanf - c

I would like to take an array of integers as an input . Even if some one enter a space or an alpahabet, I want to ignore it.
int i=0;
while(L--){
scanf("%d",&arr[i++]);
}
But if I enter: 4 wtf the arr[0] gets initialized to 4 and the loop ends. Is there a way I can ignore everything after a space in scanf and just take the integers.
The input can be of form: 4 abc 3 def 7 ghi.

I think like this?
int a;
scanf("%d %*s", &a);
printf("%d\n",a);
And
input: 11 wwwww
output: 11
The * is used to skip an input without putting it in any variable.

Try this
while(L--){
scanf("%d",&arr[i++]);
while(getchar() != '\n'); // Consumes all characters after space.
}

You can use fgets to get the input string from stdin and then use sscanf to filter out integer from input string.
char input[50];
int num;
fgets(input, 50, stdin);
sscanf(input, "%d %*s", &num);
The %*s rejects the string after the integer encountered.

I think that what you'd actually like to achieve here is to extract all numbers from a random input. I propose to use fgets to read the input into a buffer and next, using isdigit and strtol, extract the numbers:
#include <stdio.h>
int main(void)
{
char buff[255] = {0};
fgets(buff, sizeof(buff), stdin); // read data from stdin
char *ptr = buff;
do {
if(!isdigit(*ptr)) // check if current character is a digit
continue; // if not...
long val = strtol(ptr, &ptr, 10); // read a number
printf("%ld\n", val); // print it
} while(*ptr++); // ...move to next character
}
...and the quick test:
[root#dmudms01 temp]# ./a.out
1abc23 **4
1
23
4

Related

How do I request characters from a user, and then print the size of the characters?

I'm very new to C, any help would be greatly appreciated.
I can't use the <string.h> or <ctype.h> libraries.
This is the code I have:
int main(void)
{
char character;
printf("Introduce characters: ");
scanf(" %c", &character);
printf("\nSize of character: %d", sizeof(character)/sizeof(char));
return 0;
}
This only prints 1 as the size.
I read in another post that the problem was that initializing character by char character; would only let me store 1 single character. So, I modified it to be an array:
int main(void)
{
char character[10];
printf("Introduce maximum 10 characters: ");
scanf(" %s", character);
printf("\nSize of character: %d", sizeof(character)/sizeof(char));
return 0;
}
The problem now is that by doing character[10], it prints out that the size is 10. How would I go about fixing this?
sizeof(character)/sizeof(char) gives you the size of the array you declared, not the size of what the user has entered.
sizeof(character) gives the size of the entire array in bytes
sizeof(char) gives the size of a single character in bytes
So, when you do sizeof(character)/sizeof(char), you get the actual size (i.e. number of elements) of your array. What you are trying to achieve can be done with strlen(). But since you can't use <string.h>, you can write it yourself:
int strlen2(char *s)
{
int size;
for (size = 0; s[size]; size++)
;
return size;
}
Then use it like:
#include <stdio.h>
int main(void)
{
char character[10];
printf("Introduce maximum 10 characters: ");
scanf("%s", character);
printf("\nSize of character: %d", strlen2(character));
}
strlen2() counts the number of characters of your string, it stops counting when it encounters the first \0 character (null terminator).
Avoid using scanf() to read input
Your code is prone to bugs. If the user enters a string more than 9 characters long (don't forget the \0 is added at the end of your string), you'll get a buffer overflow, because character is only supposed to contain 10 characters. You would want to limit the number of characters read into your string:
scanf("%9s", character); // Read only the first 9 characters and ignore the rest
Moreover, scanf() is used to parse input, not to actually read it. Use fgets() instead:
#include <stdio.h>
#include <string.h> // for strcspn()
int main(void)
{
char character[10];
printf("Introduce maximum 10 characters: ");
if(!fgets(character, 10, stdin)) {
fprintf(stderr, "Error reading input.\n");
return 1;
}
character[strcspn(character, "\n")] = '\0'; // fgets() reads also `\n` so make sure to null-terminate the string
printf("\nSize of character: %zu", strlen(character));
}
fgets() accepts three arguments:
The first one is the array in which you want to store user input
The second one is the size of your array
The third one is the file stream you want to read from
It returns NULL on failure so you should check that as well.
Well if you can't use any headers, maybe you can create a custom strlen() function.
strlen() pretty much counts all character until the '\0' character is found. '\0' is used to signify the end of string and is automatically appended by scanf("%s",...).
#include <stdio.h>
size_t ms_length(const char *s)
{
size_t i = 0;
for (; s[i] != '\0'; i++)
;
return i;
}
int main(void)
{
char *str = "hello";
printf("%zu\n", ms_length(str));
return 0;
}
And if you want to be pedantic, you might even want to check the return value of scanf(), for input errors and also apply a limit to the character to be read to avoid a buffer overflow.
if (scanf(" %9s", character) != 1) /* 9 characters + 1 reserved for \0 */
{
/* handle error */
return 1;
}

Return Value of sscanf

I was reading about sscanf and i came across this:
Return Value
Each of these functions [including s_sscanf()] returns the number of fields that are successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. The return value is EOF for an error or if the end of the string is reached before the first conversion.
I am doing error checking for my input file and i wanna make sure i get a valid line so i tried using sscanf but how do i make sure there are no more fields in the line than i expect. So if i have 3 values in a line but i only need two then that is an invalid line for me but when i use sscanf i only read in 2 variables and the rest are ignored. How do i check the entire line making sure there is no garbage in the line but im not sure what to expect so its not like i can add another variable cause the user can input anything. Someone mentioned to me that you can use * in your sscanf function but im not really sure how i haven't been able to find it anywhere where it is being implemented in code.
The scanf() family of functions returns the number of successful assignments made. If code is expecting three input items there is no way to tell from the value returned by sscanf() alone whether three or more input items were provided.
The scanf() functions operate by reading a character, attempting to match that character, making an assignment if applicable, then moving to the next character or returning from the function call. There is a conversion specifier, %n, that stores the number of characters read in this process so far (without incrementing the number of characters read). This conversion specifier can be used to determine if the input has been exhausted by the call to sscanf().
The code below provides a demonstration. Lines of input gathered by fgets() contain a newline, unless the input is too large to fit in the buffer array. Here buffer[] is large enough to store reasonably-sized inputs, but more robust code would handle oversized inputs more carefully. When sscanf() scans the input string, each character is read in turn until a failing match occurs or the end of the string is reached, so the number of read characters expected after matching "%d %d %d %n" is the same as the length of the input string, including any trailing whitespace characters.
#include <stdio.h>
#include <string.h>
#define BUF_SZ 1024
int main(void)
{
char buffer[BUF_SZ];
int x, y, z;
int pos;
printf("Enter three integers: ");
fflush(stdout);
// get user input
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
// first check: does input match 3 integers?
if (sscanf(buffer, "%d %d %d %n", &x, &y, &z, &pos) != 3) {
puts("Incorrectly formatted input");
} else {
// second check: did sscanf() finish at the end of the buffer?
int expected = strlen(buffer);
if (pos != expected) {
puts("Extra input in buffer");
printf("expected = %d, pos = %d\n", expected, pos);
} else {
// everything OK
printf("You entered: %d, %d, %d\n", x, y, z);
}
}
}
return 0;
}
Sample interactions:
>$ ./a.out
Enter three integers: 1 2 3
You entered: 1, 2, 3
>$ ./a.out
Enter three integers: 1 2
Incorrectly formatted input
>$ ./a.out
Enter three integers: 1 2 3 4
Extra input in buffer
expected = 8, pos = 6
If it is desired to disallow even trailing whitespace characters, "%d %d %d%n" can be used instead. Note that in order for this to work, the newline character must be removed from buffer[] so that it is not counted as extra input. One typical way to do this is by using buffer[strcspn(buffer, "\r\n")] = '\0':
int main(void)
{
char buffer[BUF_SZ];
int x, y, z;
int pos;
printf("Enter three integers: ");
fflush(stdout);
// get user input
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
// first check: does input match 3 integers?
if (sscanf(buffer, "%d %d %d%n", &x, &y, &z, &pos) != 3) {
puts("Incorrectly formatted input");
} else {
// remove trailing newline character
buffer[strcspn(buffer, "\r\n")] = '\0';
// second check: did sscanf() finish at the end of the buffer?
int expected = strlen(buffer);
if (pos != expected) {
puts("Extra input in buffer");
printf("expected = %d, pos = %d\n", expected, pos);
} else {
// everything OK
printf("You entered: %d, %d, %d\n", x, y, z);
}
}
}
return 0;
}
You may, first of all, give the conversion specifiers for the values that you are sure must be present, and then add an "assignment-allocation modifier" to capture any remaining input. I am not sure whether you are talking about sscanf, fscanf or scanf; I will just use scanf to illustrate.
The following program reads 2 integers, and places any remaining input in a string variable, the size of which is dynamically allocated:
Update: Using sscanf instead of scanf.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
int a,b;
char *s;
int n;
char src[]="1 2 This is the remainder";
n=sscanf(src,"%d %d %m[^\n]",&a,&b,&s);
if(n>2)
printf("s=%s\n", s), free(s);
return 0;
}
$ ./a.out
s=This is the remainder

fgets() doesn't work as expected in C

Given the following code:
#include <stdio.h>
int main()
{
int testcase;
char arr[30];
int f,F,m;
scanf("%d",&testcase);
while(testcase--)
{
printf("Enter the string\n");
fgets(arr,20,stdin);
printf("Enter a character\n");
F=getchar();
while((f=getchar())!=EOF && f!='\n')
;
putchar(F);
printf("\n");
printf("Enter a number\n");
scanf("%d",&m);
}
return 0;
}
I want a user to enter a string, a character and a number until the testcase becomes zero.
My doubts / questions:
1.User is unable to enter a string. It seems fgets is not working. Why?
2.If i use scanf instead of fgets,then getchar is not working properly, i.e whatever character I input in it just putchar as a new line. Why?
Thanks for the help.
Mixing functions like fgets(), scanf(), and getchar() is error-prone. The scanf() function usually leaves a \n character behind in the input stream, while fgets() usually does not, meaning that the next call to an I/O function may or may not need to cope with what the previous call has left in the input stream.
A better solution is to use one style of I/O function for all user input. fgets() used in conjunction with sscanf() works well for this. Return values from functions should be checked, and fgets() returns a null pointer in the event of an error; sscanf() returns the number of successful assignments made, which can be used to validate that input is as expected.
Here is a modified version of the posted code. fgets() stores input in a generously allocated buffer; note that this function stores input up to and including the \n character if there is enough room. If the input string is not expected to contain spaces, sscanf() can be used to extract the string, leaving no need to worry about the newline character; similarly, using sscanf() to extract character or numeric input relieves code of the burden of further handling of the \n.
#include <stdio.h>
int main(void)
{
int testcase;
char arr[30];
char F;
int m;
char buffer[1000];
do {
puts("Enter number of test cases:");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
} while (sscanf(buffer, "%d", &testcase) != 1 || testcase < 0);
while(testcase--)
{
puts("Enter the string");
/* if string should not contain spaces... */
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
sscanf(buffer, "%29s", arr);
printf("You entered: %s\n", arr);
putchar('\n');
puts("Enter a character");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
sscanf(buffer, "%c", &F);
printf("You entered: %c\n", F);
putchar('\n');
do {
puts("Enter a number");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
} while (sscanf(buffer, "%d", &m) != 1);
printf("You entered: %d\n", m);
putchar('\n');
}
return 0;
}
On the other hand, if the input string may contain spaces, fgets() can read input directly into arr, but then the stored string will contain a \n character, which should probably be removed. One way of doing this is to use the strcspn() function to find the index of the \n:
#include <string.h> // for strcspn()
/* ... */
puts("Enter the string");
/* or, if string may contain spaces */
if (fgets(arr, sizeof arr, stdin) == NULL) {
/* handle error */
}
/* replace newline */
arr[strcspn(arr, "\r\n")] = '\0';
printf("You entered: %s\n", arr);
putchar('\n');
/* ... */
Note that a maximum width should always be specified when using %s with the scanf() functions to avoid buffer overflow. Here, it is %29s when reading into arr, since arr can hold 30 chars, and space must be reserved for the null terminator (\0). Return values from sscanf() are checked to see if user input is invalid, in which case the input is asked for again. If the number of test cases is less than 0, input must be entered again.
Finally got the solution how can we use scanf and fgets together safely.
#include <stdio.h>
int main()
{
int testcase,f,F,m;
char arr[30];
scanf("%d",&testcase);
while((f=getchar())!=EOF && f!='\n')
;
while(testcase--)
{
printf("Enter the string\n");
fgets(arr,30,stdin);
printf("Enter a character\n");
F=getchar();
while((f=getchar())!=EOF && f!='\n')
;
putchar(F);
printf("\n");
printf("Enter a number\n");
scanf("%d",&m);
while((f=getchar())!=EOF && f!='\n')
;
}
}
We need to make sure that before fgets read anything,flushout the buffer with simple while loop.
Thanks to all for the help.
A simple hack is to write a function to interpret the newline character. Call clear() after each scanf's
void clear (void){
int c = 0;
while ((c = getchar()) != '\n' && c != EOF);
}
Refer to this question for further explaination: C: Multiple scanf's, when I enter in a value for one scanf it skips the second scanf

Entering more characters skips prompts

well I have a buffer of I'm assuming 10 characters. I notice when I enter 9 characters though it will skip prompt EX.
Enter a p value:
123456789
Enter a q value:
Enter a k value:
But if I put in 8 or less it will accept it normally as the program is intended, even if the user inputs letters or special characters.
My code:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <ctype.h>
int main()
{
char pbuffer[10], qbuffer[10], kbuffer[10];
int p=0, q=0, k=0;
int r, i, Q, c, count, sum;
char a[3];
a[0]='y';
while(a[0]=='y' || a[0]=='Y')
{
printf("Enter a p value: \n");
fgets(pbuffer, sizeof(pbuffer), stdin);
p = strtol(pbuffer, (char **)NULL, 10);
printf("Enter a q value: \n");
fgets(qbuffer, sizeof(qbuffer), stdin);
q = strtol(qbuffer, (char **)NULL, 10);
printf("Enter a k value: \n");
fgets(kbuffer, sizeof(kbuffer), stdin);
k = strtol(kbuffer, (char **)NULL, 10);
while(p<q+1)
{
Q=p;
sum=0;
count=0;
while(Q>0)
{
count++;
r = Q%10;
sum = sum + pow(r,k);
Q = Q/10;
}
if ( p == sum && i>1 && count==k )
{
printf("%d\n",p);
}
p++;
a[0]='z';
}
while((a[0]!='y') && (a[0]!='Y') && (a[0]!='n') && (a[0]!='N'))
{
printf("Would you like to run again? (y/n) ");
fgets(a, sizeof(a), stdin);
}
}
return 0;
}
fgets will read in as many characters as it can until it hits either a newline, EOF, or the size of the buffer. It also saves one extra character for a string-terminating \0. So, if you type in 123456789\n and have a 10-character buffer, fgets knows that it can only fit 9 characters in that buffer, so it reads in the first 9 and appends a NULL, giving you 123456789\0 in your buffer, and \n still in STDIN. Then, you call fgets a second time. It doesn't wait for input, because there is already a \n in STDIN, so it reads up to that \n, which happens to be only one character. So, your second buffer is now \n\0, and STDIN is now empty.
Either make your buffers large enough to store the strings that you're going to input, or flush STDIN after every fgets. Likely something like:
while((c = getchar()) != '\n' && c != EOF)
/* Ignore the character */ ;
Add this line after the fgets
scanf("\n");
Instead of reading into a char buffer first, you could use scanf(), e.g. scanf("%d", &p) could replace both fgets() and strtol().
Actually fgets retains the \n character when the size argument provided to it is less than the characters entered. In your case you provided value 10 as size to fgets.
so When you enter 9 characters, it fills the buffer with them and waits for an enter from you to stop reading. And when you press the enter it just puts the null character in the end of it and forward the enter to next prompt and hence skipping it.
check the examples in the answer to a question https://stackoverflow.com/a/11180652/1386897.
Flush the stdin after to the calls to fgets using
int c;
while((c = getchar()) != '\n' && c != EOF);
The reason why fgets dosen't wait for the user to enter data is because fgets knows that the buffer is full (9 chars and one space for \0) and appends a \0 in the end of the string and leaves the \n in the stdin which is taken by the next fgets

How to prevent users from inputting letters or numbers?

I have a simple problem;
Here is the code :
#include<stdio.h>
main(){
int input;
printf("Choose a numeric value");
scanf("%d",&input);
}
I want the user to only enter numbers ...
So it has to be something like this :
#include<stdio.h>
main(){
int input;
printf("Choose a numeric value");
do{
scanf("%d",&input);
}while(input!= 'something');
}
My problem is that I dont know what to replace in 'something' ... How can I prevent users from inputting alphabetic characters ?
EDIT
I just got something interesting :
#include<stdio.h>
main(){
int input;
printf("Choose a numeric value");
do{
scanf("%d",&input);
}while(input!= 'int');
}
Adding 'int' will keep looping as long as I enter numbers, I tried 'char' but that didnt work .. surely there is something for alphabets right ? :S
Please reply !
Thanks for your help !
The strtol library function will convert a string representation of a number to its equivalent integer value, and will also set a pointer to the first character that does not match a valid number.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
...
int value;
char buffer[SOME_SIZE];
char *chk;
do
{
printf("Enter a number: ");
fflush(stdout);
if (fgets(buffer, sizeof buffer, stdin) != NULL)
{
value = (int) strtol(buffer, &chk, 10); /* assume decimal format */
}
} while (!isspace(*chk) && *chk != 0);
If chk points to something other than whitespace or a string terminator (0), then the string was not a valid integer constant. For floating-point input, use strtod.
You can't prevent the user from entering anything he wants -- you can only ignore anything s/he enters that you don't "like".
A typical pattern is to read a string with fgets, then scan through the string and check that all the input was digits with isdigit. If it was all digits, then convert to an integer; otherwise, throw it away and get the input again.
Alternatively, use strtol to do the conversion. It sets a pointer to the end of the data it could convert to a number; in this case you (apparently) want it to point to the end of the string.
If you don't mind some non-portable code, you can read one character at a time, and throw away anything but digits (e.g. with getch on Windows).
You should not use scanf to read in numbers - see http://www.gidnetwork.com/b-63.html
Use fgets instead.
However, if you must use scanf, you can do this:
#include <stdio.h>
int main() {
char text[20];
fputs("enter some number: ", stdout);
fflush(stdout);
if ( fgets(text, sizeof text, stdin) ) {
int number;
if ( sscanf(text, "%d", &number) == 1 ) {
printf("number = %d\n", number);
}
}
return 0;
}
Personally, I would read the input into a buffer and scan that string for my number.
char buffer[100];
float value;
do {
scanf("%s", buffer);
} while ( sscanf(buffer,"%f", &value) != 1 )
This will loop until the first thing the user enters on the line is a number. The input could be anything but will only get past this block when the first thing entered is a number.
example input:
43289 (value is 43289)
43.33 (value is 43.44)
392gifah (value is 392)
ajfgds432 (continues to loop)

Resources