可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am working on a simple C program to make a multiple choice quiz to help my students prepare for their exams.
I used struct function. So far the program works fine
My questions:
Is there a way to use my current code below to generate questions randomly?
How would you suggest keeping track of percentage answered correctly?
(counter + for loop? while loop?
3) Is there anything I have done extremely inefficiently, can you recommend a solution?
I'm genuinely a beginner so please not to complicated explanation. Thank you
Here's the code:
#include <stdio.h>
struct question
{
char quiz[130]; // Question will be stored here
char answer1[20]; // Text for multiple choice possible answer 1
char answer2[20]; // Text for multiple choice possible answer 2 ..
char answer3[20];
char answer4[20];
int correctAnswer;
};
int main (){
struct question one={
"Que significa la palabra 'ser'\n",
"1. to do",
"2. to be",
"3. to make",
"4. to understand",
2,
};
printf ("%s %s %s %s %s\n",one.quiz,one.answer1,one.answer2,one.answer3,one.answer4);
scanf ("%d",&one.correctAnswer);
if (one.correctAnswer!=2){
printf("Equivocado! 'ser' significa: to be\n");
}
else {
printf ("Correcto\n");
}
struct question two={
"Que significa la palabra 'poder'\n",
"1. to do",
"2. to read",
"3. to make",
"4. to be able to",
4,
};
printf ("%s %s %s %s %s\n",two.quiz,two.answer1,two.answer2,two.answer3,two.answer4);
scanf ("%d",&two.correctAnswer);
if (two.correctAnswer!=4){
printf("Equivocado! 'ser' significa: to be able to\n");
}
else {
printf ("Correcto\n");
}
回答1:
You can create an array of each struct containing the question and answers and the correct answer. Randomly select an index in the array and print its contents. If an answer is correct just increase a variable like correct_answers++;
and keep track of the questions asked.
Calculating a percentage then just becomes (float)correct_answers/questions_asked *100
.
Writing the questions and answers into the C source by hand is a very inefficient(and slow!) way of encoding the data. I'm guessing reading from files is too advanced at the moment. But you should really look into it.
In the meantime, try the following template:
struct question
{
char quiz[130]; // Question will be stored here
char answer1[20]; // Text for multiple choice possible answer 1
char answer2[20]; // Text for multiple choice possible answer 2 ..
char answer3[20];
char answer4[20];
int correctAnswer;
};
struct question Questions[] = {
{
"Example questions",
"Option 1",
"other options",
...
/* Correct Answer */ 4
},
{
"Example question 2",
"Option 2_1",
"other options",
...
/* Correct Answer */ 2
},
};
回答2:
1) Yes, it's totally possible and easy!
2) correct, you can just loop through all of your questions and keep a counter of all of the correct one and then calculate the average.
3) You probably want to set all your data on one place, and then have your code run though all the questions using some generic way. You could do something like I did below.
Also, note, since you you are giving out questions in random order, it is possible to ask the same question more than once. I added a loop to keep trying to select random questions until you get a unique one.
There are multiple ways to solve this, one way would be to take that array of questions and randomize them before the loop. below is brute force for simplicity
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define arrsize(a) (sizeof(a) / sizeof(a[0]));
struct Question
{
char quiz[130]; // Question will be stored here
char answer1[20]; // Text for multiple choice possible answer 1
char answer2[20]; // Text for multiple choice possible answer 2 ..
char answer3[20];
char answer4[20];
int correctAnswer;
bool used;
};
static Question s_questions[] = {
{
"Que significa la palabra 'ser'\n",
"1. to do",
"2. to be",
"3. to make",
"4. to understand",
2,
false
},
{
"Que significa la palabra 'poder'\n",
"1. to do",
"2. to read",
"3. to make",
"4. to be able to",
4,
false
}
// Add more questions below this
};
int main () {
unsigned totalQuestions = arrsize(s_questions);
unsigned correct = 0;
// Set random seed
srand((unsigned)time(0));
for (unsigned i = 0; i < totalQuestions; ++i) {
// Loop over questions until you get a new one
unsigned curr = rand() % totalQuestions;
while (s_questions[curr].used == true) {
curr = rand() % totalQuestions;
}
s_questions[curr].used = true;
printf ("%s %s %s %s %s\n", s_questions[curr].quiz, s_questions[curr].answer1,s_questions[curr].answer2,s_questions[curr].answer3,s_questions[curr].answer4);
unsigned answer = 0;
scanf ("%d",&answer);
if (s_questions[curr].correctAnswer != answer){
printf("Equivocado!");
}
else {
printf ("Correcto\n");
correct++;
}
}
float percent = ((float)correct / (float)totalQuestions) * 100.0f;
printf ("Your average score was: %f\n", percent);
return 0;
}
回答3:
1)Is there a way to use my current code below to generate questions randomly?
You haven't explained what you mean by "randomly", whether you mean "unpredictably" (meaning a question could appear repeatedly, again and again) or "with relatively uniform frequency"... I'll assume you meant the latter. Though either way the answer is "yes", the latter of the two is probably easier because computers aren't very good at coming up with unpredictable data.
At the beginning of your program, you need to seed the pseudo-random generator. It's fairly common to use the time as a seed, like so: srand(time(NULL));
Now you can extract a pseudo-random number within the range of [0..RAND_MAX
] by calling rand()
. Assuming you have an array of struct question
named q
, you could reduce that number to within your range by using the modulo %
operator: rand() % range
. This will introduce a small amount of bias, but that's probably not a huge issue.
If it is an issue, you could discard any number that's greater than or equal to the multiple of range
:
int n;
do {
n = rand();
} while (RAND_MAX - n <= RAND_MAX % range);
I imagine you'll want to decrement range
as you ask questions, and move the questions asked from q
to beyond your range
to avoid asking them again. This leads in to your next question:
2) How would you suggest keeping track of percentage answered correctly? (counter + for loop? while loop?
You could set the correctAnswer
member of each question to 0
if incorrect or 1
if correct, loop over a
to count up the 1
s, then divide by the total number of questions... or you could keep a running tally of the number of correct answers as you're asking them. The less memory your program requires, the better, in my opinion. You could introduce that optimisation later if necessary.
3) Is there anything I have done extremely inefficiently, can you recommend a solution? I'm genuinely a beginner so please not to complicated explanation.
If there is, then you'll find it using your profiler when you've written the entire program... However, given the probability that you'll have a small number of questions (< 1000) and a recent computer to run it on (> y2k) this program should be fine.
回答4:
1) Yes, absolutely you can. There are many many different ways to do that. Here is one. Create an array of "struct question" and populate it with your question data, generate a random index, check if the indexed question has been used already, if yes continue generating random index, if no display the question and mark it used. Note that this is a deliberately simple algorithm and you can make it (much) more efficient.
2) You just need two counters: Number of questions asked and number of correct answers. This is independent of the need for a loop (the looping needs to occur regardless of whether you keep track of correct answer percentage).
3) IMHO it's better not to tackle that at this stage. Get your basic algorithm and implementation sorted out first. Especially in this Stackoverflow question as there's too much to cover all in one go (especially considering your solution is in flux).