C 无效结束问题 [英] C Void ending issue

查看:27
本文介绍了C 无效结束问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个简单的停车安排代码,我想按 1000 辆车、颜色、车牌和型号对容量进行排序

I am trying to write a simple parking arrangement code, I want to sort the capacity by 1000 vehicles, color, license plate and model

#include <stdio.h>
#include <stdlib.h>
void NewCar()
{
    char model[1000][20];
    char color [1000][20];
    char number[1000][20];
    int x = 1;
        printf("\nModel: ");
        scanf("%s",model[x]);
        printf("Color: ");
        scanf("%s",color[x]);
        printf("Number: ");
        scanf("%s",number[x]);
}
void CarList()
{
    int x;
    char model[1000][20];
    char color [1000][20];
    char number[1000][20];
    for (x ; x >= 1 ; x--)
    {
        printf("\n%d. Car: %s %s %s",x,number[x],model[x],color[x]);
    }
}
int main()
{
    char model[1000][20];
    char color [1000][20];
    char number[1000][20];
    char menu;
    int x = 1;
    flag:
    printf("New Car(N)\nCar List(L)\n");
    scanf("%s",&menu);
    if (menu == "n" || menu == "N")
    {
        NewCar();
        goto flag;
    }
    if (menu == "l" || menu == "L")
    {
        CarList();
        goto flag;
    }
}

当我不使用 void 时,代码可以工作,但我必须使用 void

when i don't use void, the code works but i have to use void

我想要的输出示例;

 1. Car Red Jeep FGX9425
 2. Car Yellow Truck OKT2637
 3. Car Green Sedan ADG4567
 ....

推荐答案

这是我最喜欢的评论的开头.

This is prefaced by my top comments.

从不使用goto.使用(例如)一个 while 循环.

Never use goto. Use (e.g.) a while loop.

menuscanf 会[可能] 溢出.

Your scanf for menu would [probably] overflow.

正如其他人所提到的,一些错误.

As others have mentioned, a number of bugs.

我已经用您的旧代码和一些新代码重构了您的代码.这仍然需要更多的错误检查,并且可以进行更多的概括,但是,我已经测试了它的基本功能:

I've refactored your code with your old code and some new code. This still needs more error checking and can be generalized a bit more, but, I've tested it for basic functionality:

#include <stdio.h>
#include <stdlib.h>

// description of a car
struct car {
    char model[20];
    char color[20];
    char number[20];
};

int
NewCar(struct car *cars,int carcount)
{
    struct car *car = &cars[carcount];

    printf("\nModel: ");
    scanf("%s", car->model);

    printf("\nColor: ");
    scanf("%s", car->color);

    printf("\nNumber: ");
    scanf("%s", car->number);

    ++carcount;

    return carcount;
}

void
CarList(struct car *cars,int carcount)
{
    struct car *car;
    int caridx;

    for (caridx = 0;  caridx < carcount;  ++caridx) {
        car = &cars[caridx];
        printf("%d. Car: %s %s %s\n",
            caridx + 1, car->number, car->model, car->color);
    }
}

int
main(int argc,char **argv)
{
#if 1
    int carcount = 0;
    struct car carlist[1000];
#endif
#if 0
    char menu;
    int x = 1;
#else
    char menu[20];
#endif

    // force out prompts
    setbuf(stdout,NULL);

    while (1) {
        printf("New Car(N)\nCar List(L)\n");
#if 0
        scanf("%s", &menu);
#else
        scanf(" %s", menu);
#endif

        // stop program
        if ((menu[0] == 'q') || (menu[0] == 'Q'))
            break;

        switch (menu[0]) {
        case 'n':
        case 'N':
            carcount = NewCar(carlist,carcount);
            break;

        case 'l':
        case 'L':
            CarList(carlist,carcount);
            break;
        }
    }

    return 0;
}

<小时>

更新:

如你所说,有一些小错误,对我来说不是问题,但是如果你想知道并修复它们,我可以写错误.(如果你写的板之间有空格,代码重复新车列表"命令多次)

As you said, there are a few minor errors, it's not a problem for me, but I can write errors if you want to know and fix them.(if you write the plate with a space between it, the code repeats the "new car car list" command many times)

好的,我制作了一个增强版本,用一个使用 fgets 的函数 askfor 替换了 scanf.后者将防止 [意外] 缓冲区溢出.而且,混合使用 scanf fgets 可能会有问题.就我个人而言,我总是使用 fgets 来滚动我自己的",因为它可以提供更精细的粒度控制 [如果与包装函数一起使用,例如这里提供的 askfor]

Okay, I've produced an enhanced version that replaces the scanf with a function askfor that uses fgets. The latter will prevent [accidental] buffer overflow. And, mixing scanf and fgets can be problematic. Personally, I always "roll my own" using fgets as it can provide finer grain control [if used with wrapper functions, such as the askfor provided here]

Per chux,我已经用使用 strchr 的更安全版本替换了 strlen 以删除换行符:

Per chux, I've replaced the strlen for removing newline with a safer version that uses strchr:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STRMAX      20

// description of a car
struct car {
    char model[STRMAX];
    char color[STRMAX];
    char number[STRMAX];
};

// askfor -- ask user for something
void
askfor(const char *tag,char *ptr)
{

    printf("Enter %s: ",tag);
    fflush(stdout);

    fgets(ptr,STRMAX,stdin);

    // point to last char in buffer
    // remove newline
#if 0
    ptr += strlen(ptr);
    --ptr;
    if (*ptr == '\n')
        *ptr = 0;
#else
    // remove trailing newline [if it exists]
    ptr = strchr(ptr,'\n');
    if (ptr != NULL)
        *ptr = 0;
#endif
}

int
NewCar(struct car *cars,int carcount)
{
    struct car *car = &cars[carcount];

    askfor("Model",car->model);
    askfor("Color",car->color);
    askfor("Number",car->number);

    ++carcount;

    return carcount;
}

void
CarList(struct car *cars,int carcount)
{
    struct car *car;
    int caridx;

    for (caridx = 0;  caridx < carcount;  ++caridx) {
        car = &cars[caridx];
        printf("%d. Car: %s %s %s\n",
            caridx + 1, car->number, car->model, car->color);
    }
}

int
main(int argc,char **argv)
{
    int carcount = 0;
    struct car carlist[1000];
    char menu[STRMAX];

    // force out prompts
    setbuf(stdout,NULL);

    while (1) {
        askfor("\nNew Car(N)\nCar List(L)",menu);

        // stop program
        if ((menu[0] == 'q') || (menu[0] == 'Q'))
            break;

        switch (menu[0]) {
        case 'n':
        case 'N':
            carcount = NewCar(carlist,carcount);
            break;

        case 'l':
        case 'L':
            CarList(carlist,carcount);
            break;
        }
    }

    return 0;
}

<小时>

更新 #2:

感谢您修复错误,但正如我在问题中所说,我必须使用 void 来实现新车"功能.你用 int 做的,你能用 void 做吗?

Thank you for your bug fix, but as I said in my question, I have to do the "New car" feature using void. You did it with int, can you do it with void?

好的.当您说使用 void"时,我 [或其他一些人] 并不完全清楚您的意思.存在足够多的错误,它们掩盖了其他一些考虑因素.

Okay. When you said "using void", what you meant wasn't totally clear to me [or some others]. There were enough bugs that they overshadowed some other considerations.

所以,我必须假设使用 void"意味着函数返回 void.

So, I have to assume that "using void" means that the functions return void.

您的原始函数定义为 void NewCar()void CarList().那些无法按原样完成工作,因此必须对其进行更改.

Your original functions were defined as void NewCar() and void CarList(). Those could not have done the job as is, so they had to be changed.

如果你有类似的标准,更好的表达方式是:

If you have similar criteria, a better way to phrase that would be:

我必须创建两个函数,具有以下函数签名...

I must create two functions, with the following function signatures ...

无论如何,这是更新后的代码:

Anyway, here's the updated code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STRMAX      20

// description of a car
struct car {
    char model[STRMAX];
    char color[STRMAX];
    char number[STRMAX];
};

// askfor -- ask user for something
void
askfor(const char *tag,char *ptr)
{

    printf("Enter %s: ",tag);
    fflush(stdout);

    fgets(ptr,STRMAX,stdin);

    // remove trailing newline [if it exists]
    ptr = strchr(ptr,'\n');
    if (ptr != NULL)
        *ptr = 0;
}

void
NewCar(struct car *cars,int *countptr)
{
    int carcount = *countptr;
    struct car *car = &cars[carcount];

    askfor("Model",car->model);
    askfor("Color",car->color);
    askfor("Number",car->number);

    carcount += 1;
    *countptr = carcount;
}

void
CarList(struct car *cars,int carcount)
{
    struct car *car;
    int caridx;

    for (caridx = 0;  caridx < carcount;  ++caridx) {
        car = &cars[caridx];
        printf("%d. Car: %s %s %s\n",
            caridx + 1, car->number, car->model, car->color);
    }
}

int
main(int argc,char **argv)
{
    int carcount = 0;
    struct car carlist[1000];
    char menu[STRMAX];

    // force out prompts
    setbuf(stdout,NULL);

    while (1) {
        askfor("\nNew Car(N)\nCar List(L)",menu);

        // stop program
        if ((menu[0] == 'q') || (menu[0] == 'Q'))
            break;

        switch (menu[0]) {
        case 'n':
        case 'N':
#if 0
            carcount = NewCar(carlist,carcount);
#else
            NewCar(carlist,&carcount);
#endif
            break;

        case 'l':
        case 'L':
            CarList(carlist,carcount);
            break;
        }
    }

    return 0;
}

但是,鉴于您的原始函数,签名必须可能是:void NewCar(void)void CarList(void) 并且汽车列表变量必须是全局范围.

However, given your original functions, it may be possible that the signatures have to be: void NewCar(void) and void CarList(void) and that the car list variables must be global scope.

这将是一种不太灵活和理想的做事方式,但这里有一个仅使用列表全局变量的版本:

This would be a less flexible and desirable way to do things, but here is a version that uses only global variables for the lists:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STRMAX      20

// description of a car
struct car {
    char model[STRMAX];
    char color[STRMAX];
    char number[STRMAX];
};

#if 1
int carcount = 0;
struct car carlist[1000];
#endif

// askfor -- ask user for something
void
askfor(const char *tag,char *ptr)
{

    printf("Enter %s: ",tag);
    fflush(stdout);

    fgets(ptr,STRMAX,stdin);

    // remove trailing newline [if it exists]
    ptr = strchr(ptr,'\n');
    if (ptr != NULL)
        *ptr = 0;
}

void
NewCar(void)
{
    struct car *car = &carlist[carcount];

    askfor("Model",car->model);
    askfor("Color",car->color);
    askfor("Number",car->number);

    carcount += 1;
}

void
CarList(void)
{
    struct car *car;
    int caridx;

    for (caridx = 0;  caridx < carcount;  ++caridx) {
        car = &carlist[caridx];
        printf("%d. Car: %s %s %s\n",
            caridx + 1, car->number, car->model, car->color);
    }
}

int
main(int argc,char **argv)
{
#if 0
    int carcount = 0;
    struct car carlist[1000];
#endif
    char menu[STRMAX];

    // force out prompts
    setbuf(stdout,NULL);

    while (1) {
        askfor("\nNew Car(N)\nCar List(L)",menu);

        // stop program
        if ((menu[0] == 'q') || (menu[0] == 'Q'))
            break;

        switch (menu[0]) {
        case 'n':
        case 'N':
#if 0
            carcount = NewCar(carlist,carcount);
#else
            NewCar();
#endif
            break;

        case 'l':
        case 'L':
#if 0
            CarList(carlist,carcount);
#else
            CarList();
#endif
            break;
        }
    }

    return 0;
}

这篇关于C 无效结束问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆