How do I sort my data? - c

I am new to programming so this is difficult for me. I need the program to end if the user's first input is -999, if not then they go on to input the account_num, last_name, and balance. But if the user enters -999 after the first input then it ends their input and displays the results. I cannot figure out how to get this whole -999 part to work while making my client[x].account_num be sorted in ascending order.. My code is below.
#include <stdio.h>
void bubble_sort(int[], int);
struct information
{
int account_num;
char last_name[30];
float balance;
};
int main()
{
/* declare variables */
struct information client[5];
int i, x, temp;
char c;
/* Prompt user */
printf ("Enter account number, last name, and balance.\n");
printf ("Enter -999 to end input:\n\n");
/* prompt user to enter number of people */
x = 0;
while (client[x].account_num != -999)
{
int tmp;
scanf ("%i", &tmp);
/* if types -999 as their first input program ends */
if (tmp == -999)
{
break;
}
else if (tmp < 1 || tmp > 1000)
{
printf ("*** Invalid account number. Please enter 1 - 1000 or -999 to exit ***\n");
}
else
{
client[x].account_num = tmp;
x ++;
}
bubble_sort(client[x].account_num, i);
scanf("%s", client[x].last_name);
while ( (c = getchar() != '\n') && c != EOF); /* clear input buffer. */
scanf("%.2f", &client[x].balance);
}
for (x = 0; x < 5; x++)
printf("%i\n", &client[x].account_num);
return 0;
}
void bubble_sort(int list[], int i)
{
int e, d, t;
for (e = 0; e < (i - 1); e++)
{
for (d = 0; d < i - e - 1; d++)
{
if (list[d] > list[d + 1])
{
/* swapping */
t = list[d];
list[d] = list[d + 1];
list[d + 1] = t;
}/* end for*/
}/*end for*/
}/* end for */
}/* end function */

There are several issues here. First, you don't want to index account_num and balance in the struct, unless you want to have several account numbers and balances per account holder. I also suggest replacing the for with a while loop so you don't have to fiddle with the loop counter x in case the user enters an invalid account number. Finally, for the sake of clarity I introduced a temporary variable tmpfor input and performed all tests on it, assigning the content to the account structure only if all validity tests were passed. tmpis only needed inside the whileloop which is why I declared it there, instead of making it part of the declarations in main().
#include <stdio.h>
#define MAX_CLIENTS 5
#define MAX_ACCOUNTS 1000
struct information
{
int account_num;
char last_name[30];
float balance;
};
int main()
{
/* declare variables */
struct information client[MAX_CLIENTS];
int i, x, people;
char c;
/* Prompt user */
printf ("Enter account number, last name, and balance.\n");
printf ("Enter -999 to end input:\n\n");
/* prompt user to enter number of people */
x = 0;
while (x < MAX_CLIENTS)
{
int tmp;
scanf ("%i", &tmp);
/* if types -999 as their first input program ends */
if (tmp == -999)
{
break;
}
else if (tmp < 1 || tmp > MAX_ACCOUNTS)
{
printf ("*** Invalid account number. Please enter 1 - %d or -999 to exit ***\n", MAX_ACCOUNTS);
}
else
{
client[x].account_num = tmp;
x ++;
}
}
return 0;
}

Related

Input number resets to 0 after scanf

I have a weird issue. I ask a user to enter a number between 1 and 15. Then I would ask the user would the like to get the factorial value of the number using either recursive or a for loop.
When they answer that question the inputted value goes to 0. If I remove the question for testing purpose the value stays the value the user inputted.
#include <stdio.h>
int recursive(int);
int nonRecursive(int);
int main()
{
/* Variables */
int numberSelected, returnedValue;
char answer;
do
{
/* Request a number between 1 and 15 */
printf("Please enter a number between 1 and 15: ");
scanf("%d", &numberSelected);
printf("%d\n", numberSelected); /* This prints out the user's number */
}while(numberSelected < 1 || numberSelected > 15); /* Loops if the value is not between 1 and 15 */
/* Ask user if they want to return a recursive value or a value calculated manually */
printf("Would you like a recusive value of the number you entered? Y or N: ");
scanf("%s", &answer);
if(answer == 'y' || answer == 'Y')
{
printf("%d\n", numberSelected); /* Here it resets to 0 */
returnedValue = recursive(numberSelected); /* Returns the recursive value */
printf("The recursive value of %d is %d\n", numberSelected, returnedValue);
}
else
{
printf("%d\n", numberSelected); /* Here it resets to 0 also*/
returnedValue = nonRecursive(numberSelected); /* Returns the value from for loop */
printf("The non recursive value of %d is %d\n", numberSelected, returnedValue);
}
return 0;
}
/* Get value using recursive */
int recursive(int n)
{
if (n == 0)
return 1; // Base case
else
return n * recursive(n - 1);
}
/* Get value using for loop */
int nonRecursive(int n)
{
int i;
int fact = 1;
for(i = 1; i <= n; i++)
{
fact *= i;
}
return fact;
}
Thank you for the help
scanf("%s", &answer);
is wrong. %s is for reading strings (null-terminated sequence of characters), but answer has only room for 1 character, so out-of-bound write will occur when strings with one or more characters is read. It may break data around that.
The line should be
scanf(" %c", &answer);
Use %c, which reads single character.
Add a space before %c to have scanf() ignore whitespace characters.

For loop being skipped after bubble sort function

I am making a sorting program for a final assignment. It takes the account number, last name, and balance of the account and sorts it in ascending order based on the account number. The issue I am having with my program is that once it gets to the for loop to output the information, it completely skips it. I believe it might have to do with my bubble sort function, but I am not sure how to fix it. We haven't been taught quick sort, so I am not using it. I am receiving an error: incompatible type for argument 1 of `sort', but I cannot change the array to type struct without it causing more issues. Here is my code:
#include <stdio.h>
/* Define structure */
struct account
{
int number;
char full_name[30];
float balance;
};
/* Function prototype */
void sort (int[], int);
/* Begin main function */
int main()
{
/* Declare variables */
struct account person[5];
int x=0, i=0, count=0;
printf("Enter account number, last name, and balance.\n");
printf("Enter -999 to end input:\n\n");
/* Create loop for user information */
while(1)
{
scanf("%i", &person[x].number);
if(person[x].number == -999) /*Break when -999 is input */
{
count = x;
break;
}
if(person[x].number < 1 || person[x].number >1000)
{
printf("***Invalid account number. Please enter 1 - 1000 or -999 to exit***\n");
x--;
continue;
}
scanf("%s", person[x].full_name);
scanf("%f", &person[x].balance);
if(person[x].balance < 0)
{
printf("*** Invalid balance amount. Please enter a positive value. ***\n");
x--;
continue;
}
}/* End of while loop */
/* Call to sort function to sort information */
sort(person[x].number, count);
/* Display the information in ascending order */
printf("ACCOUNT\tLAST NAME\tBALANCE\n");
/* Create for loop to output the sorted information */
for(x=0; x < count; x++)
{
printf("%d\t%s\t%f\n",person[x].number,person[x].full_name,person[x].balance);
} /* End of for loop */
}/* End of main */
/* Start sort function */
void sort(int p[], int count)
{
/* Declare variables.*/
char changed = 'T'; /* a "flag" to indicate if a swap was made.*/
int x, temp;
while (changed == 'T')
{
changed = 'F';
/* Create for loop for swaping information */
for (x = 0; x < count-1; x++)
{
if ( p[x] > p[x + 1])
{
/* Swap needs to be made.*/
temp = p[x];
p[x] = p[x+1];
p[x+1] = temp;
/* Set flag indicating that a swap was made. This ensures that */
/* processing will continue, until nothing needs to be swapped. */
changed = 'T';
}
} /* end for loop */
} /* end while loop*/
} /* end function sort */
Here is my output:
Enter account number, last name, and balance.
Enter -999 to end input:
10 Happy 55.00
15 Day 60.00
35 Man 75.00
-999
ACCOUNT LAST NAME BALANCE
Press any key to continue . . .
I appreciate your assistance and the time you are taking to help!
first as mentioned in comments add x++ at the end of your while-loop to scan data.
also you should know that by sending one member of struct (number) to your sort function , and sorting it , other members won't be sorted (only another number will be replaced with theirs).
also note here sort(person[x].number, count); you are sending one element of member number from struct to function . while in declaration of function ,you said you will send an array of integer to it.
this should be sort(person, count); and in function deceleration you should
use sort(struct account p[],int count); also you have to change function by using p[x].number.
also note that to add x++ at the end of your while-loop , you have to remove those continue , otherwise when you do x-- you won't reach x++.
I wrote another sort function which I think is more logical.
struct account
{
int number;
char full_name[30];
float balance;
};
void sort(struct account p[], int count);
int main()
{
struct account person[5];
int x = 0, i = 0, count = 0;
printf("Enter account number, last name, and balance.\n");
printf("Enter -999 to end input:\n\n");
while (1)
{
scanf("%i", &person[x].number);
if (person[x].number == -999)
{
count = x;
break;
}
if (person[x].number < 1 || person[x].number >1000)
{
printf("***Invalid account number. Please enter 1 - 1000 or -999 to exit***\n");
x--;
//remove continue
}
scanf("%s", person[x].full_name);
scanf("%f", &person[x].balance);
if (person[x].balance < 0)
{
printf("*** Invalid balance amount. Please enter a positive value. ***\n");
x--;
//remove continue
}
x++;//add x++
}
sort(person, count);//new function sort
printf("ACCOUNT\tLAST NAME\tBALANCE\n");
for (x = 0; x < count; x++)
{
printf("%d\t%s\t%f\n", person[x].number, person[x].full_name, person[x].balance);
}
}
void sort(struct account p[], int count)
{
char changed = 'T';
int x, temp;
float btemp;
char ntemp[30];// btemp for balance and ntemp for full_name
while (changed == 'T')
{
changed = 'F';
for (x = 0; x < count - 1; x++)
{
if (p[x].number > p[x + 1].number)
{
temp = p[x].number;
p[x].number = p[x + 1].number;
p[x + 1].number = temp;
btemp = p[x].balance;
p[x].balance = p[x + 1].balance;
p[x + 1].balance = btemp;
strcpy(ntemp , p[x].full_name);
strcpy(p[x].full_name , p[x + 1].full_name);
strcpy(p[x + 1].full_name , ntemp);
changed = 'T';
}
}
}
}

C Basics : Grade Book Using Array Storing and Printing, Plus Looping

Yes, hello. I'm really new to programming. I genuinely need help because I would like to both understand what I'm doing wrong and also pass my class.
I'm in a Intro to Programming class and my assignment is to create a program that uses an array to store percentage grades in the range from 0 to 100 (inclusive). The program should allow the user to indicate when they are done entering grades. When the user is done entering grades, the program should print out the grades entered.
I have a running code, compiled in Code::Blocks. But my questions/problems are:
A.) What's the best way to tell C when the user is done? Should I
Leave the code as is and let any key be hit?
Add a specific variable like 'done'?
Do something else?
B.) How do I print only the grades that have been entered without it going through all 100 slots? I can't for the life of me find the solution.
Any and all suggestions welcome and appreciated!!!
int i = 0;
float percentScore[100];
for (i = 0; i < 10; i++) {
printf("Grade %d: ", i + 1);
scanf("%f", &percentScore[i]);
}
for (i = 0; i < 10; i++) {
printf("\n%.2f%%", percentScore[i]);
}
return 0;
Your choices for A) are not mutually exclusive; the first is something the user can do, the second is a way to represent that in the code. As such, you could reasonably do both.
As for B), you need a way to represent the number of grades entered (hint: a variable); this can then be used to control how many get printed.
Here is a simple approach for your problem:
for each input, read a full line from the user ;
try and convert this line as a number with sscanf() ;
if the conversion fails, consider the input exhausted ;
if the value is out of bounds, restart this input.
The user can thus signal the end of the list by entering a blank line.
Here is a example:
#include <stdio.h>
#define GRADE_NB 100
int main(void) {
int i, n;
float grade, percentScore[GRADE_NB];
char buf[100];
for (n = 0; n < GRADE_NB;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
return 0;
}
If the potential number of inputs is not limited, you must allocate the array from the heap and reallocate it as more inputs are gathered. Here is a simple solution for this where the array is reallocated for each input:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, n;
float grade, *percentScore;
char buf[100];
for (n = 0, percentScore = NULL;;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore = realloc(percentScore, (n + 1) * sizeof(*percentScore));
if (percentScore == NULL) {
printf("allocation failed\n");
return 1;
}
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
free(percentScore);
return 0;
}

int differs in level of indirection from char[2] error

The code is from Absolute beginner's guide to C, and I get this error ./BlackJack.c<41> : warning C4047: '==' : 'int' differes in levels of indirection from 'char [2]' when I try to compile it in Visual Studio. This is the main function of a Blackjack game.
Line <41> is if (ans == "H") {
main()
{
int numCards; /* Equals 52 at the beginneing */
int cards[52], playerPoints[2], dealerPoints[2], total[2];
/* For user Hit/Stand or Yes/No response */
do { initCardsScreen(cards, playerPoints, dealerPoints, total, &numCards);
dealerGetsCard(&numCards, cards, dealerPoints);
printf("\n");
playerGetsCard(&numCards, cards, playerPoints);
playerGetsCard(&numCards, cards, playerPoints);
do {
ans = getAns("Hit or stand (H/S)? ");
if (ans == "H") {
platerGetsCard(&numCards, cards, playerPoints);
}
}
while ( ans != 'S');
totalIt(playerPoints, total, PLAYER);
/* Player's total */
do {
dealerGetsCard(&numCards, cards, dealerPoints);
} while (dealerPoints[ACEHIGH] < 17);
/* 17: Dealer stop */
totalIt(dealerPoints, total, DEALER);
/* Dealer's total */
findWinner(total);
ans = getAns("\nPlay again (Y/N)? ");
} while (ans == 'Y');
return;
}
(Update): Here is the entire code.
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>
#define BELL '\a'
#define DEALER 0
#define PLAYER 1
#define ACELOW 0
#define ACEHIGH 1
int askedForName = 0;
/****************************
This program specific prototype
****************************/
void dispTitle(void);
void initCardsScreen(int cards[52], int playerPoints[2], int dealerPoints[2], int total[2], int * numCards);
int dealCard(int * numCards, int cards[52]);
void dispCard(int cardDrawn, int points[2]);
void totalIt(int points[2], int total[2], int who);
void dealerGetsCard(int *numCards, int cards[52], int dealerPoints[2]);
void playerGetsCard(int *numCards, int cards[52], int playerPoints[2]);
char getAns(char mesg[]);
char ans;
void findWinner(int total[2]);
main()
{
int numCards; /* Equals 52 at the beginneing */
int cards[52], playerPoints[2], dealerPoints[2], total[2]; /* For user Hit/Stand or Yes/No response */
do { initCardsScreen(cards, playerPoints, dealerPoints, total, &numCards);
dealerGetsCard(&numCards, cards, dealerPoints);
printf("\n");
playerGetsCard(&numCards, cards, playerPoints);
playerGetsCard(&numCards, cards, playerPoints);
do {
char ans = getAns("Hit or stand (H/S)? ");
if (ans == "H") {
playerGetsCard(&numCards, cards, playerPoints);
}
}
while ( ans != 'S');
totalIt(playerPoints, total, PLAYER);
/* Player's total */
do {
dealerGetsCard(&numCards, cards, dealerPoints);
} while (dealerPoints[ACEHIGH] < 17);
/* 17: Dealer stop */
totalIt(dealerPoints, total, DEALER);
/* Dealer's total */
findWinner(total);
ans = getAns("\nPlay again (Y/N)? ");
} while (ans == 'Y');
return;
}
void initCardsScreen(int cards[52], int playerPoints[2], int dealerPoints[2], int total[2], int *numCards)
{
int sub, val=1; /* This function's Work variables */
char firstName[15]; /* Holds user's first name */
*numCards = 52; /* Holds running total of number of cards */
for (sub = 0; sub <= 51; sub++) { /* Counts from 0 to 51 */
val = (val == 14) ? 1 : val; /* If val is 14 reset to 1 */
cards[sub] = val;
val++; }
for (sub = 0; sub <= 1; sub++) { /* Counts from 0 to 1 */
playerPoints[sub] = dealerPoints[sub] = total[sub]=0; }
dispTitle();
if (askedForName ==0) { /* Name asked for nly once */
printf("\nWhat is your first name? ");
scanf_s(" %s", firstName);
askedForName = 1; /* Don't ask prompt again */
printf("Ok, %s, get ready for casino action!\n\n", firstName);
getchar(); /* Discards newline. You can safely */
} /* ignore compiler warning here. */
return;
}
/*** This function gets a card for the player and updates the player's points. ***/
void playerGetsCard(int *numCards, int cards[52], int playerPoints[2])
{
int newCard;
newCard = dealCard(numCards, cards);
printf("You draw: ");
dispCard(newCard, playerPoints);
}
/*** This function gets a card for the dealer and updates the dealer's poimts. ***/
void dealerGetsCard(int *numCards, int cards[52], int dealerPoints[2])
{
int newCard;
newCard = dealCard(numCards, cards);
printf("The dealer draws: ");
dispCard(newCard, dealerPoints);
}
/*** This function gets a card from the deck and stores it in either the dealer's or the player's hold of cards ***/
int dealCard(int * numCards, int cards[52])
{
int cardDrawn, subDraw;
time_t t; /* Gets time for a random value */
srand((unsigned int)(time(&t))); /* Seeds random-number generator */
subDraw = (rand() % (*numCards)); /* From 0 to numcards */
cardDrawn = cards[subDraw];
cards[subDraw] = cards[*numCards -1]; /* Puts top card */
(*numCards); /* in place of drawn one */
return cardDrawn;
}
/*** Displays the last drawn card and updates points with it. ***/
void dispCard(int cardDrawn, int points[2])
{
switch (cardDrawn) {
case(11) : printf("%s\n", "Jack");
points[ACELOW] += 10;
points[ACEHIGH] += 10;
break;
case(12) : printf("%s\n", "Queen");
points[ACELOW] += 10;
points[ACEHIGH] += 10;
break;
case(13) : printf("%s\n", "King");
points[ACELOW] += 10;
points[ACEHIGH] += 10;
break;
default : points[ACELOW] += cardDrawn;
if (cardDrawn == 1)
{
printf("%s\n", "Ace");
points[ACEHIGH] += 11;
}
else
{
points[ACEHIGH] += cardDrawn;
printf("%d\n", cardDrawn);
}
} return;
}
/*** Figure the total for player or dealer to see who won. This function takes into account the fact that Ace is either 1 or 11. ***/
void totalIt(int points[2], int total[2], int who)
{
/* The following routine first looks to see if the total points counting Aces as 1 is equal to the total points couning Aces as 11. If so,
or if the total points counting Aces as 11 is more than 21, the program uses the total with Aces as 1 only */
if ((points[ACELOW] == points[ACEHIGH]) || (points[ACEHIGH] > 21)) {
total[who] = points[ACELOW]; /* Keeps all Aces as 1 */
}
else {
total[who] = points[ACEHIGH]; /* Keeps all Aces as 11 */
}
if (who == PLAYER) /* Determines the message printed */ {
printf("You have a total of %d\n\n", total[PLAYER]);
}
else {
printf("The house stands with a total of %d\n\n", total[DEALER]);
}
return;
}
/*** Prints the winning player. ***/
void findWinner(int total[2])
{
if (total[DEALER] == 21) {
printf("The house wins.\n");
return;
}
if ((total[DEALER] > 21) && (total[PLAYER] > 21)) {
printf("%s", "Nobody wins.\n");
return;
}
if ((total[DEALER] >= total[PLAYER]) && (total[DEALER] < 21)) {
printf("The house wins.\n");
return;
}
if ((total[PLAYER] > 21) && (total[DEALER] < 21)) {
printf("The house wins.\n");
return;
}
printf("%s%c", "You win!\n", BELL);
return;
}
/*** Gets the user's uppercase, single-character response. ***/
char getAns(char mesg[])
{
char ans;
printf("%s", mesg); /* Prints the prompt message passed */
ans = getchar();
getchar(); /* Discards newline. You can safely ignore compiler warning here. */
return toupper(ans);
}
/*** Clears everything off the screen. ***/
void dispTitle(void)
{
int i=0;
while (i < 25) { /* Clears screen by printing 25 blank lines to 'push off' stuff that
might be left over on the screen before this program */
printf("\n");
i++;
}
printf("\n\n*Step right up to the Blackjack tables*\n\n");
return;
}
Notice how all of your other comparisons have single quotes?
while (ans == 'Y')
There, you're comparing a single character (which is a number, and thus comparable to another number).
In the code that's failing, on the other hand, you're using double quotes.
ans == "H"
So you're comparing to a string, which is an array of chars. The array is two characters long to accommodate the null terminator.
"H" (in double quotes) is a string, not a character. To get a character constant containing the letter H, you need 'H' (in single quotes.) So, your line should read if( ans == 'H' ).
What will also work is if( ans == "H"[0] ). This will compare ans against the first (zero-th) character of the string "H".
I agree that this is an insanely cryptic message for a simple type mismatch error. Blame it on C and C compilers. (May I suggest that you use some more modern language like C# or Java?)
The compiler reports your ans as an int while you may have declared it as a char. (I do not know how you have declared it, because you seem to have omitted its declaration from the source code that you posted.) If that is happening, it is because the compiler implicitly converts the char to int while trying to compare it with something else.
The compiler also reports your "H" as a char[2], and it might not be immediately obvious why: C uses null-terminated strings, so the literal "H" is represented as a 2-character array, where the first character is 'H' and the second character is the null character. ('\0').
And then the compiler mumbles something about different levels of indirection instead of telling you that the types you are trying to compare are incompatible. That's because in trying to perform the comparison the compiler considers "H" not as an array of characters, but as a pointer to the first character of the array, but that still does not help, because what it ends up with is a pointer to a character, (one level of indirection,) while it needs a character. (Zero levels of indirection.)

A basic/ manual way to check that a value entered by the user is numeric

I've searched in and out of these forums but am still having trouble. My understanding of C is still very basic. I'm creating a small program that takes 3 numerical values entered by the user and then calculates the highest. I nailed that.
I now want to ensure that the user enters only integer values. I managed to get the prog to keep prompting the user to re-enter the value until it is within the specified numerical range (for example, any number between 1 and 1000 inclusive, piece of cake) but that's not good enough. I used 3 while loops to test each value, but this only works as long as the input is of type integer.
The trick is I cant use built in functions. It needs to be manual (sorry, poor choice of words) I tried to use char variables and x = getchar(); to get the ASCII value and test it in a condition but I can't get it working in a loop. (while/ do-while)
I also tried using a "for loop" and array variables but once again am struggling to get it to keep prompting the user.
I've also tried to test the value returned by scanf to see if its integer but my knowledge level of correct C syntax is level: noob. Either my loops don't loop or they loop infinitely.
Here is some sample code:
int x, y, z =0;
printf("Enter the first number:\n");
scanf("d", &x);
while (condition) /* Here is where I need to determine that the entered val is false */
{
printf("Wrong input. Re-enter a valid value.\n");
x =0;
scanf("%d", &x); /*user re-prompted */
}
I'm getting the idea that I'll have to use ASCII and a loop, but I just can't get to it. Also, the values entered get sent to a function for comparing and are then returned.
Could someone give me some advice and a few tips please?
Much thanks
You would have to use something like fgets, and strtol:
long someValue;
char *bufEnd = NULL;
char buf[128]; // max line size
do {
printf("enter a value: ");
fgets(buf, 128, stdin);
someValue = strtol(buf, &bufEnd, 10); // base 10
} while (bufEnd == buf || *bufEnd != '\n');
printf("got value: %li", someValue);
What we are doing here is we are tapping into strtol's capability to tell us where it stopped parsing, by passing in bufEnd.
Then, we are making sure that bufEnd doesn't point to the beginning of buf (in which case, it didn't start with a number), and also checking to make sure that bufEnd points to \n, or the end of the line (making sure that the user didn't enter something like 123abc, which strtol would interpret as 123). You may wish to trim buf of whitespace characters first, however.
You're absolutely on the right track with "scanf()". Just check the return value. If you don't get the expected #/values, then you got invalid input:
char found = FALSE;
int ival;
double x;
while (!found)
{
printf("Please enter a valid integer: ");
if (scanf("%d", &ival) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
printf("Please enter a valid floating point number: ");
if (scanf("%lf", &x) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
found = TRUE;
}
Here's my solution. It safe against buffer overflow and straightforward .
#include <stdio.h>
#define LEN 10
int main() {
int a;
char str[LEN];
fgets( str, LEN, stdin );
while ( !sscanf( str, "%d", &a ) )
fgets( str, 10, stdin );
printf("Num is : %d\n", a);
return 0;
}
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
int getInteger(int* err){
int ch;
int n;//int32
int takeNum, sign;
long long int wk;//long long int as int64
wk=0LL;
*err = 0;
takeNum = 0;//flag
sign = 1;//minus:-1, other:1
/* //skip space character
while(EOF!=(ch=getchar()) && (ch == ' ' || ch == '\t' || ch == '\n'));
ungetc(ch, stdin);
*/
while(EOF!=(ch=getchar())){
if(ch == '-'){
if(takeNum != 0){//in input number
*err = 1;
break;
}
if(sign == -1){//already sign
*err = 2;
break;
}
sign = -1;
continue;
}
if(ch >= '0' && ch <= '9'){//isdigit(ch) in ctype.h
if(takeNum == 0)
takeNum = 1;
wk = wk * 10 + (ch - '0')*sign;
if(INT_MAX < wk || INT_MIN > wk){//overflow
*err = 3;
break;
}
continue;
}
if(ch != '\n'){//input other [-0-9]
*err = 4;
}
break;
}
if(takeNum == 0){//not input number
*err = 5;
} else {
n=wk;
}
while(ch != '\n' && EOF!=(ch=getchar()));//skip to newline
return n;
}
int getValue(const char* redoprompt, int low, int high){
int num, err=0;
while(1){
num = getInteger(&err);
if(err || low > num || high < num)
printf("%s", redoprompt);
else
break;
}
return num;
}
#define max(x,y) ((x)>(y))? (x) : (y)
int main(){
const char *error_message = "Wrong input. Re-enter a valid value.\n";
int x, y, z, max;
x = getValue(error_message, 1, 1000);
y = getValue(error_message, 1, 1000);
z = getValue(error_message, 1, 1000);
max = max(max(x,y), z);
printf("max:%d\n", max);
return 0;
}

Resources