【问题标题】:Program stops working after entering the value for more than 6 users输入超过 6 个用户的值后程序停止工作
【发布时间】:2019-12-29 12:50:56
【问题描述】:

我有一个学校项目,要求我使用结构和函数编写一个关于希腊城市销售的代码。系统会提示您输入 'em 的值。如果我输入有 6 个推销员,该程序就可以正常工作,但是大于该数字的数字会使它在输入所有值后停止。一个例子是:

业务员人数:7

(

  1. 输入他的身份证:

  2. 输入他的姓氏:

  3. 输入销售数量:

  4. 输入区号:

) x7 次。

然后,当您输入最后一个值时,它就会停止。不退出,不停止响应/崩溃,实际上只是停止,您将无法再输入任何内容,唯一的选择是退出。

问题是,构建消息和日志中都没有错误或警告,这让我很困惑。

我的猜测是错误出现在“calcSales”函数中,但我想发布整个代码,以防您需要更多信息。

您能否看一下代码并告诉我您是否发现任何问题?谢谢。

#include <stdio.h>
#include "genlib.h"
#include <simpio.h>
#include <string.h>
#define N 20
#define M 4

struct{
     int id;
     char surname[16];
     long sales;
     int area;
} salesmen[N];

void info(int *count);
void calcSales(int *count);

int main(){

     int count;

     printf("Give me the number of salesmen:\n");
     count=GetInteger();

     info(&count);

     calcSales(&count);
}

void info(int *count){

for (int i=0; i<*count; i++){
    printf("\nInfo for salesman number %d:\n", i+1);

    printf("\nGive me his id: ");
        salesmen[i].id=GetInteger();

    printf("\nGive me his surname: ");
        gets(salesmen[i].surname); 

    printf("\nGive me the number of sales: ");
        salesmen[i].sales=GetLong();

    printf("\n 1=Thessaloniki, 2= Athens, 3= Volos, 4= Hrakleio \n");
    printf("\nLastly, give me the number of his area: ");
        salesmen[i].area=GetInteger();

    if (salesmen[i].area>4){
        printf("\nThe number you are trying to enter doesn't match to an area.\n");
        break;
        }
    }
}

void calcSales(int *count){


    long tSales[4];
    for (int i=0; i<*count; i++){
    tSales[i]=0;
    }

for (int i=0; i<*count; i++){

    if(salesmen[i].area==1){
            tSales[0]+=salesmen[i].sales;
        }
    if(salesmen[i].area==2){
            tSales[1]+=salesmen[i].sales;
        }
    if(salesmen[i].area==3){
            tSales[2]+=salesmen[i].sales;
        }
    if(salesmen[i].area==4){
            tSales[3]+=salesmen[i].sales;
    }
}

for (int i=0; i<4; i++){
    printf("\nSales for area number %d: %ld\n",i+1, tSales[i]);
    }
}

【问题讨论】:

  • 查看tSales 中有多少元素,然后查看您在将其归零的循环中访问了多少元素。
  • 避免此问题的最佳方法是正确初始化数组 - long tSales[4] = {0}; - 而不是使用“先声明,然后分配”方法。
  • 最后一件事,请不要使用gets
  • @RahulBharadwaj,完全同意!它可能导致缓冲区溢出。但对于刚开始学习 C 的人来说,这有点高级。
  • @RahulBharadwaj 我们已经学会了 strncpy 和 get 但对我来说 get 似乎真的容易多了!你会说 strncpy 版本对初学者来说会更好,错误更少吗?

标签: c


【解决方案1】:

你的猜测是正确的。 calcSales函数中的错误。

没错,就是以下部分:

long tSales[4];
for (int i=0; i<*count; i++) {
        tSales[i]=0;
}

*count 的值为 20。这意味着循环从 i = 0 到 i = 19。 当您访问tSales[i] for i = 4 及以上时。您正在调用未定义的行为。这是您没有为 tSales 保留的记忆。我建议使用以下内容:

long tSales[4];
for (int i=0; i<4; i++) {
        tSales[i]=0;
}

或者更好:

long tSales[4];
for (int i=0; i<sizeof(tSales)/sizeof(tSales[0]); i++) { // number of elements is the total size of array divided by the size of one element.
        tSales[i]=0;
}

或者更好的是,您根本不需要循环:

long tSales[4] = {0};

除了你的问题:

对于您提供的代码,您不需要将指针传递给函数。

您可以使代码如下所示:

#include <stdio.h>
#include "genlib.h"
#include <simpio.h>
#include <string.h>
#define N 20
#define M 4

struct{
     int id;
     char surname[16];
     long sales;
     int area;
} salesmen[N];

void info(int count);
void calcSales(int count);

int main(){

     printf("Give me the number of salesmen:\n");
     int count=GetInteger(); // I've made declaration and assignment in same line. That seems cleaner to me.

     info(count);
     calcSales(count);
}

void info(int count){

    for (int i=0; i<count; i++){
        printf("\nInfo for salesman number %d:\n", i+1);

        printf("\nGive me his id: ");
        salesmen[i].id=GetInteger();

        printf("\nGive me his surname: ");
        gets(salesmen[i].surname); 

        printf("\nGive me the number of sales: ");
        salesmen[i].sales=GetLong();

        printf("\n 1=Thessaloniki, 2= Athens, 3= Volos, 4= Hrakleio \n");
        printf("\nLastly, give me the number of his area: ");
        salesmen[i].area=GetInteger();

        if (salesmen[i].area>4 || salesmen[i].area < 1){ // Added an extra condition.
            printf("\nThe number you are trying to enter doesn't match to an area.\n");
            break;
        }
    }
}

void calcSales(int count){

    long tSales[4] = {0};

    for (int i=0; i<count; i++){
            tSales[salesmen[i].area - 1]+=salesmen[i].sales; // No need for if conditions.
    }

    for (int i=0; i<4; i++){
        printf("\nSales for area number %d: %ld\n",i+1, tSales[i]);
    }
}

【讨论】:

  • 您好 Youssef13,您能否向 OP 显示 gets 部分的小替换代码(不使用 scanf)。
  • 非常感谢您帮助我解决它,同时也感谢您展示所有可能的方法。干杯!!
  • @RahulBharadwaj,就个人而言,我更喜欢使用 fgets。 scanf 和 gets 都不安全。 fgets 是安全的。其原因可以单独解释。但所有的事情都是关于缓冲区溢出
猜你喜欢
  • 1970-01-01
  • 2014-06-04
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 2020-05-08
  • 1970-01-01
相关资源
最近更新 更多