i'm trying to make the c++ program that manage student list but got into error from the very beginning. Here's my program:
#include<iostream>
#include<string.h>
using namespace std;
struct Candidate
{
char id[5];
char fullname[30];
int reading, listening,total;
};
int main ()
{
struct Candidate can[100];
int n=0;
do {
cout << "Input number of candidate:";
cin >> n;
if (n <= 0 || n>=50)
cout << "Candidate number must be between 0 and 50:\n";
} while (n <= 0 || n>=50);
for (int i = 0; i < n; i++)
{
cout << "Input information for candidate number " << i + 1 << endl;
cin.ignore(32323, '\n');
cout << "Input ID(only 5 character):";
gets(can[i].id);
cout << "Input full name:";
gets(can[i].fullname);
do {
cout << "Input reading mark:";
cin >> can[i].reading;
if(can[i].reading < 5 || can[i].reading>495)
cout<<"Your reading mark is not between 5 and 495\n";
} while (can[i].reading < 5 || can[i].reading>495);
do {
cout << "Input listening mark:";
cin >> can[i].listening;
if(can[i].listening < 5 || can[i].listening>495)
cout<<"Your listening mark is not between 5 and 495\n";
} while (can[i].listening < 5 || can[i].listening>495);
can[i].total = can[i].reading + can[i].listening;
}
cout << endl << can[0].id<<endl;
}
So i got an output like this:
Input number of candidate:1
Input information for candidate number 1
Input ID(only 5 character):EW2RR
Input full name:Test1
Input reading mark:344
Input listening mark:233
EW2RRTest1
It seems like the value of fullname is written continually to ID. I have tried a lot of way to fix but couldn't figure out. Does anyone have a clue?
In every string if you have a string length of N you must have char array of size at least N+1 for '\0' which indicates that the string ends here for cout to stop printing.
In your case you declared char array of size 5 and you fill all 5 with characters so '\0' is put somewhere else. Notice that "id" and "fullname" locate next to each other , so my best guess is that gets put '\0' of when you scan "ID" which should be "id[5]" to "fullname[0]", and then when you scan "FULLNAME" , it replaces this '\0' , so "id" has no termination point and must use termination point of "fullname". That's why it seems like fullname has been appended to id. Be aware that this is not the default behavior , the program may act different on other machines.
Also , gets() is a broken function , if you use cin or scanf before , you should flush your stdin first by calling
fflush(stdin);
before you use gets() because sometimes '\n' is left in the stdin but in your case this was taken care by
cin.ignore(32323, '\n');
Using fgets() as Paul Rooney stated is much more preferable. I myself also had a lot of problems with gets.
Happy Coding!!
You need to put a terminal '\0' char at the end of every string.
When the ID gets printed, the code (cout) won't stop til it hits a NULL.
This is called overrunning your buffer.
Related
I have used a loop for that:
int number1;
int sum=0;
for(int i =1; i<6; i++){
cout<<"Enter number:\n";
cin>>number1;
sum+=number1;
}
cout<<sum;
cout<<"Total Sum is = "<<sum<<"\n";
return 0;
}
My question is how can I print first statement like this ...
"Enter first number"
Enter Second number" and so on
Whenever you are reading numbers (or any value for that matter), you must check the stream-state (see: std::basic_istream State Functions). You have four stream states you must test following every input:
.bad() or .eof(). If badbit is set an unrecoverable error occurred, and if eofbit is set, there is nothing more to read (you can combine both into a single test that exits if either are set)
.fail() is set when a read error occurs, such as the user entering "FIVE" instead of 5 where integer input is expected. You handle failbit being set by calling .clear() to clear failbit and then call ignore() to empty the characters causing the failure before your next read attempt, and finally
.good() - valid input was received from the user, you can proceed to the next input.
By validating your input here, you can Require the user provide 5 valid integer values for you to sum. Do not use a for loop, instead use a while (or do .. while();) and only increment your counter when good input is received.
Putting that altogether, you can do:
#include <iostream>
#include <limits>
int main (void) {
int number = 0,
sum = 0;
const char *label[] = { "first", "second", "third", "fourth", "fifth" };
while (number < 5) /* loop continually until 5 int entered */
{
int tmp; /* temporary int to fill with user-input */
std::cout << "\nenter " << label[number] << " number: ";
if (! (std::cin >> tmp) ) { /* check stream state */
/* if eof() or bad() exit */
if (std::cin.eof() || std::cin.bad()) {
std::cerr << " (user canceled or unreconverable error)\n";
return 1;
}
else if (std::cin.fail()) { /* if failbit */
std::cerr << " error: invalid input.\n";
std::cin.clear(); /* clear failbit */
/* extract any characters that remain unread */
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
else { /* on succesful read of int, add to sum, increment number */
sum += tmp;
number++;
}
}
std::cout << "\nsum: " << sum << '\n';
}
Now your code will gracefully handle an invalid input without exiting just because a stray character was entered.
Example Use/Output
When you write an input routine, go try and break it. Enter invalid data and make sure you handle all error cases correctly. If something doesn't work right, go fix it. Repeat until you input routine can handle all corner-cases as well as the cat stepping on the keyboard:
$ ./bin/sumintlabel
enter first number: 3
enter second number: four five six seven!!
error: invalid input.
enter second number: 4
enter third number: 5
enter fourth number: 6
enter fifth number: 7
sum: 25
Form good habits now regarding handling input, it will pay dividends for the rest of your programming career. Let me know if you have questions.
if you need to print the words "first"... untill "fifth" then I'd do it like this:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int number1;
int sum=0;
string positions[5] = {"first", "second", "third", "fourth", "fifth"};
for(int i = 0; i<5; i++){
cout<<"Enter the " << positions[i] << " number:" << endl;
cin>>number1;
sum+=number1;
}
cout<<"Total Sum is = "<<sum<<"\n";
return 0;
}
I used an array of strings to display the words and changed the for loop to start at 0 so that we can go through the array positions and add the 5 numbers as well. If you just want to use: 1st, 2nd, 3rd... then you could change the for loop to what it was and do:
cout<<"Enter the " << i << "st" << " number:" << endl;
But for this you would have to use the if statement to print the right endings("st", "rd", "nd"). I think it would take longer for it to run but its miliseconds so we wouldn't even notice hahaha.
Hope it helped :)
You can use switch():
#include <iostream>
using std::cin;
using std::cout;
using std::string;
int main() {
int number1;
int sum = 0;
for(int i = 1; i < 6; i++) {
string num;
switch(i) {
case 1:
num = "first";
break;
case 2:
num = "second";
break;
//and 3 4 5 like this
}
cout << "Enter " << num << " number:\n";
cin >> number1;
sum += number1;
}
cout << "Total Sum is = " << sum << "\n";
return 0;
}
or you can use struct or containers like vector (in fact you have to use containers if you want to get a huge number of data.)
I have what seems like a pretty simple, beginner question that I must be missing something obvious. I am just trying to prompt the user to input a 4 digit number and then take in the input as an array, splitting up the digits to be by themselves. I thought it hade something to do with "cin >> input[4]" I just can't seem to get the right answer.
int main()
{
int input[4]; //number entered by user
cout << "Please enter a combination to try for, or 0 for a random value: " << endl;
cin >> input[4];
}
When I go to run it, I get an error message "Stack around the variable was corrupted.
I tried looking at similar examples in other questions but I just can't seem to get it right. I need the input as one 4 digit number and then split it up to a 4 position array.
If anyone could help I would greatly appreciate it.
Your array is of size 4, so elements have indicies 0 .. 3; input[4] is located behind the end of your array so you are attemping to modify memory not allocated or allocated for other stuff.
This will work for you:
cin >> input[0];
cin >> input[1];
cin >> input[2];
cin >> input[3];
You do not need an arry to input 4 digit number.
int in;
int input[4];
cin >> in;
if(in>9999 || in < 1000) {
out << "specify 4 digit number" << endl;
return;
}
input[0] = in%1000;
input[1] = (in-1000*input[0])%100;
input[2] = (in-1000*input[0]-100*input[1])%10;
input[3] = in-1000*input[0]-100*input[1]-input[2]*10;
The problem is that you are trying to read in a character that does not exist (the one at index 4).If you declare input as int input[4];, then it doesn't have any characters at index 4; only indices 0...3 are valid.
Perhaps you should just use an std::string and std::getline(), and you could then parse the user input to integers however you like. Or you can try
std::cin >> input[0] >> input[1] >> input[2] >> input[3];
if you can live with the constraint that the numbers must be whitespace-separated.
This includes a small bit of error checking:
int n = 0;
while( n < 1000 || n >= 10000 ) // check read integer fits desired criteria
{
cout << "enter 4 digit number: ";
cin >> n; // read the input as one integer (likely 10 digit support)
if( !cin.good() ) // check for problems reading the int
cin.clear(); // fix cin to make it useable again
while(cin.get() != '\n'); // make sure entire entered line is read
}
int arr[4]; // holder for desired "broken up" integer
for( int i=0, place=1; i<4; ++i, place *= 10 )
arr[i] = (n / place) % 10; // get n's place for each slot in array.
cout << arr[3] << " " << arr[2] << " " << arr[1] << " " << arr[0] << endl;
I'm just starting to learn c++ and in this whole pointer / arrays chapter I'm trying to code something to get a grip on those concepts. What I want my code to do is: 1) ask for a number of students, 2) ask for a name for each student, 3) assign an ID and name to this student in a struct, 4) print the student ID and names for verification.
The problem is the following.
Let's say for example I choose to type 3 students and type the following names:
JOHN
GEORGE
NICK
What the program prints back as student ID/Names will be:
0 JOHN
1 EORGE
2 ICK
It seems to cut the first letter of all names but the first one.
#include <iostream>
using namespace std;
struct STUDENT
{
char chName[256];
int nID;
};
int main(){
//array tests
int i=0;
int nLoops=0; //number entered by user
STUDENT *pnStudents; //pointer to our student array
cout << "Enter number of students: ";
cin >> nLoops;
pnStudents = new STUDENT[nLoops];
for (i=0 ; i < nLoops ; i++)
{
cout << endl << "Full Name of Student " << i <<": ";
cin.ignore();
cin.getline(pnStudents[i].chName,255);
pnStudents[i].nID=i;
}
for (i=0 ; i < nLoops ; i++)
{
cout << pnStudents[i].nID << " " << *pnStudents[i].chName << endl;
}
system("pause");
return 0;
}
for (i=0 ; i < nLoops ; i++)
{
cout << endl << "Full Name of Student " << i <<": ";
cin.ignore();
cin.getline(pnStudents[i].chName,255);
pnStudents[i].nID=i;
}
In the first iteration of the loop, ignore() extracts a new line character that has been left in the stream by cin >> nLoops; call. istream::getline(), on the other hand, discards the trailing '\n' and so each subsequent iteration waits for and discards the first character of your input.
Move cin.ignore() just before the loop.
cin.ignore(); without an argument discards from cin, a stream of size 1.
istream& ignore ( streamsize n = 1, int delim = EOF );
Extract and
discard characters Extracts characters from the input sequence and
discards them.
Remove that. That seems to be the only thing in your code, which could eat one character away. Also, if you need to use ignore, use something like:
cin.ignore(256,' ');
^ ^ (number of char, delim)
If you are trying to ignore the character you took as input for nLoops, you need not do it in every iteration.
the following is an exercise from a book for practicing some class inheritance. But the problem is in the client, not with the class design. (BaseCore, baseDMA, lacksDMA and hasDMA are the classes BTW).
// usedma.cpp -- polymorphic example (compile with dma.cpp)
#include <iostream>
#include "dma.h" // includes <iostream>
const int ELEMENTS = 1;
const int LENGTH = 30;
int main()
{
using std::cin;
using std::cout;
BaseCore *pArr[ELEMENTS];
char tempDate[LENGTH];
char kind;
for (int i = 0; i < ELEMENTS; i++)
{
cout << "\nEntering data for element #" << i + 1 << "\n\n";
cout << "Enter the date it was created: ";
cin.getline(tempDate, LENGTH - 1);
cout << "Enter 1 for baseDMA, 2 for lacksDMA, or 3 for hasDMA: ";
while (cin >> kind && kind != '1' && kind != '2' && kind != '3')
cout <<"Wrong data. Please, try again: ";
while (cin.get() != '\n')
continue;
char tempLabel[LENGTH];
int tempRating;
cout << "Enter the label: ";
cin.getline(tempLabel, LENGTH - 1);
cout << "Enter the rating: ";
cin >> tempRating;
if (kind == '1') // baseDMA
pArr[i] = new baseDMA(tempDate, tempLabel, tempRating);
if (kind == '2') // lacksDMA
{
char tempColor[LENGTH];
cout << "Enter the color: ";
cin.getline(tempColor, LENGTH - 1);
pArr[i] = new lacksDMA(tempDate, tempLabel, tempColor, tempRating);
}
if (kind == '3') // hasDMA
{
char tempStyle[LENGTH];
cout << "Enter the style: ";
cin.getline(tempStyle, LENGTH - 1);
pArr[i] = new hasDMA(tempDate, tempLabel, tempStyle, tempRating);
}
while (cin.get() != '\n')
continue;
}
cout << "\n";
for (int i = 0; i < ELEMENTS; i++)
{
pArr[i]->View();
cout << "\n";
}
cout << "Done.\n";
std::cin.get();
return 0;
}
Sample execution:
Entering data for element #1
Enter the date it was created: 2012.01.01
Enter 1 for baseDMA, 2 for lacksDMA, or 3 for hasDMA: 2
Enter the label: lacksDMA
Enter the rating: 15
Enter the color: blue
Date of creation: 2012.01.01
Label: lacksDMA
Rating: 15
Color:
Done.
It seems the Color member gets assigned the null character. This behavior happens inside both the if (kind == '2') and if (kind == '3') statements (with the style member in this case).
If I put a cin.get(); just before cin.getline() it works fine but I have to press an extra key to make the program ask for input.
Why is this happening? If there was a '\n' pending in the input queue, cin.getline() would discard it and put '\0' in the variable, I can understand that. But the program asks me for the input for color and let's me enter it normally. Also, if I put a cin.get(), then the program shouldn't be waiting for an extra key stroke in the execution, it just should get rid of that extra '\n'. What am I missing here?
cout << "Enter the rating: ";
cin >> tempRating;
Unlike, istream::getline(), operator>> leaves the trailing \n in the stream. It causes the next call to getline inside one of your if statements to get empty input.
The stream is empty when control flow reaches while (cin.get() != '\n') statement at the end of for loop - it's waiting for input and it appears as if you're still inputing color.
Call cin.ignore() right after and it'll work.
Note that this kind of bug is immediately obvious if you put a "debugging cout" right after the input statement for color. There's one more issue with the way you're getting tempRating. If you enter invalid input, say "xy", the erros flags will be set on cin and the program will enter an infinite loop. Always check whether input operations suceeded.
If I put a cin.get(); just before cin.getline() it works fine but I have to press an extra key to make the program ask for input.
It seems to me that when you don't put the cin.get(), your getline is getting an empty character. Then, when you put the cin.get, you get that empty character and the your getline works fine..
But you should definitely go in debug to see exactly what's happening!
I'm just following a simple c++ tutorial on do/while loops and i seem to have copied exactly what was written in the tutorial but i'm not yielding the same results. This is my code:
int main()
{
int c=0;
int i=0;
int str;
do
{
cout << "Enter a num: \n";
cin >> i;
c = c + i;
cout << "Do you wan't to enter another num? y/n: \n";
cin >> str;
} while (c < 15);
cout << "The sum of the numbers are: " << c << endl;
system("pause");
return (0);
}
Right now, after 1 iteration, the loop just runs without asking for my inputs again and only calculating the sum with my first initial input for i.
However if i remove the second pair of cout/cin statements, the program works fine..
can someone spot my error please? thank you!
After you read the string with your cin >> str;, there's still a new-line sitting in the input buffer. When you execute cin >> i; in the next iteration, it reads the newline as if you just pressed enter without entering a number, so it doesn't wait for you to enter anything.
The usual cure is to put something like cin.ignore(100, '\n'); after you read the string. The 100 is more or less arbitrary -- it just limits the number of characters it'll skip.
If you change
int str;
to
char str;
Your loop works as you seem to intend (tested in Visual Studio 2010).
Although, you should also probably check for str == 'n', since they told you that they were done.
...and only calculating the sum with my first initial input for i...
This is an expected behavior, because you are just reading the str and not using it. If you enter i >= 15 then loop must break, otherwise continues.
I think you wanted this thing
In this case total sum c will be less than 15 and continue to sum if user inputs y.
#include<iostream>
using namespace std;
int main()
{
int c=0;
int i=0;
char str;
do
{
cout << "Enter a num: \n";
cin >> i;
c = c + i;
cout << "Do you wan't to enter another num? y/n: \n";
cin >> str;
} while (c < 15 && str=='y');
cout << "The sum of the numbers are: " << c << endl;
return 0;
}