我试图编写一个基于小菜单的程序来维护记录。 用户输入要用于存储的总人数的数字(名字,姓氏,分数)。用户在一行中输入信息,用空格分隔,然后我将它们分成3列(名字,姓氏,分数),然后按Enter键继续输入更多信息,直到最大人数被击中。
我的问题是,当我运行它时,它不能正常工作;它运行并接受用户输入,但仅限于两个学生(即使我已经使用大于5的数字用于测试用例),然后程序立即结束(没有错误代码,只是结束...)并且它没有&甚至可以进入菜单。有人能告诉我我的代码有什么问题吗?
int i, j, count, numberPeople, temp, choice;
char people[15][3], tempArr[20];
char *token;
printf("Please indicate number of records you want to enter (min 5, max 15): ");
scanf("%d", &temp);
while ((temp > 15) || (temp < 5)) {
printf("\nNumber not in specified range, try again.\n");
printf("Please indicate number of records you want to enter (min 5, max 15): ");
scanf("%d", &temp);
}
numberPeople = temp;
printf("\nEnter the first name, last name, and grade (put a space in between each): ");
for (i = 0; i < numberPeople; i++) {
fgets(tempArr, 20, stdin);
token = strtok(tempArr, " ");
for (j = 0; j < 3; j++) {
while (token != NULL) {
people[i][j] = *token;
printf("%s\n", token); // this is here to as a test case to see if my data was being stored.
token = strtok(NULL, " ");
}
}
}
已编辑:将scanf更改为fgets
输出
Please indicate number of records you want to enter (min 5, max 15): 5
Enter the first name, last name, and grade (put a space in between each): firstname1 lastname1 85
firstname1
lastname1
85
firstname2 lastname2 84
firstname2
lastname2
Program ended with exit code: 0
答案 0 :(得分:2)
一个问题是你使用scanf()
读取整个输入行,其中包含名字,姓氏和等级之间的空格:
for (i = 0; i < numberPeople; i++) {
scanf("%s", tempArr);
}
scanf("%s", tempArr)
一击到第一个空格就会退出。对于此循环,您要使用fgets()
:
for (i = 0; i < numberPeople; i++) {
fgets(tempArr, 20, stdin);
}
但正如@Pooya所说,这个字符串大小对于你正在做的事情来说太小了。虽然您分配了学生和信息字段的二维数组,但您永远不会分配字符串空间来保存其姓名和成绩:
char people[15][3]
如果您在堆栈中执行此操作,它在概念上将成为第三个维度:
char people[15][3][24]
在scanf()
之后,缓冲区中仍然有一个返回字符:
scanf("%d", &temp);
它可能应该被清除掉。 @KevinDTimm和@bruceg在这里暗示了一个问题:
for (j = 0; j < 3; j++) {
while (token != NULL) {
people[i][j] = *token;
但我不认为凯文的建议是指数j。 @Weather_Vane建议将\r\n
添加到strtok()
分隔符字符串:
token = strtok(NULL, " ")
否则您的成绩字符串(最后一个字段)将有一个悬空换行符。此外,您需要制作strtok()
返回的令牌的副本,您不应该直接存储它。
将所有这些建议放在一起并清理/修复我遇到的任何其他内容,我提供以下返工:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINIMUM_STUDENTS 5
#define MAXIMUM_STUDENTS 15
#define DATA_FIELDS 3
#define MAXIMUM_LINE_LENGTH 100
#define MAXIMUM_DATA_LENGTH 50
int main(int argc, char **argv) {
int numberPeople;
char people[MAXIMUM_STUDENTS][DATA_FIELDS][MAXIMUM_DATA_LENGTH];
printf("Please indicate number of records you want to enter (min %d, max %d): ", MINIMUM_STUDENTS, MAXIMUM_STUDENTS);
scanf("%d", &numberPeople);
while ((numberPeople < MINIMUM_STUDENTS) || (numberPeople > MAXIMUM_STUDENTS)) {
printf("\nNumber not in specified range, try again.\n");
printf("Please indicate number of records you want to enter (min %d, max %d): ", MINIMUM_STUDENTS, MAXIMUM_STUDENTS);
scanf("%d", &numberPeople);
}
printf("\n");
while ((getchar()) != '\n'); // flush the return (and anything else) after the number input above
printf("Enter the first name, last name, and grade (put a space in between each): \n");
for (int i = 0; i < numberPeople; i++) {
char tempArr[MAXIMUM_LINE_LENGTH];
fgets(tempArr, MAXIMUM_LINE_LENGTH, stdin);
char *token = strtok(tempArr, " ");
for (int j = 0; j < DATA_FIELDS && token != NULL; j++) {
strncpy(people[i][j], token, MAXIMUM_DATA_LENGTH);
// this is here to as a test case to see if my data was being stored.
printf("%s\n", people[i][j]);
token = strtok(NULL, " \r\n");
}
}
// do what you need to do with the data here!
return 0;
}
答案 1 :(得分:0)
首先,请使用fgets()
而不是scanf()
接下来,您不需要由(j=0; j<3; j++)
处理的strtok
部分。而是使用以下内容:
token = strtok(tempArr, " ");
while (token != NULL) {
people[i][j] = *token;
printf("%s\n", token); // this is here to as a test case to see if my data was being stored.
token = strtok(NULL, " ");
}
答案 2 :(得分:0)
根据您的示例,您的输入大约需要24
个字符,但您定义了tempArr[20]
。因为如果您扫描超过20
个字符的内容,则会覆盖内存中的其他内容,最好使用tempArr[100]
或任何对您的测试有意义的数字。