how to prevent the user from entering symbols and letters in [duplicate] - arrays

This question already has answers here:
Validate the type of input in a do-while loop
(5 answers)
How to check if input is an integer in C?
(2 answers)
Closed 3 months ago.
I'm trying to prevent the user from entering a wrong value(letters and symbols) in this C program but I did not find any information on this and I have no idea how to do it in my code please help me I will be very grateful
#include <stdio.h>
void main ()
{
int number[30];
int i, j, a, n;
printf("Enter the value of N\n");
scanf("%d", &n);
printf("Enter the numbers \n");
for (i = 0; i < n; ++i)
scanf("%d", &number[i]);
// sorting begins
for (i = 0; i < n; ++i)
{
for (j = i + 1; j < n; ++j)
{
if (number[i] < number[j])
{
a = number[i];
number[i] = number[j];
number[j] = a;
}
}
}
printf("The numbers arranged in descending order are given below\n");
for (i = 0; i < n; ++i)
{
printf("%d\n", number[i]);
}
}

You can't stop a user from entering invalid input, but what you can do is try to validate it.
From the man page:
RETURN VALUE:
On success, these functions return the number of input items successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.
if((scanf("%d", &n) != 1)
{
... print error message here
exit(EXIT_FAILURE);
}
Note: Scanf would happily match and assign the value to n if the input was a floating point number, by discarding the mantissa.
A number followed by some alphabets would also be accepted, and the trailing junk would be left in the input buffer for subsequence input calls to deal with.
A better option would be to read a whole line with fgets, and parse it with sscanf, strtol etc.
You can refer to their man pages for help.

Related

While reading two array in c through scanf, the second one somehow modify the first [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I have the following problem reading two strings through scanf: I insert the first string and everything it's OK, but after I insert the second one the first one changes.
#include<stdio.h>
#define N 6
#define K 2
int main(){
char a[N];
char b[K];
int i = 0,j=0;
printf("first word\n\n\n");
scanf("%s", a);
for(i = 0; i <= N; i++){
printf("%c", a[i]);
}
printf("second word \n\n\n");
scanf("%s", b);
for(i = 0; i <= N; i++){
printf("%c", a[i]);
}
}
The first time it prints it correctly. The second time it prints a similar string (maybe the first scanf is still getting the input when I'm inserting the second one)
To begin, you are printing the array a twice; it seems that you mean to print b with the second loop. But there is a problem in your loops. They are going out of array bounds. Since arrays are zero-indexed in C, you need:
for (i = 0; i < N; i++) {}
for a, and:
for (i = 0;i < K; i++) {}
for b.
But even this is not quite right, since the input strings may not entirely fill the arrays. You really need to terminate the loop when the null-terminator is reached, or when the end of the array has been reached:
for (i = 0; a[i] != '\0' && i < N; i++) {}
and:
for (i = 0; b[i] != '\0' && i < K; i++) {}
Of course, it would be simpler to just use puts() to print the strings.
It seems that the inputs (abcabc and abc) were too large for the arrays, causing buffer overflow. This can be avoided by specifying maximum widths when using the %s conversion specifier with scanf().
Here is a modified version of the posted code. I increased the sizes of N and K by one, since it appears that space for null-terminators was not considered in the original code:
#include <stdio.h>
#define N 7
#define K 3
int main(void)
{
char a[N];
char b[K];
int i = 0;
printf("first word\n\n\n");
scanf("%6s", a);
for (i = 0; a[i] != '\0' && i < N; i++) {
printf("%c", a[i]);
}
putchar('\n');
printf("second word \n\n\n");
scanf("%2s", b);
for (i = 0; b[i] != '\0' && i < K; i++) {
printf("%c", b[i]);
}
putchar('\n');
return 0;
}
You are printing a twice, change the second printf("%c", a[i]); to printf("%c", b[i]); .
The problem you are experiencing is because you invoke undefined behavior by failing to insure the strings are nul-terminated and by using incorrect limits regarding b. For instance, you
#define N 6
#define K 2
...
char a[N], b[K];
a can hold a total of 5-chars + the nul-terminator, for a total of 6-chars. b on the other hand, can only hold 1-char + the nul-terminator for a total of 2-chars.
When you then subsequently loop of both a and b with for(i = 0; i <= N; i++), not only have you guaranteed to access an element outside the bounds of the array, e.g. a[6] (valid indexes are 0-5), you have also invoked undefined behavior for any a with less that 6 total characters by attempting to read from an uninitialized value (those uninitialized array elements after the last valid char in word of say, 3-chars) When you invoke Undefined Behavior, the execution of your code is unreliable from that moment forward.
In your case you can eliminate undefined behavior by using field width modifiers to limit the number of characters placed in the arrays by scanf itself, e.g.
if (scanf ("%5s", a) != 1) {
fprintf (stderr, "error: invalid input - a.\n");
return 1;
}
You validate the return of scanf to insure the proper number of conversions have taken place, or you handle the error if they have not.
You prevent reading beyond the bounds of the array by limiting your read and output char loop to only valid characters within the array. You do that by checking the character to be printed is not the nul-terminating character, and when the nul-terminating character is reached, you exit the loop without attempting to print it.
Putting those pieces together, you could do something similar to the following (note j is unused in your code so it is commented out):
#include <stdio.h>
#define N 6
#define K 2
int main (void ) {
char a[N], b[K];
int i = 0/*, j = 0*/;
printf ("enter first word: ");
if (scanf ("%5s", a) != 1) {
fprintf (stderr, "error: invalid input - a.\n");
return 1;
}
for (i = 0; a[i] && i < N; i++)
printf ("%c", a[i]);
putchar ('\n');
printf ("enter second word: ");
if (scanf ("%1s", b) != 1) {
fprintf (stderr, "error: invalid input - b.\n");
return 1;
}
for (i = 0; b[i] && i < N; i++)
printf ("%c", b[i]);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/twowords
enter first word: cats
cats
enter second word: dogs
d
I would strongly caution you to consider reading line-oriented input with a line-oriented input function like fgets. This eliminates many pitfalls for new programmers. The only additional step when using fgets is to recall it reads up-to-and-including the trailing '\n', so you need to trim the '\n' from the string read.
Look things over an let me know if you have further questions.
For the second printf you have to write
printf("%c", b[i]);
As per inputs(abcabc and abc ) you mentioned your are providing to scanf are causing overflow for both the variables a and b,
You should enter string of length 5 for first and 1 for second keeping space for \0 for both the strings
Edit: Also change loop condition from i <= N to i<N or i<sizeof(a).
Please note the loop will print garbage characters past string length if the length of string happens to be less than 5
I see two things that you can do here:
Use another big buffer array that you will load data to, and that copy data to specyfic array. Than you will get max 6 letters of first word in a[], and max 2 letters of second word in b[]. But you will be able to load 2 words.
Scanf specyfic amount of chars like #xing mentiond in comment.
scanf("%6s",word) //general use, not in OP's case
Than when you've got longer word than size that you set up, you will have the rest of input as input in second word.

Alphabetizing a list in C, extra input [duplicate]

This question already has answers here:
scanf issue when reading double
(2 answers)
Closed 5 years ago.
sorry for the remedial question. Been troubleshooting to try and find the error and I have come up empty.
I need to write a program that alphabetizes a list of inputs. The first input is the integer value of the number of inputs. Each input ends with a new line character.
int main()
{
int word_total;
char word_in[100][30], t[30];
int i, j;
printf("\nPlease the number of words you wish to sort: \n");
scanf("%d", &word_total);
printf("\nPlease enter a single word at a time. After each word, press return.\n");
for (i = 0; i < (word_total); i++)
{
scanf("%s\n", word_in[i]);
}
for (i = 1; i < (word_total); i++)
{
for (j = 1; j < (word_total); j++)
{
if (strcmp(word_in[j - 1], word_in[j]) > 0)
{
strcpy(t, word_in[j - 1]);
strcpy(word_in[j - 1], word_in[j]);
strcpy(word_in[j], t);
}
}
}
printf("\nSorted list:\n");
for (i = 0; i < (word_total); i++)
{
printf("%s\n", word_in[i]);
}
printf("\n");
}
The problem: the input of words takes word_total + 1. For instance, if word_total = 5, I have to input 6 words. The last word that is input is ignored and not included in the "Sorted list". I can fix the problem by:
for (i = 0; i < (word_total - 1); i++)
{
scanf("%s\n", word_in[i]);
}
but then the "Sorted list" is short one word. I've tried changing "<" to "<=", etc, but haven't found a fix.
Thank you for your help!
The problem seems to be
scanf("%s\n", word_in[i]);
which, due to the "\n", will attempt to read more whitespace following the string (until it finds another non-whitespace; note that any whitespace character actually means any number of whitespace characters; the \n does not match just a single newline as you apparently expect). You should remove the "\n" from the scanf format and eat the newline with a getchar() or similar.
PS: not testing the return value from scanf() is asking for trouble.

array goes above limit when taking user input

I am taking a couple of numbers as input from the user, storing them into a file and then reading from that file, sorting the numbers and displaying them to the user. The program works except for 1 issue. When taking input from the user it asks for an extra elememnt than the specifies limit. This extra element doesn't get stored anywhere. I have tried reducing the limit value by one but that results in loss of 1 element(i.e. 1 element becomes 0). I understand that this may be a very newbie issue but I coudn't find any direct answer to this issue. I wrote the program in Visual Studio 2010 as a C program. here's the code:
#include <stdio.h>
int arr[50];
int n;
int writefile()
{
FILE *ptr;
ptr = fopen("Sort.txt","w");
if(ptr==NULL)
{
printf("No such file exists\n");
fclose(ptr);
return 0;
}
else
{
int i;
printf("Enter number of elements in array\n");
scanf("%d", &n);
printf("Enter %d elements\n", n);
for(i=0; i<n; i++) //The issue is here
{
scanf("%d\n",&arr[i]); //say the user enter n=3, then after adding 1,2,3 it will ask for another 4th element but only 1,2,3 will get stored.
}
fwrite(arr, sizeof(int), n, ptr);
fclose(ptr);
printf("done\n");
}
}
void sortarr(int arr1[]);
int readfile()
{
FILE *ptr;
ptr = fopen("Sort.txt","r");
if(ptr==NULL)
{
printf("No such file exists\n");
fclose(ptr);
return 0;
}
else
{
int i;
int arrb[50];
fread(arrb, sizeof(int), n, ptr);
printf("Before sorting data\n");
for(i=0; i<n; i++)
{
printf("%d",arrb[i]);
}
printf("\n");
sortarr(arrb);
printf("After Sorting data\n");
for(i=0; i<n; i++)
{
printf("%d",arrb[i]);
}
printf("\n");
}
}
void sortarr(int arr1[])
{
int i,j,temp;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (arr1[i] > arr1[j]) {
temp = arr1[i];
arr1[i] = arr1[j];
arr1[j] = temp;
}
}
}
}
int main()
{
writefile();
readfile();
return 0;
}
scanf("%d\n",&arr[i]);
Should be:
scanf("%d",&arr[i]);
If you ask it to ignore white space after the number, it will have to keep reading until it reads some non-whitespace in order for it to ensure it has ignored all the whitespace. You definitely don't want scanf to try to ignore whitespace after it has read the number, you want it to terminate.
The %d format specifier already ignores whitespace before the number.
Let's just narrow this down to the following code:
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%d\n", &arr[i]);
}
Notice the difference in the scanf calls? The first call doesn't have a \n in its format string. The second call does.
Remove the \n from the scanf format string (in the second call). Things should work more like you're expecting then.
An online manual page for scanf says:
The format string consists of a sequence of directives which describe how to process the sequence of input characters... A directive is one of the following: A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
So the looped over scanf (with the extra \n in it) was effectively reading the number, the newline, the next number, then realizing it's read all of the white space it could. scanf then returned with the first number assigned to your array entry and the next number ready for the next call to reading from standard input. This left things effectively offset appearing like you saw and requiring the extra number before ending (in order that it could detect that the white space had ended).

C program to find the number of elements in an array after inserting and without counting while inserting

Looking for a C program to count the number of elements in an integer array after inserting and without counting while inserting.Alternatively, what is the integer array substitution for strlen() ?
In this program I need to determine the value of c:
#include <stdio.h>
int main()
{
int a[300],mx=0,c=0,i=0,j;
for(i=0;i<=300;i++)
{
scanf("%d",&a[i]);
if(a[i]=='q') break;
}
c=??;
for(j=0;j<=c;j++)
{
printf("%d\n",a[j]);
if(a[j]>mx) mx=a[j];
}
printf("Max=%d\n",mx);
return 0;
}
From Your input seems that once you get q(113D) input you stop accepting any more input from user.
So need to iterate through array until you found q to get array length.
for(c=0;a[c] != 113;c++)
{
//do nothing
}
//Now you can use c as array length
I guess there is no alternative way like strlen() for what you are doing.
for(i = 0; i < 300; ++i)
{
scanf("%d", &a[i]); /* TODO: check if return value != 1 -> input error */
if (a[i] == 'q')
break;
}
for(j = 0; j < 300 && a[j] != 'q'; ++j)
{
printf("%d\n", a[j]);
if (a[j] > mx)
mx = a[j];
}
As vagish noted, having the input be terminated by 'q' in the way you attempt is pretty strange. The input "113" will map to the ASCII value of 'q', so that input value can't be processed by your program. Furthermore, if somebody actually tried to enter "q" to end the input, I believe the scanf would fail, return 0 and leave a[i] uninitialized, which is definitely not what you want.
You probably want your input to be terminated by EOF instead (ctrl-D if you are typing it into a terminal on most platforms) and you want to check the return code of your call to scanf for input errors and EOF.
I found the answer of my question. Smart vertion of the above program:
include
int main()
{
double a[100000],mx=0;
int i,j,c=0;
printf("Enter as many numbers as you wish . Press Ctrl+D or any character to stop inputting :\n");
for(i=0;i<100000;i++)
{
if((scanf("%lf",&a[i]))==1)
c++;
//else break;
}
for(j=0;j<c;j++)
{
if(a[j]>mx) mx=a[j];
}
printf("You have inserted %d values and the maximum is:%g",c,mx);
return 0;
}

Get the unknown length of number from input [duplicate]

This question already has answers here:
how to scanf unknown amount of integer numbers into array in C?
(3 answers)
Closed 6 years ago.
I am doing a assignment which requires the input of a list of numbers and get the output when I press Enter on the keyboard. This is the code I am trying the use to get the list of numbers when I enter, but it doesn't work:
#include <stdio.h>
int main(){
int arra[100];
int i ;
int j = -1;
while (scanf("%d",&i) != 1){
arra[++j] = i;
}
printf("\n");
int k;
for(k = 0; k < j; k++){
printf("%d",arra[k]);
}
return 0;
}
I want to print the elements of arra.
First off, massive kudos for testing the return value from scanf, most people just blindly assume it works. It's just a shame you're using it in the wrong way :-)
You want the loop to continue as long as the return value is 1, meaning that you managed to scan an integer. That means it should be:
while (scanf ("%d", &i) == 1) {
That also means that any non-numeric input will cause scan failure and hence the while loop will exit. So, if you enter:
3 1 4 1 5 9 stop
you should successfully see the numeric values from the array.
The only other thing is to clean up your j handling since the k loop will stop early. This can be done with:
for (k = 0; k <= j; k++) {
Alternatively, leave that loop alone and just change how you initialise and modify j:
int j = 0;
:
arra[j++] = i;
I tend to find the second choice more C-like since j is then a count of the elements in the array rather than the maximum index.
And, of course, you're open to a buffer overflow attack at the moment since you assume nobody will enter more than a hundred numbers. So, don't use this as a homework solution (what you have is good enough with the slight bug fixes) but I'd tend to write it as something like:
#include<stdio.h>
#define SZ 100
int main (void){
int arra[SZ], i, nxt = 0;
while ((nxt < SZ) && (scanf ("%d", &(arra[nxt])) == 1))
nxt++;
printf ("\n");
for (i = 0; i < nxt; i++)
printf ("%d ", arra[i]);
return 0;
}
Check the below code:
#include<stdio.h>
int main(){
int arra [100];
int i ;
int k;
int j = 0; /* index from 0 */
printf("Keep entering numbers and press q once done \n");
while (scanf("%d",&i) == 1){ /* scan for integers */
arra[j++] = i;
}
printf("\n");
for(k = 0; k < j; k++){
printf("%d",arra[k]);
}
return 0;
}

Resources