字符串数组,并打印这些元素

时间:2016-11-11 23:53:08

标签: c arrays string structure

我正在尝试创建一个程序,该程序将从10名参赛者那里获取信息。该程序将获取并存储其名字,姓氏,年龄,性别(m / f)和比赛时间(hh:mm:ss)。为此,我计划为每个赛车手提供一系列结构,其中包含上述每个元素。然后我遇到了问“请输入第一个赛车手的名字”的问题,因为“第一个”这个词需要改为“第二个”,“第三个”等等...一个循环将无法去做。所以我决定然后创建一个字符串数组,其中数组的第一个元素是“first”,依此类推。那么我可以通过访问places数组的每个元素,使用循环为每个racer打印正确的单词。

我对字符串和字符串数组不太熟悉,我在网上搜索了一些帮助并提出了以下程序,它使用带指针的字符数组,我不太明白,必须是某些东西与字符串有关。无论如何,当我运行程序时,我遇到了严重的问题,必须重新打开Visual Studio。希望有人能帮助我,帮助澄清一些关于这些字符串数组和指针重要性的谜团。谢谢!

#include <stdio.h>
#include <math.h>

typedef struct DATASET
{
    char firstname[12], lastname[12], gender;
    int age, hours, minutes, seconds;
};

#define MaxRacers 10

int main()
{
    int i;
    DATASET data[MaxRacers];

    char *places[MaxRacers];

    char place1[6] = "First";
    char place2[7] = "Second";
    char place3[6] = "Third";
    char place4[7] = "Fourth";
    char place5[6] = "Fifth";
    char place6[6] = "Sixth";
    char place7[8] = "Seventh";
    char place8[7] = "Eighth";
    char place9[6] = "Ninth";
    char place10[6] = "Tenth";

    places[0] = place1;
    places[1] = place2;
    places[2] = place3;
    places[3] = place4;
    places[4] - place5;
    places[5] = place6;
    places[6] = place7;
    places[7] = place8;
    places[8] = place9;
    places[9] = place10;


    printf("%s", places[1]); // TEST which works fine

    for(i = 0, i < MaxRacers; i = i + 1;)
    {
        printf("Enter the name of the %s finisher\n", places[i]); // Problem
    }



    getchar();
    return(0);


}

现在我的事情变得更进一步了,我现在遇到一个问题,一旦我完成输入第一个终结者的姓氏,程序退出命令窗口,然后出现一个新窗口:

“ConsoleApplication30.exe中0x0FF6D0F1(ucrtbased.dll)抛出异常:0xC0000005:访问冲突写入位置0xFFFFFFCC。

如果存在此异常的处理程序,则可以安全地继续该程序。“

#include <stdio.h>
#include <math.h>

struct DATASET
{
    char firstname[12], lastname[12], gender;
    int age, hours, minutes, seconds;
};

#define MaxRacers 10

int main()
{
    int i;
    DATASET data[MaxRacers];

    char *places[] = { "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth", "Ninth", "Tenth" };


    for (i = 0; i < MaxRacers; i++)
    {
        printf("Enter the first name of the %s finisher:\n", places[i]);
        scanf("%s", data[i].firstname);
        printf("Enter the last name of the %s finisher:\n", places[i]);
        scanf("%s", data[i].lastname);
        printf("Enter the gender of the %s finisher: [m/f]: \n", places[i]);
        scanf("%c", data[i].gender);
        printf("Enter the age of the %s finisher:\n", places[i]);
        scanf("%d", data[i].age);
        printf("Enter the time of the %s finisher: [hh:mm:ss]\n", places[i]);
        scanf("%d:%d:%d", data[i].hours, data[i].minutes, data[i].seconds);
        printf("\n\n");
    }




    getchar();
    return(0);


}

2 个答案:

答案 0 :(得分:1)

for(i = 0, i < MaxRacers; i = i + 1;)

for循环不起作用。试试这个:

for(i = 0; i < MaxRacers; i++)
//       ^                  ^
//       |                  |
//      semicolon here     more idiomatic

此外,您应该使用惯用字符数组初始化:

char *places[MaxRacers] = { "First", "Second", ... };

不仅因为它比20行[{1}}更容易打字,而且因为错过错字的机会也少得多

places

虽然我们正在努力,

places[3] = place4;
places[4] - place5;   // <---- whoops
places[5] = place6;

没什么意义。它不会创建任何typedef名称,因此单词typedef struct DATASET { // whatever }; 是无用的。它相当于

typedef

因此,这个声明

struct DATASET
{ // whatever
};
C中的 无效。它在C ++中有效,这可能意味着您正在使用C ++编译器。如果您正在学习C,请确保您的源文件扩展名为DATASET data[MaxRacers];

答案 1 :(得分:1)

在此问题的第二次迭代中,您报告:

  

我输入第一个终结者的姓氏后立即遇到问题

我认为此问题是由于您错误地声明了data[]DATASETstruct,而不是typedef,因此您需要:

struct DATASET data[MaxRacers];

但这揭示了一个新问题。您对scanf()的来电有几个问题。首先,您未能提供地址以在多个实例中存储scanf()的结果。要解决此问题,您需要更改为:

printf("Enter the gender of the %s finisher: [m/f]: \n", places[i]);
scanf("%c", &data[i].gender);
printf("Enter the age of the %s finisher:\n", places[i]);
scanf("%d", &data[i].age);
printf("Enter the time of the %s finisher: [hh:mm:ss]\n", places[i]);
scanf("%d:%d:%d", &data[i].hours, &data[i].minutes, &data[i].seconds);

但现在又出现了另一个问题。 (邪恶)函数scanf()经常留下换行符和其他字符,污染输入流以用于下一个输入函数。 I personally usually write a function to handle user input in the form of strings,然后使用strtol()转换结果,如果需要数字输入。

最简单的事情是,在将scanf()%c说明符一起使用之前,只需编写一个函数来清除输入流:

void clear_stream(void)
{
    int ch;

    while ((ch = getchar()) != '\n' && ch != EOF)
        continue;                   // remove unwanted characters
}

然后像这样修改输入代码:

printf("Enter the first name of the %s finisher:\n", places[i]);
scanf("%s", data[i].firstname);
printf("Enter the last name of the %s finisher:\n", places[i]);
scanf("%s", data[i].lastname);
printf("Enter the gender of the %s finisher: [m/f]: \n", places[i]);
clear_stream();
scanf("%c", &data[i].gender);
printf("Enter the age of the %s finisher:\n", places[i]);
scanf("%d", &data[i].age);
printf("Enter the time of the %s finisher: [hh:mm:ss]\n", places[i]);
scanf("%d:%d:%d", &data[i].hours, &data[i].minutes, &data[i].seconds);
printf("\n\n");

对于许多格式说明符,scanf()会跳过前导空格,包括换行符。但是%c说明符不是这样,这意味着如果你输入一个字符串,那么输入流中留下的换行符将被拾取而不是你想要的字符。

这些更改将使您的代码运行。但是你的输入方案很脆弱。它不会检查是否存在输入(scanf()返回已读取的值的数量)并且它不验证值。您是否希望用户输入负年龄?我建议您至少重新考虑输入代码,以确保获得所需的输入。因为scanf()容易出错,所以你应该考虑使用fgets()或编写自己的输入函数,例如我之前链接的函数。