user initiated looping in c++ [duplicate] - c++

This question already has answers here:
How to do scanf for single char in C [duplicate]
(11 answers)
Closed 8 years ago.
I would like to write a program that takes a input from the user and calculates the triangular number. There should also be an option to ask the user if he wants to take another input or exit and that needs to be done using while or do...while. I have the following code written but doesn't do what is intended:
#include <stdio.h>
int main(void)
{
int n, number, triangularNumber;
char s = 'Y';
while (s == 'Y') {
printf("What triangular number do you want? ");
scanf("%i", &number);
triangularNumber = 0;
for (n = 1; n <= number; ++n)
triangularNumber += n;
printf("Triangular number %i is %i\n\n", number, triangularNumber);
printf("Do you want to continue?\n");
scanf("%c", &s);
}
return 0;
}
The above code only does it once after which it exits. How can I make it run the loop again based on the input I give? Thanks in advance.

scanf("%i",&number); generates a newline that is consumed by your scanf("%c",&s);
Rewrite as scanf(" %c",&s) (contains a space before %c) to ignore all whitespace before input.

Two problems: First of all there is a difference between small and capital letters, 'y' != 'Y'.
The second problem, and what you are seeing here, is that the first scanf where you read the number, it leaves the newline in the input buffer. Then the second scanf call reads that newline and writes it to the variable s.
The first problem can easily be solved by making sure the contents of the variable s is a capital letter, by using toupper:
while (toupper(s) == 'Y') { ... }
The second problem can be just as easily fixed by asking scanf to read and discard leading whitespace when getting the character, this is done by simply adding a space before the format code:
scanf(" %c", &s);
// ^
// |
// Note space here

Related

How to keep taking values from the user in C but stop when the user does not enter any value and presses enter?

int k;
vector<int>v;
while ((scanf("%d", &k)) != EOF) {
if (v.size() > 20) break;
else {
if (k > 0 && k <= 120) v.push_back(k);
}
}
**The above snippet is taken from codechef blogs **
<rant>Never tag a question both C and C++ on SO again. It is reserved for questions about interoperations or very specific language-lawyer points, and should not be used for code that could be more or less used on both languages. In that latter case choose one in your first question and if you later need it ask a new question for the other language</rant>
Your problem is that for the scanf family questions spaces and newlines are just ignored when you use a %d conversion character. And scanf returns the number of elements that could be decoded and only stops on an end of file, read error or conversion error.
If you want to be able to detect an empty input, you will have to use fgets + sscanf from the C standard library, or getline + stringstream from the C++ one.

using getchar() and getting stuck in loop [duplicate]

For my homework assignment, I need to implement Horners Algorithm for converting between bases.
I have been told to use getchar() for this assignment. But I am having a problem where when I hit enter, the program doesn't terminate and just takes in more chars.
Example:
bryce> ./pa1
Enter the fromRadix:16
Enter the toRadix:2
abc
abc
^C
bryce>
Code:
int readRadixA(int radixA)
{
char myChar = getchar();
int result = 0;
int run = 0;
while(myChar != EOF)
{
if(myChar == "\n")
break;
Horners();
myChar = getchar();
}
return result;
}
I am not asking for help implementing Horners; I am asking for help to terminate the getchar() correctly.
if(myChar=="\n")
^ ^
You're comparing myChar wrong. Try this instead:
if(myChar == '\n')
^ ^
A second problem is that getchar returns int, not char. Maybe you can rewrite it like this:
int myChar;
while((myChar = getchar()) != EOF && myChar != '\n')
{
/* Your stuff. */
}
EDIT
In light of comments, I think some stdio operation before that while is leaving a \n in the buffer.
Instead of scanf("%d", &radix) try:
scanf("%d ", &radix);
^
That space will make scanf eat the remaining blanks (including the newline).
Check the return type of getchar(). Yes, it's an int. That's because EOF must have a value that can be distinguished from a valid character. myChar must actually be made to be int.
Try this code
int readRadixA(int radixA)
{
char myChar;
int result = 0;
int run = 0;
do
{
myChar = getchar();
// implement horners here
}while(myChar != 13);
return result;
}
I checked your code I think you are leaving a '\n' in the input keyboard buffer after the toRadix.
And their is one more thing that
getchar()
reads all the characters in one go till a '\n' is received.
And there is one more mistake you have committed by comparing a
char to a pointer e.g mychar=="\n"
further information about your implementation of toRadix can be really helpful to answer your question
On linux, to end the standard input, you have to type  Ctrl-D. The kernel and tty layers makes that an end-of-file mark or condition. Then getchar gives EOF (which is not a valid char, for example on systems where char are unsigned bytes between 0 and 255, EOF could be -1).
Notice that feof(3) is valid only after a read operation (e.g. getchar, fgets, etc...) so coding while(feof(stdin)) is generally wrong (contrarily to what I wrote in the previous version of this answer). You'll better test that getchar is returning EOF so your myChar should be an int (not a char).

Error in reading the file in C [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm trying to write and read from file. writing works fine, but when it tries to read, the program crashed. tell me whats the error?
The objective of this program is to store the record of students in a file.
Calculate the percentage, and find the highest and lowest percentage of student.
#include <stdio.h>
#include <conio.h>
#include <string.h>
struct result
{
char name[15];
int batchNo;
int rgtNo;
int marks;
float perc;
};
int main()
{
char answer, i = 1;
FILE *ptr, *abc;
result s, st;
int j;
ptr = fopen("rec.txt","a");
abc = fopen("rec.txt","r");
if(!ptr)
printf("Error opening file");
else if(!abc)
printf("Error opening read file");
else {
do
{
int sum = 0;
printf("\nEnter name of student %d: ", i);
scanf("%s", s.name);
printf("\nEnter Batch #: ");
scanf("%d", &s.batchNo);
printf("\nEnter Registeration no: ");
fflush(stdin);
scanf("%d", &s.rgtNo);
printf("\nEnter marks of Five subjects: ");
scanf("%d",&s.marks);
/*for(j = 0; j < 5; j++)
{
scanf("%d",&s.marks[j]);
sum += s.marks[j];
}*/
s.perc = sum / 5.0;
printf("Percentage of student %d: %f", i+1, s.perc);
fprintf(ptr, "%s %d %d %d %f", s.name, s.batchNo, s.rgtNo, s.marks, s.perc);
printf("\n\n\n");
printf("Do you want to add another record? (y/n) ");
answer = getche();
i++;
} while(answer == 'y');
printf("outside loop\n");
fclose(ptr);
fflush(stdin);
rewind(abc);
do
{
fscanf(abc, "%s%d%d%d%f", s.name, s.batchNo, s.rgtNo, s.marks, s.perc);
printf("in loop");
} while( !feof(abc));
fclose(abc);
}
}
So many defects, so little time.
C is not C++
They are two different languages. Remove the C++ tag.
But since you tagged it as C++, you should use the fstream and iostream libraries as well as the std::string type.
One pointer per physical file
You have one FILE * for each different mode of the same file. In many cases, this will confuse the operating system and heck some won't allow it.
Instead, use one FILE * and open the file as rw+ for read, write and append.
See fseek function.
Buffer overflow with scanf
You have reserved 15 letters for the name. What happens if the user types in a name longer than 15 letters? Buffer overflow. You could write over other variables that follow the name member.
You could resolve this by using fscanf with the C language or std::cin and std::string with the C++ language.
Flushing the input
The flush function only works with output buffers. Don't use with input streams.
In the C language you have to read characters until the buffer is empty or until your terminator character is found (such as 'n').
In C++ this is accomplished by cin.ignore(1000000, '\n').
Checking input functions for errors
You can't trust the User. You must check the scanf return value for errors. If you ask for a number and the User types in a number, the scanf will fail. The value is undefined.
the program crashes whenever you type something different than 'y' at the last question Do you want to add another record? (y/n).
think what happens after this stage in your program...
hint - take a look at your ptr and abc File pointers - do they point to the same file?
The issue which makes your program segfault is the fscanf call: you're supposed to pass pointers to variables for arguments. I guess you quickly C&P without double checking your code.
As mentioned in another answer: fflush behaviour isn't specified for input streams, though many implementations behave as you expect. Another way to flush is to do a loop on the stream and read char by char:
void flush_stdin(){
char c;
while (c != '\n' && c != EOF)
c = getchar();
}
Note: I'm using getchar, as getche isn't available on my system. I suppose you should have it too, and would recommend using it for portability.
Regarding multiple opening of the same file in different modes: I don't think it should be a problem, though it seems much more straightforward to open it in append mode first, close it when the input session is done, and then reopen it for reading afterwards. In a more complex program, you'd probably split these two functionalities in separate functions, each doing its own I/O, thus following that pattern.
One last thing: you probably want to test the result of your calls to scanf and the like. Perhaps a small macro like the following would help:
#define CHECK_SCAN(x) do { \
int err = (x); \
if (err <= 0) { \
printf("error on scan: %s", strerror(err)); \
exit(1); \
} } while(0)

What is wrong with my UVa code

I tried to solve this problem in UVa but I am getting a wrong answer and I cant seem to find the error
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2525
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int t,j,k,i=1;
char a[1000];
while(scanf("%d",&t)!=EOF && t)
{
int sum=0;
getchar();
gets(a);
k=strlen(a);
for(j=0;j<k;j++)
{ if(a[j]=='a'||a[j]=='d'||a[j]=='g'||a[j]=='j'||a[j]=='m'||a[j]=='p'||a[j]=='t'||a[j]=='w'||a[j]==32)
sum=sum+1;
else if(a[j]=='b'||a[j]=='e'||a[j]=='h'||a[j]=='k'||a[j]=='n'||a[j]=='q'||a[j]=='u'||a[j]=='x')
sum=sum+2;
else if(a[j]=='c'||a[j]=='f'||a[j]=='i'||a[j]=='l'||a[j]=='o'||a[j]=='r'||a[j]=='v'||a[j]=='y')
sum=sum+3;
else if(a[j]=='s'||a[j]=='z')
sum=sum+4;
}
printf("Case #%d: %d\n",i,sum);
i++;
}
return 0;
}
In the problem description there is a single number that indicates the number of texts that will be in the input afterwards. Your original code was trying to read the number before every row of input.
The attempt to read the number in each one of the rows will fail since the input character set does not include any digits, so you could be inclined to think that there should be no difference. But there is, when you try to read a number it will start by consuming the leading whitespace. If the input is:
< space >< space >a
The output should be 3 (two '0' and one '2' keys), but the attempt to read the number out of the line will consume the two leading whitespace characters and the later gets will read the string "a", rather than " a". Your count will be off by the amount of leading whitespace.
separate your code into functions that do specific things: read the data from the file, calculate the number of key presses for each input, output the result
Benefit:
You can test each function independently. It is also easier to reason about the code.
The maximum size of an input is 100, this means you only need an array of 101 characters( including the final \0) for each input, not 1000.
Since this question is also tagged C++ try to use std::vector and std::string in your code.
The inner for seems right at a cursory glance. The befit of having a specialized function that computes the number of key presses is that you can easily verify it does the correct thing. Make sure you check it thoroughly.

ASCII and isalpha if statement issue

I am writing a program that takes a user inputted character, such as A, and a user inputted number, such as 7. The program checks the validity of the character, if true runs thru till it gets to this loop inside of a function. I am using ascii decimal for this loop inside of a function. This loop needs to check isalpha and if it is run the code inside the {}'s, it's doing that correctly. The else is not working the way I want and am not sure how to correct it. I need the else (is not alpha) to add a 1 back to the counter in the loop and increase the ascii by 1. If I run it as so, it gives off a retry/ignore/abort error. If I run it without the num++; it runs and stops after the loop ends. So, if you put in a Z and choose 3, it runs thru the loop 3 times and outputs just a Z. Any thoughts on how to fix this?
I need it to output something like: Input: Z Input: 4 it should output: Z A B C to the screen. It needs to ignore other ascii non alpha characters.
Thanks
string buildSeries(char A, int num)
{
//builds the output with the info the
//user inputted
stringstream str1;
string outted;
int DeC=(int)A, i = 0;
//loop builds the output
for(i=0;i<num;i++)
{
if (isalpha(DeC))
{
//converts the decimal to a letter
str1<<(char)DeC;
//adds a space
str1<<" ";
//increases the decimal
DeC++;
}
else
{
num++;
DeC++;
}
}
//builds the sstream and puts it in
//variable "outted"
outted = str1.str();
return outted;
}
If you need to loop back to 'A' at Z change your DeC++ to
if DecC == 'Z'
DecC = 'A'
else
DecC++;
Or you could get fancy and use the modulus operator
Edit
I think the problem may be that this stringstream insertion operator, >>, doesn't have an overload that handles a char. It's converting the char to a short or an int then inserting it. Try using string::append(size_t size, char c) instead. That should handle inserting a char.
That is replace you calls to str1<<(char)DeC; with outted.append(1, (char)DeC) and remove your use of the string stream
What is DeC? The phrase "ascii list" makes me suspect it's a 'C' string, in which case you are calling isAlpha() on the pointer not on the value in the string.
edit: If for example you have
char DeC[40];
// read in a string form somewhere
// DeC is a pointer to some memory it has a value of a 32 or 64bit number
if ( isAlpha(DeC) {
// what you might have meant is
if ( isAlpha(*DeC) { // the character value at the current position in DeC