首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >斯堪夫和斯特托克不适合我

斯堪夫和斯特托克不适合我
EN

Stack Overflow用户
提问于 2016-03-23 20:42:00
回答 3查看 615关注 0票数 0

我试着写一个基于菜单的小程序来保存记录。用户输入要存储的总人数(名、姓、分数)所用的数字。用户在一行中输入所有信息,用空格分隔,我将它们分成3列(名字、姓氏、分数),然后按enter键,然后继续输入更多信息,直到最大用户被击中为止。

我的问题是,当我运行它时,它不能正常工作;它运行并接受用户输入,但只对两个学生(即使我在测试用例中使用大于5的数字),然后程序立即结束(没有错误代码,只是结束.)甚至连菜单上都没有。有人能告诉我我的密码出了什么问题吗?

代码语言:javascript
运行
复制
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更改为fget

输出

代码语言:javascript
运行
复制
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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-03-23 20:54:34

一个问题是,您正在使用scanf()读取整个输入行,该输入行在名字、姓氏和等级之间有空格:

代码语言:javascript
运行
复制
for (i = 0; i < numberPeople; i++) {
    scanf("%s", tempArr);
}

scanf("%s", tempArr)一到达第一个空格就退出阅读。对于这个循环,您要使用fgets()

代码语言:javascript
运行
复制
for (i = 0; i < numberPeople; i++) {
    fgets(tempArr, 20, stdin);
}

但正如@Pooya所指出的,这个字符串的大小对于您所做的工作来说太小了。虽然您分配了学生和信息字段的二维数组,但从未分配字符串空间来保存他们的姓名和年级:

代码语言:javascript
运行
复制
char people[15][3]

如果在堆栈上执行此操作,则在概念上成为第三个维度:

代码语言:javascript
运行
复制
char people[15][3][24]

在这个scanf()之后,缓冲区中仍然保留一个返回字符:

代码语言:javascript
运行
复制
scanf("%d", &temp);

可能应该清空了。@KevinDTimm和@bruceg在这里暗示了一个问题:

代码语言:javascript
运行
复制
for (j = 0; j < 3; j++) {
    while (token != NULL) {
        people[i][j] = *token;

但我不认为Kevin的建议说明了j. @Weather_Vane建议在strtok()分隔符字符串中添加\r\n

代码语言:javascript
运行
复制
token = strtok(NULL, " ")

否则,您的等级字符串(最后一个字段)将有一个悬空的换行符。另外,您需要复制strtok()返回的令牌,不应该直接存储它。

将所有这些建议结合起来,并清理/修复我遇到的其他任何东西,我提供以下重做:

代码语言:javascript
运行
复制
#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;
}
票数 2
EN

Stack Overflow用户

发布于 2016-03-23 20:54:10

首先,使用fgets()而不是scanf()

接下来,您不需要由strtok处理的for strtok部件。相反,请使用以下内容:

代码语言:javascript
运行
复制
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, " ");
}
票数 0
EN

Stack Overflow用户

发布于 2016-03-23 20:56:32

根据您的示例,您的输入是关于24字符的,但是定义了tempArr[20]。因为如果扫描的不是20字符,而是覆盖内存中的其他内容,所以最好有tempArr[100]或对测试有意义的任何数字。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36188318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档