loop not working in my c code - c

Below is my c code and the forever for(;;) loop is not breaking out base on the condition i have given it using an if statement. Is there something am doing wrong? my codes are as below:
#include <stdio.h>
main()
{
/*
* Program starts
*/
int tracks; /* tracks is declared as a variable for the number of tracks */
float price; /* Price is declared as variable for number of tracks */
char title[100]; /* title is declared as a varibel for the title of thr CD*/
char album_single[2]; /* album_single is a variable declared for either the CD is a single or an album */
char artiste[50];
printf("Welcome to the CD database\n\n");
printf("Please enter the details of the CD below...\n");
/*
* First, title
*/
printf("Title? ");
scanf("%[^\n]", title);
/*
* Next, Artiste
*/
printf("Artiste? ");
fflush(stdin);
scanf("%[^\n]", artiste);
/*
* Next, number of tracks
*/
printf("Number of Tracks? ");
fflush(stdin);
scanf("%d",&tracks);
/*
* Next, Type(album or single)
*/
for(; ;)
{
printf("ALbum or a single (Enter 'a' for an album and 's' for a single): ");
fflush(stdin);
scanf("%c", &album_single);
if(album_single == "a" || album_single == "s")
break;
printf("Error!\n");
}
/*
* Conditions to assign the right type(album/single) to the variable album_single
*/
if(strcmp(album_single, "a") == 0)
{
strcpy(album_single,"Album");
}
else
{
if(strcmp(album_single, "s") == 0)
strcpy(album_single, "single");
}
/*
* Finally, Price
*/
printf("Retail Price(e.g $4.66)? ");
fflush(stdin);
scanf("%f", &price);
/*
* Details, finallly output
*/
printf("\n\nDetails of %s's CD\n", title);
printf("========================\n");
printf("Title: %s\n",title);
printf("Artiste: %s\n", artiste);
printf("Number of tracks: %d\n",tracks);
printf("Album/Single: %s\n", album_single);
printf("Price:$ %.2f\n", price);
printf("========================\n");
/*
* User Friendly exit of the program
*/
printf("\n Press ENTER to exit the program.");
/*
* Program end
*/
fflush(stdin);
getchar();
}
Below is the part of the forever for(;;) loop which is not breaking out:
for(; ;)
{
printf("ALbum or a single (Enter 'a' for an album and 's' for a single): ");
fflush(stdin);
scanf("%c", &album_single);
if(album_single == "a" || album_single == "s")
break;
printf("Error!\n");
}
This loop keep on looping even if the input is 'a' or 's'. what am i doing wrong in this codes ?

Try this:
char album_single;
while (album_single != 'a' && album_single != 's')
{
printf("Album or a single (Enter 'a' for an album and 's' for a single): ");
scanf("%c", &album_single);
scanf("%c"); // discard carriage return
}
Experiment commenting out the last scanf() statement, see what happens.

this code solved the question using the strcmp() function in the comparison instead of the ==.
correct code
if(strcmp(album_single, "a") == 0 || strcmp(album_single, "s") == 0 )
wrong code
if(album_single == "a" || album_single == "s")
thanks for ur contribution guys .!!

You can not compare strings using == operator. Either declare album_single as a character, or use strcmp() function.
if(strcmp(album_single, "a")==0||strcmp(album_single, "s")==0) break;
Remember to include the correct header file.

Related

Switch case inside loop (for or while) in C [duplicate]

I'm trying to input a character into a linked list, where the character can be 'A','a','G','g','T','t','C' or 'c'.
I'm not yet familiar with C and I know I've screwed something up here:
do{
printf ("\nEnter a new nucleotide: \n");
scanf("%c",&newChar);
/* Checking */
if(newChar == 'A' ||
newChar == 'a' ||
newChar == 'G' ||
newChar == 'g' ||
newChar == 'T' ||
newChar == 't' ||
newChar == 'C' ||
newChar == 'c' )
{
AddToSequence(newChar);
size++;
} else {
printf ("\nBad Element");
}
}while(newChar != 'x');
newChar is initialized with a junk value, in this case 'q'.
Entering 'x' exits the loop, entering any acceptable value calls AddToSequence(), and any unacceptable value gets a warning.
For some reason, no matter what value is in newChar, it will jump to the else. It will also jump straight past the scanf without waiting for entry from the user and do two loops every time it loops. Can anyone tell me where I'm going wrong?
Full program:
#include<stdio.h>
#include<stdlib.h>
/*Structure declaration for the node*/
struct node{
char nucleotide;
struct node *point;
}*start;
/* Adds a nucleotide to the chain. Creates a new linked list if no chain exists exists.*/
void AddToSequence(char nucleotide){
struct node *loc, *first;
//Dynamic memory is been allocated for a node
first=(struct node*)malloc(sizeof(struct node));
first->nucleotide=nucleotide;
first->point=NULL;
if(start==NULL){
/*If list is empty*/
start=first;
}else{
/*Element inserted at the end*/
loc=start;
while(loc->point!=NULL){
loc=loc->point;
loc->point=first;
}
}
}
/* Display elements */
void Display(){
struct node *loc;
if(start == NULL){
printf ("\n\nList is empty");
return;
}
loc=start;
printf("\n\nList is : ");
while(loc!=NULL){
printf ("%c", loc->nucleotide);
loc=loc->point;
}
printf ("\n");
}
/* Finds and displays percentage of the chain made up of each nucleotide. */
void Percentage(int size){
struct node *loc;
if(start == NULL){
printf ("\n\nList is empty");
return;
}
loc=start;
printf("\n\nList is : ");
int A = 0, G =0, T =0, C = 0;
double Adouble = 0, Gdouble =0, Tdouble=0, Cdouble=0;
while(loc!=NULL){
if(loc->nucleotide=='A' || 'a'){A++;}
if(loc->nucleotide=='G' || 'g'){G++;}
if(loc->nucleotide=='T' || 't'){T++;}
if(loc->nucleotide=='C' || 'c'){C++;}
loc=loc->point;
}
printf ("\n");
/* Convert to double for percentages as int loses precision */
Adouble =A;
Gdouble =G;
Tdouble =T;
Cdouble =C;
Adouble =(Adouble/size)*100;
Gdouble =(Gdouble/size)*100;
Tdouble =(Tdouble/size)*100;
Cdouble =(Cdouble/size)*100;
printf("\nA: %f", Adouble);
printf("\nG: %f", Gdouble);
printf("\nT: %f", Tdouble);
printf("\nC: %f", Cdouble);
}
/* There be dragons beyond here */
int main(){
int navigate, size =0;
char newChar = 'q';
do{ /* Menu */
printf("\n 1. Create / Extend Sequence\n");
printf("\n 2. Display Sequence\n");
printf("\n 3. Count \n");
printf("\n 0. Exit \n");
printf("\nPlease select an option (0 to 3)\n");
scanf("%d",&navigate);
switch (navigate){
case 0: /* Exit */
break;
case 1: /* Add nucleotides */
do{
printf ("\nEnter a new nucleotide: \n");
scanf("%c",&newChar);
/* Some error checking */
if(newChar == 'A' || newChar == 'a' || newChar == 'G' || newChar == 'g' || newChar == 'T' || newChar == 't' || newChar == 'C' || newChar == 'c' ){
AddToSequence(newChar);
size++;
} else {
printf ("\nBad Element");
}
}while(newChar != 'x');
break;
case 2:
Display();
break;
case 3:
Percentage(size);
break;
default:
printf ("\n\nBad choice. Please select another.\n");
}
} while (navigate !=0);
return 0 ;
}
You don't handle the newline. The %c specifier doesn't skip blanks. Try:
scanf(" %c", &newChar);
/* ^ <-- Makes `scanf` eat the newline. */
Or maybe add an explicit test.
scanf(...);
if (newChar == '\n')
continue;
add space to "%c" to catch the newline character. the space charcter is used to catch space characters, tabulations, newline
scanf("%c ",&newChar);
You're leaving the '\n' on stdin:
scanf("%d",&navigate);
getchar(); // consume the newline character
...
scanf("%c",&newChar);
getchar(); // consume the newline character
Or since you're already using scanf() you can tell scanf itself to take care of the newline character:
scanf("%d\n", &navigate);
....
scanf("%c\n",&newChar);
Even better you can leave it open by adding a space after the format specificer:
scanf("%d ", &navigate);
....
scanf("%c ",&newChar);
Just in case the user wants to do something like: 2<tab key><enter key>
Regardless of how you handle it, the point is you need to consume the newline character.
Use
newChar=getche();
This is a nonstandard function that gets a character from the keyboard, echoes to screen.

Making a for loop that edits a list in a data structure

The code that I'm trying to write is supposed to take given data by the user and put it into a data structure, which works perfectly. What is going wrong is when I try to remove a entry( if(choice == 2). All it has to do is take that entry and make it empty but I didn't like the idea of empty space. The for loop that I tried to make was to take the top entry and move everything down one but what it does is take the first entry and copy it to the second, leaving the others alone. Any help on how to take the data and just delete the entry to move them down one would be great.
#include <stdio.h>
#include <string.h>
typedef struct book { //This is the data structure
char personName[15];
char personLname[15];
char phoneNumber[15];
char null[4];
} Book;
static int loopValue;// this is going to loop the program forever until the
//loop is broke
main()
{
int index = 0;
int choice;
Book *ptrBook = (Book*)malloc(sizeof(Book));
int i,j;
int stopValue = 1;
while(stopValue=0)
{
printf("\t\tPhone Book Application\n");
printf("\t1. Add Contact\t\t2. Remove Contact\n");
printf("\t3. Show Contacts\t10. Exit\n");
printf("\tChoice: ");
scanf("%i",&choice);
printf("\n\n");
if(choice == 1) // this is the add person, it takes the print if
/and puts it into the data structure
{
ptrBook = (Book*)realloc(ptrBook, sizeof(Book)*(index + 1));
printf("What is the FIRST name: ");
scanf("%s",ptrBook[index].personName);
printf("What is the LAST name: ");
scanf("%s",ptrBook[index].personLname);
printf("What is the number: ");
scanf("%s",ptrBook[index].phoneNumber);
printf("\nAdded to the Phone Book.\n");
printf("\nName: %s %s\n",ptrBook[index].personName,
ptrBook[index].personLname);
printf("Phone Number: %s",ptrBook[index].phoneNumber);
index++;
}
else if (choice == 2) // this removes people from the data
//structure
{
loopValue == 0;
printf("Who would you like to remove?\n\n");
for(i=0;i<index;i++) // this loops prints out the names to
//choose from
{
printf("%i. %s %s\n",i+1,ptrBook[i].personName,ptrBook[i].personLname);
}
printf("Who would you like to remove? ");
scanf("%i",choice);
for(i=choice;i<0;i--) //THIS IS WHAT NEED HELP WITH PLZ
{ //
strcpy(ptrBook[i-2].personName,ptrBook[i-1].personName); //
strcpy(ptrBook[i-2].personLname,ptrBook[i-1].personLname); //
strcpy(ptrBook[i-2].phoneNumber,ptrBook[i-1].phoneNumber); //
} `//
printf("\n");
scanf("%i",&choice);
}
if(choice == 3) // this loops to print out all the values in the
//data structure
{
for(i=0;i<index;i++)
{
printf("%s %s\n",ptrBook[i].personName,ptrBook[i].personLname);
printf("%i. %s\n\n\n",index,ptrBook[i].phoneNumber);
}
}
else if(choice == 4)
{
//make code to sort names
}
else if(choice == 5)
{
//find a phone number for a given name
}
else if(choice == 6)
{
//random person for you to call
}
else if(choice== 7)
{
//delete everyone
}
else if(choice == 8) // this exits the program by changing the
//loop variable to something that makes the loop false
{
printf("Exiting");
stopValue = 0;
}
}
}
Your code has a LOT of issues. In the future, please make sure to clean up your code really thoroughly before posting a question. I've taken the time to clean up a lot of it because I hate myself, so I hope you appreciate. First, a bug list:
1 and 2) Your condition in the while loop is actually an assignment: please turn on warnings on your compiler, because they will catch stuff like this. It's also erroneous with your initalization of stopValue.
3) The loopValue is used inconsistently throughout the code, and is not the thing that controls your while loop.
4) Inside if (choice == 2), loopValue == 0 means compare it to 0, not set it to 0. That has no effect on your program, but you've made the =, == error twice now. That's really basic stuff that you absolutely have to get a grip on.
5) In the same if section, your scanf where you set choice didn't have & in front of choice, meaning the variable wouldn't actually be set to the value typed in.
6) Same section, the last printf and scanf are probably not meant to be there? In any case they bring the input to an unintuitive halt, which would render the program useless to anyone who didn't have the source code.
7) The if (choice == 3) wasn't an else if.
8) The quit option is 8 in the source code, but the menu says it's 10.
After all that, here's the code (with a lot of stuff that didn't have anything to do with the problem you were having taken out)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct book { //This is the data structure
char personName[15];
char personLname[15];
char phoneNumber[15];
char null[4];
} Book;
static int loopValue;
int main(void) {
int index = 0;
int choice;
Book *ptrBook = (Book*) malloc(sizeof(Book));
int i, j;
int stopValue = 0; // was 1
while (stopValue == 0) { // was =
printf("\t\tPhone Book Application\n");
printf("\t1. Add Contact\t\t2. Remove Contact\n");
printf("\t3. Show Contacts\t8. Exit\n");
printf("\tChoice: ");
scanf("%i", &choice);
printf("\n\n");
if (choice == 1) {
ptrBook = (Book*) realloc(ptrBook, sizeof(Book)*(index + 1));
printf("What is the FIRST name: ");
scanf("%s",ptrBook[index].personName);
printf("What is the LAST name: ");
scanf("%s",ptrBook[index].personLname);
printf("What is the number: ");
scanf("%s",ptrBook[index].phoneNumber);
printf("\nAdded to the Phone Book.\n");
printf("\nName: %s %s\n",ptrBook[index].personName,
ptrBook[index].personLname);
printf("Phone Number: %s",ptrBook[index].phoneNumber);
index++;
} else if (choice == 2) {
loopValue = 0; // was ==
printf("Who would you like to remove?\n\n");
for (i = 0; i < index; i++) {
printf("%i. %s %s\n", i+1, ptrBook[i].personName, ptrBook[i].personLname);
}
printf("Who would you like to remove? ");
scanf("%d", &choice); // didn't have &
for (int i = (choice - 1); i < (index - 1); i++) {
ptrBook[i] = ptrBook[i + 1];
}
index--;
// used to be redundant/confusing/wrong printf and scanf
} else if (choice == 3) { // used to not be else if
for (i = 0; i<index; i++) {
printf("%s %s\n", ptrBook[i].personName, ptrBook[i].personLname);
printf("%i. %s\n\n\n", index, ptrBook[i].phoneNumber);
}
} else if (choice == 8) { // Should've been 10
printf("Exiting");
stopValue = 1;
}
}
}
There are so many little problems with your code that it is hard to know where to begin. Probably the most glaring is the failure to validate the the return of scanf and your failure to empty stdin of any extraneous characters after each input leaving your program just waiting to enter an endless-loop on the first errant keystroke. You cannot use the "%s" conversion specifier to read names (many are two-part names) and you will stop reading at the first whitespace and the remainder of the name will be taken as the next input. The same applies to reading a phone number (which would trigger an endless loop if a whitespace and punctuation is included).
Which brings up a larger recommendation of using fgets instead of scanf for all line-oriented input (such as taking user input). You can use sscanf to parse integer values from the input and you avoid a whole host of pitfalls inherent in new C programmers taking input with scanf. Don't skimp on buffer size. For example #define MAXC 1024 and then char buf[MAXC]; would be adequate for most user input.
Next, when doing a menu, consider using switch () { case 1: ...; break; case 2: ...; break } instead of the long chain of if (...) {...} else if (...) {...}, etc.... It provides more readable code;
There are many, many more corrections made to your code which are explained in the comments inline below, e.g.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NULLSZ 4 /* if you need a constant #define one (or more) */
#define MAXNMNUM 15
typedef struct book {
char personName[MAXNMNUM]; /* use constants for array sizes */
char personLname[MAXNMNUM];
char phoneNumber[MAXNMNUM];
char null[NULLSZ]; /* no clue what this is for */
} Book;
/* helper function to empty extraneous characters from stdin */
void empty_stdin (void)
{
int c = getchar();
while (c != EOF && c != '\n')
c = getchar();
}
int main (void) /* See http://port70.net/~nsz/c/c11/n1570.html#5.1.2.2.1p1 */
{
int index = 0;
Book *ptrBook = malloc (sizeof *ptrBook); /* do NOT cast malloc return */
for (;;) { /* loop continually */
int rtn, /* return for scanf */
choice = 0;
/* you only need a single fputs - not muliple printf calls
* there is no conversion taking place, so printf not neeeded.
*/
fputs ( "\nPhone Book Application\n\n"
" 1. Add Contact 2. Remove Contact\n"
" 3. Show Contacts ... 8. Exit\n"
"\nChoice: ", stdout);
rtn = scanf ("%d", &choice); /* ALWAYS VALIDATE EVERY INPUT */
if (rtn == EOF) { /* check if user canceled input with Ctrl+d */
fputs ("(user canceled input)\n", stderr);
break;
}
else if (rtn < 1) { /* check for matching or input failure */
fputs ("error: invalid integer input.\n", stderr);
empty_stdin(); /* always empty stdin before next input */
continue;
}
empty_stdin(); /* ditto */
if (choice == 1) { /* add book */
char *p;
/* don't realloc every addition - very inefficient.
* don't realloc the pointer itself, use a temp pointer
* or you create memory leak on failure.
*/
void *tmp = realloc (ptrBook, sizeof *ptrBook * (index + 1));
if (!tmp) {
perror ("realloc-ptrBook");
break;
}
ptrBook = tmp; /* assign new block to ptrBook */
fputs ("What is the FIRST name: ", stdout);
/* don't read line-oriented input with scanf, use fgets
* if (scanf ("%s", ptrBook[index].personName) != 1) {
*/
if (!fgets (ptrBook[index].personName, MAXNMNUM, stdin)) {
fputs ("(user canceled input.)\n", stderr);
break;
}
p = ptrBook[index].personName; /* set convenience pointer */
p[strcspn (p, "\r\n")] = 0; /* trim '\n' from end of str */
fputs ("What is the LAST name: ", stdout);
if (!fgets (ptrBook[index].personLname, MAXNMNUM, stdin)) {
fputs ("(user canceled input.)\n", stderr);
break;
}
p = ptrBook[index].personLname; /* set convenience pointer */
p[strcspn (p, "\r\n")] = 0; /* trim '\n' from end of str */
fputs ("What is the number: ", stdout);
if (!fgets (ptrBook[index].phoneNumber, MAXNMNUM, stdin)) {
fputs ("(user canceled input.)\n", stderr);
break;
}
p = ptrBook[index].phoneNumber; /* set convenience pointer */
p[strcspn (p, "\r\n")] = 0; /* trim '\n' from end of str */
printf ("\nAdded to the Phone Book.\n"
"\nName: %s %s\nPhone Number: %s\n",
ptrBook[index].personName,
ptrBook[index].personLname,
ptrBook[index].phoneNumber);
index++; /* increment index */
}
else if (choice == 2) { /* remove entry */
putchar ('\n');
for (int i = 0; i < index; i++) {
printf (" %d. %s %s\n", i + 1, ptrBook[i].personName,
ptrBook[i].personLname);
}
fputs ("\nWho would you like to remove? ", stdout);
rtn = scanf ("%d", &choice);
if (rtn == EOF) {
fputs ("(user canceled input)\n", stdout);
break;
}
else if (rtn < 1) {
fputs ("error: invalid integer input.\n", stderr);
empty_stdin();
continue;
}
else if (choice - 1 < 0 || index - 1 < choice - 1) {
fputs ("error: out of range of valid indexes.\n", stderr);
empty_stdin();
continue;
}
/* remvove entry with memmove copying over removed entry */
memmove (ptrBook + choice - 1, ptrBook + choice,
(index - choice) * sizeof *ptrBook);
index -= 1; /* decrement index */
/* realloc to remove entry */
void *tmp = realloc (ptrBook, index * sizeof *ptrBook);
if (!tmp) {
perror ("realloc-index");
break;
}
ptrBook = tmp;
}
if (choice == 3) { /* output the entries */
putchar ('\n');
for (int i = 0; i < index; i++) {
printf ("%s %s\n%d. %s\n\n", ptrBook[i].personName,
ptrBook[i].personLname, i + 1,
ptrBook[i].phoneNumber);
}
} else if (choice == 4) {
//make code to sort names
} else if (choice == 5) {
//find a phone number for a given name
} else if (choice == 6) {
//random person for you to call
} else if (choice == 7) {
//delete everyone
} else if (choice == 8) {
printf ("Exiting\n");
break;
}
}
}
(note: the use of p as a temporary pointer is simply for convenience and readability rather than having to type, e.g. the full ptrBook[index].personLname over and over and causing the strcspn command to span multiple lines)
Also, consider removing null from your struct (no clue what that is for) and consider adding index or nentries as a member so the number of entries is always part of the struct itself (which makes things much more convenient when passing or returning the struct (or pointer to it) to/from other functions)
Below note how the program can now recover from invalid input. Try the same input with your code at the menu, e.g. "I don't know" and see what happens...
Example Use/Output
$ ./bin/book_remove
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: I don't know
error: invalid integer input.
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 1
What is the FIRST name: Mark
What is the LAST name: Twain
What is the number: (444) 555-1212
Added to the Phone Book.
Name: Mark Twain
Phone Number: (444) 555-1212
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 1
What is the FIRST name: Samuel
What is the LAST name: Clements
What is the number: (444) 555-1213
Added to the Phone Book.
Name: Samuel Clements
Phone Number: (444) 555-1213
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 1
What is the FIRST name: Won Hung
What is the LAST name: Lo
What is the number: (444) 555-1214
Added to the Phone Book.
Name: Won Hung Lo
Phone Number: (444) 555-1214
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 1
What is the FIRST name: Fred
What is the LAST name: Flintstone
What is the number: (444) 555-1215
Added to the Phone Book.
Name: Fred Flintstone
Phone Number: (444) 555-1215
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 3
Mark Twain
1. (444) 555-1212
Samuel Clements
2. (444) 555-1213
Won Hung Lo
3. (444) 555-1214
Fred Flintstone
4. (444) 555-1215
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 2
1. Mark Twain
2. Samuel Clements
3. Won Hung Lo
4. Fred Flintstone
Who would you like to remove? 2
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 3
Mark Twain
1. (444) 555-1212
Won Hung Lo
2. (444) 555-1214
Fred Flintstone
3. (444) 555-1215
Phone Book Application
1. Add Contact 2. Remove Contact
3. Show Contacts ... 8. Exit
Choice: 8
Exiting
Look things over and make sure you understand what and why the changes were made. If not, then just ask for further clarification.

C programming loop logic error

I have some problem with the loop I trying to do.
My code will prompt user for the value 1, 2 to do something, and 3 to exit.
When I try to add the check for the input if it is not integer the loop will just loop non stop.
I wonder is my if( !input) is wrongly used here?
Can someone guide me?
thanks.
do
{
printf ("Input no\n");
scanf ("%d", &input);
if (input)
{
if ( input == 1)
{
printf ("do wat u wan if is 1\n");
}
if ( input == 2)
{
printf ("do wat u wan if is 2\n");
}
}
else if (!input)
{
printf("error\n");
}
}
while(input !=3 );
if ( input == 3)
{
printf ("exiting\n");
}
You have to clear the input buffer if scanf() doesn't read correctly.
int res = scanf ("%d", &input);
if( res == 0 )
{
int clear = 0 ;
while( ( clear = getchar() ) != EOF && clear != '\n') ;
}
In this case if res is not 1, scanf didn't read an integer and you have some characters left in stdin.
Also set input to 0 before passing it to scanf(), so that your if statement can handle the result correctly.
do
{
printf ("Input no\n");
if(scanf ("%d", &input)==1) //if `scanf` is successfull
{
if ( input == 1)
{
printf ("do wat u wan if is 1\n");
}
else if ( input == 2)
{
printf ("do wat u wan if is 2\n");
}
}else //scanning an integer failed
{
printf("Invalid input(non-numeric value entered). Breaking loop...\n");
scanf("%*s"); //discarding previous input
break; //or use `continue;` for looping once more
}
}
while(input !=3 );
printf ("exited loop\n");
The above code will do what you want and I've also removed uneccessary stuff from it.
The problem here is not your loop, but the format specifier in your call to scanf, if you call scanf with %d it expects an integer, if it doesn't receive one it will not be happy. Try calling scanf with %c instead and convert the read character to the corresponding integer value, this fixes your problem and should be managable to do by you.
Change the first part of your code to:
...
int input;
do
{
char line[256];
printf("Input no\n");
fgets(line, sizeof(line), stdin);
sscanf(line, "%d", &input);
if (input)
...
Never ever use scanf! This is almost unusable. It may lack consistent behavior across compilers.
The problem is: if scanf() encounters an item which is not usable according to the format %d, the item will stay in the input buffer forever. You can avoid this by using %s and converting afterwards. Better: on line-input use line-reading (gets()/fgets())
If you want to detect digits/non-digits in the incoming string, you could use the isdigit() function from <ctype.h>. Your code would end up in the following form:
int input;
do {
char line[256];
printf("Input no\n");
fgets(line, sizeof(line), stdin);
if (isdigit(line[0])) { /* check if first char is a number */
sscanf(line, "%d", &input); /* scan this number from string */
if (input == 1) {
printf("do wat u wan if is 1\n");
}
if (input == 2) {
printf("do wat u wan if is 2\n");
}
}
else {
input = 0; /* reset input to any value != 3 */
printf("error\n");
}
} while (input != 3);
Don't forget to #include <ctype.h>.

Search Method Failing

I'm trying to do a search Method in which checks 2 IDs which only store integer.
Firstly I have a database of customers. I input the Name,Surname,ID and Address after each other in this order and then these are immediately saved into the file
When the User inputs the ID card this calls this Search Method and checks through all the file to see whether the ID is unique or not. If it is not, then it returns 0 otherwise it returns 1
Now the problem is this.
When I am inputting the ID, whether it is unique or not it keeps on going, but then when it outputs what I wrote it, for the NAME and SURNAME it shows only the first record I have stored there (like stuck in some kind of buffer), the ID and the address outputs normally.
The File is Also NOT Updated meaning, the save file did not occur.
Now when I Remove this method, the appending works normally, but I won't have access to the comparing of IDs.
Any suggestions why this is happening? and if possible any idea how I can fix it?
it's like whenever I'm doing this search method the whole file is getting started from the beginning and getting stuck there. I Tried using the method with boolean but still no avail. When I tried using it with Boolean instead of the line "if (customerID(scanf ("%d",&cCheck)) == 1)" I made it == TRUE, it was giving me an error that the output will
always be == FALSE because the data is not NULL.
and oh TRUE and FALSE are valid in my case as I have a typedef enum boolean in the common.h
The code is as follows [posting the whole file]:
The methods concerned are [ void addCustomer()] and [int customerID (int cCheck)
but I posted all as some of them are interconnecting.
EDIT!!! - The ID even if they are NOT unique, it is still Accepted...
/*
* CustomerMainMenu.c
* Author: DodoSerebro
*
* This class will output the Customer's Main Menu and re-directs to the
* corresponding section
*
*/
#include<io.h>
#include<fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "..\Headers\common.h"
#include "..\Headers\customerManagement.h"
static FILE *cfp;
static customer c;
#define STRUCTSIZE sizeof (customer)
/** This is the Customers's Main Menu in which the various sections can be
* accessed from here
*/
boolean customerMainMenu()
{
int optionC;
clrscr();
copyright();
printf ("\n\n\n\n\t\t ************* Customer's Main Menu *************\n \n \n");
printf ("Press [1] to add a new Customer\n");
printf ("Press [2] to edit a Customer\n");
printf ("Press [3] to list all Customers\n");
printf ("Press [4] to Show a Customer's last Order\n");
printf ("Press [5] to go back to Main Menu\n\n\n");
if (scanf ("%d",&optionC) == 1)
{
switch (optionC)
{
case 1:
{
clrscr();
getchar();
addCustomer();
break;
}
case 2:
{
printf ("Edit a Customer\n");
break;
}
case 3:
{
clrscr();
listCustomers();
system ("PAUSE");
break;
}
case 4:
{
printf ("Customer's Last Order\n");
break;
}
case 5:
{
system ("PAUSE");
break;
}
default:
{
if (optionC != 1 || optionC != 2 || optionC != 3 || optionC != 4 || optionC !=5)
{
clrscr();
printf ("Invalid option!\n");
system ("PAUSE");
customerMainMenu();
}
break;
}
}
}
return TRUE;
}
/**
* This following method will append a customer to the
* database at the end of the file
*
* */
void addCustomer ()
{
char ch;
copyright();
printf ("\n\n\n\n\t\t ************* Add Client **********\n \n \n");
if ((cfp = fopen ("customers.dat","a+b")) == NULL)
{
fputs("Can't open customers.dat file\n",stderr);
}
printf ("\tThis will add another customer to the the database\n");
printf ("\tPress 'Y' to confirm or 'N' to return to the Client Main Menu\n\tWITHOUT adding a customer\n");
ch = getchar();
if (ch == 'n' || ch == 'N')
{
customerMainMenu();
}
else if (ch == 'y' || ch == 'Y')
{
fflush(stdin);
clrscr();
printf ("\n\n\n\n\t\t ************* Add Client **********\n \n \n");
printf ("Please enter Name:\n");
while (scanf ("%s", c.name) == 0 || cCheck(c.name,100) == FALSE);
{
}
printf ("Please Enter Surname: \n");
while (scanf ("%s",c.surname) == 0 && cCheck (c.surname,100) == FALSE);
{
}
printf ("Please Enter ID Card, [NOTE! Only numbers are allowed!]\n");
int cCheck;
if (customerID(scanf ("%d",&cCheck)) == 1)
{
printf ("ID already Taken, Client exists!\n");
printf ("Do you want to enter another ID? 'Y' for Yes and 'N' to return to Main Menu\n");
ch = getchar();
if (ch == 'Y' || ch == 'y')
{
scanf ("%d",&cCheck);
customerID(cCheck);
c.ID = cCheck;
}
else
{
customerMainMenu();
}
}
else
{
c.ID = cCheck;
}
getchar();
printf ("Please Enter Address:\n");
gets(c.address);
fwrite (&c,STRUCTSIZE, 1, cfp);
printf ("For Testing purposes:\n");
printf (" %s\n %s\n %s\n %d\n", c.name, c.surname, c.address, c.ID);
askAnother();
}
else
{
printf ("\nInvalid choice! Either Y or N is accepted\n");
system ("PAUSE");
getchar();
clrscr();
addCustomer();
}
}
void listCustomers()
{
if ((cfp = fopen ("customers.dat","rb")) == NULL)
{
fputs("Can't open customers.dat file\n",stderr);
printf ("Returning to Customer Main Menu");
system ("PAUSE");
customerMainMenu();
}
rewind (cfp);
while (fread (&c,STRUCTSIZE,1,cfp)==1)
{
printf ("Customer: %s %s ID: %d\n", c.surname, c.name, c.ID);
}
fclose (cfp);
}
void askAnother()
{
printf ("Do you want to add another Customer?\n");
printf ("Enter 'Y' for yes and 'N' to return to the Main Menu\n");
char input;
input = getchar();
if (input == 'Y' || input == 'y')
{
getchar();
addCustomer();
}
else if (input == 'N'|| input == 'n')
{
fclose (cfp);
customerMainMenu();
}
else
{
printf ("Invalid Option! Only Y or N are allowed\n");
system ("PAUSE");
clrscr();
askAnother();
}
}
boolean cCheck(char *test, int max)
{
int x;
for (x =0; x<max; x++)
{
if (isdigit(test[x]))
{
return FALSE;
}
if (x==max)
{
return TRUE;
}
x++;
}
return TRUE;
}
/**
* This method will compare the ID passed from the ID of the customer to check
* whether it is exists or not. If it exists it will output 1 otherwise it
* will output -1. This will make sure that the Person's ID is unique
*
*/
int customerID (int cCheck)
{
rewind (cfp);
while (fread (&c,STRUCTSIZE,1,cfp)==1)
{
if (c.ID == cCheck)
{
return 1;
}
else
{
return 0;
}
}
return 1;
}
EDIT!!
Uploading Image to show what I mean if I'm not clear
(Notice how the name and surname differ from those Input)
!http://s017.radikal.ru/i443/1212/c8/1ea9bc56d980.jpg
The following shows what I have in the file
(only one file)
!http://s017.radikal.ru/i431/1212/49/2a0df6acf9ec.jpg
if (customerID(scanf ("%d",&cCheck)) == 1)
Here, you are the return value of scanf() to function customerID() whereas you actually wanted to pass the scanned value cCheck.
You can separate the call to function and input reading as below:
if(scanf ("%d",&cCheck) != 1) {
// Input error handling
}
else if (customerID(cCheck) == 1) {
...
Another issue is, you have a function named cCheck and you also have a local variable named cCheck. Rename one of them appropriately.

Problems with character input using scanf()

I'm trying to input a character into a linked list, where the character can be 'A','a','G','g','T','t','C' or 'c'.
I'm not yet familiar with C and I know I've screwed something up here:
do{
printf ("\nEnter a new nucleotide: \n");
scanf("%c",&newChar);
/* Checking */
if(newChar == 'A' ||
newChar == 'a' ||
newChar == 'G' ||
newChar == 'g' ||
newChar == 'T' ||
newChar == 't' ||
newChar == 'C' ||
newChar == 'c' )
{
AddToSequence(newChar);
size++;
} else {
printf ("\nBad Element");
}
}while(newChar != 'x');
newChar is initialized with a junk value, in this case 'q'.
Entering 'x' exits the loop, entering any acceptable value calls AddToSequence(), and any unacceptable value gets a warning.
For some reason, no matter what value is in newChar, it will jump to the else. It will also jump straight past the scanf without waiting for entry from the user and do two loops every time it loops. Can anyone tell me where I'm going wrong?
Full program:
#include<stdio.h>
#include<stdlib.h>
/*Structure declaration for the node*/
struct node{
char nucleotide;
struct node *point;
}*start;
/* Adds a nucleotide to the chain. Creates a new linked list if no chain exists exists.*/
void AddToSequence(char nucleotide){
struct node *loc, *first;
//Dynamic memory is been allocated for a node
first=(struct node*)malloc(sizeof(struct node));
first->nucleotide=nucleotide;
first->point=NULL;
if(start==NULL){
/*If list is empty*/
start=first;
}else{
/*Element inserted at the end*/
loc=start;
while(loc->point!=NULL){
loc=loc->point;
loc->point=first;
}
}
}
/* Display elements */
void Display(){
struct node *loc;
if(start == NULL){
printf ("\n\nList is empty");
return;
}
loc=start;
printf("\n\nList is : ");
while(loc!=NULL){
printf ("%c", loc->nucleotide);
loc=loc->point;
}
printf ("\n");
}
/* Finds and displays percentage of the chain made up of each nucleotide. */
void Percentage(int size){
struct node *loc;
if(start == NULL){
printf ("\n\nList is empty");
return;
}
loc=start;
printf("\n\nList is : ");
int A = 0, G =0, T =0, C = 0;
double Adouble = 0, Gdouble =0, Tdouble=0, Cdouble=0;
while(loc!=NULL){
if(loc->nucleotide=='A' || 'a'){A++;}
if(loc->nucleotide=='G' || 'g'){G++;}
if(loc->nucleotide=='T' || 't'){T++;}
if(loc->nucleotide=='C' || 'c'){C++;}
loc=loc->point;
}
printf ("\n");
/* Convert to double for percentages as int loses precision */
Adouble =A;
Gdouble =G;
Tdouble =T;
Cdouble =C;
Adouble =(Adouble/size)*100;
Gdouble =(Gdouble/size)*100;
Tdouble =(Tdouble/size)*100;
Cdouble =(Cdouble/size)*100;
printf("\nA: %f", Adouble);
printf("\nG: %f", Gdouble);
printf("\nT: %f", Tdouble);
printf("\nC: %f", Cdouble);
}
/* There be dragons beyond here */
int main(){
int navigate, size =0;
char newChar = 'q';
do{ /* Menu */
printf("\n 1. Create / Extend Sequence\n");
printf("\n 2. Display Sequence\n");
printf("\n 3. Count \n");
printf("\n 0. Exit \n");
printf("\nPlease select an option (0 to 3)\n");
scanf("%d",&navigate);
switch (navigate){
case 0: /* Exit */
break;
case 1: /* Add nucleotides */
do{
printf ("\nEnter a new nucleotide: \n");
scanf("%c",&newChar);
/* Some error checking */
if(newChar == 'A' || newChar == 'a' || newChar == 'G' || newChar == 'g' || newChar == 'T' || newChar == 't' || newChar == 'C' || newChar == 'c' ){
AddToSequence(newChar);
size++;
} else {
printf ("\nBad Element");
}
}while(newChar != 'x');
break;
case 2:
Display();
break;
case 3:
Percentage(size);
break;
default:
printf ("\n\nBad choice. Please select another.\n");
}
} while (navigate !=0);
return 0 ;
}
You don't handle the newline. The %c specifier doesn't skip blanks. Try:
scanf(" %c", &newChar);
/* ^ <-- Makes `scanf` eat the newline. */
Or maybe add an explicit test.
scanf(...);
if (newChar == '\n')
continue;
add space to "%c" to catch the newline character. the space charcter is used to catch space characters, tabulations, newline
scanf("%c ",&newChar);
You're leaving the '\n' on stdin:
scanf("%d",&navigate);
getchar(); // consume the newline character
...
scanf("%c",&newChar);
getchar(); // consume the newline character
Or since you're already using scanf() you can tell scanf itself to take care of the newline character:
scanf("%d\n", &navigate);
....
scanf("%c\n",&newChar);
Even better you can leave it open by adding a space after the format specificer:
scanf("%d ", &navigate);
....
scanf("%c ",&newChar);
Just in case the user wants to do something like: 2<tab key><enter key>
Regardless of how you handle it, the point is you need to consume the newline character.
Use
newChar=getche();
This is a nonstandard function that gets a character from the keyboard, echoes to screen.

Resources