从另一个函数复制时C strcpy分段错误[duplicate]

k4emjkb1  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(99)

此问题在此处已有答案

Segmentation fault when returning pointers [duplicate](1个答案)
9天前关闭。
这是我在大学编程课上做的一个项目的代码片段,我的问题是,当我到达strcpy部分时,我得到了一个分段错误,我不知道为什么。
我不知道这是否相关,但我在linux下用vs代码编码。
代码如下:

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

typedef struct Teams {
    char country[20];
    char sponsor[20];
    char group;
    int points;
} E;

char *sponsor_generator(char *country) {
    int i, k = 0;
    char sp[20];
    for (i = strlen(country) - 1; i >= 0; i--) {
        sp[k] = country[i];
        k++;
    }
    sp[k] = '\0';
    return sp;
}

void read(E *ec, int *n) {
    (*n)++;
    printf("Country: ");
    scanf("%s", (ec + *n)->country);
    (ec + *n)->group = (ec + *n)->country[0];
    do {
        printf("Number of points: ");
        scanf("%d", &(ec + *n)->points);
    } while ((ec + *n)->points >= 10);

    strcpy((ec + *n)->sponsor, sponsor_generator((ec + *n)->country));
}

int main() {
    int n = -1;
    E ec[64];
    read(ec, &n);
    return 0;
}

我试着查找任何解决方案,但我没有找到任何可行的方法。

oug3syen

oug3syen1#

您的代码中存在多个问题:

  • 函数sponsor_generator返回一个指向本地数组的指针,该指针在函数返回后立即变为无效。sponsor_generator应将目标数组作为参数。
  • 将下一个函数命名为read可能与使用相同名称的POSIX系统调用冲突。请使用其他名称。
  • 如果输入超过19个字符,scanf("%s", (ec + *n)->country);可能会导致缓冲区溢出。请始终指定限制并测试返回值:
if (scanf("%19s", (ec + *n)->country) != 1) {
      printf("premature end of file\n");
      exit(1);  // or return an error code to the caller
  }
  • 使用数组语法会使代码更可读。
  • 将类型命名为E是个坏主意:使用结构标签Team将提高可读性。
  • 传递数组元素的地址并依赖函数返回值来增加条目的数量简化了代码。

以下是修改后的版本:

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

typedef struct Team {
    char country[20];
    char sponsor[20];
    char group;
    int points;
} Team;

char *sponsor_generator(char *sp, const char *country) {
    int i, k;
    for (i = strlen(country), k = 0; i-- > 0; k++) {
        sp[k] = country[i];
    }
    sp[k] = '\0';
    return sp;
}

/* flush the remainder of the input line:
   return EOF at end of file or on read error
   return '\n' otherwise
 */
int flush_line(FILE *fp) {
    int c;
    while ((c = getc(fp)) != EOF && c != '\n')
        continue;
    return c;
}

int read_team(Team *team) {
    int c, points, res;

    printf("Country: ");
    res = scanf("%19s", team->country);
    flush_line(stdin);
    if (res != 1) {
        return -1;
    }

    for (;;) {
        printf("Number of points: ");
        res = scanf("%d", &points);
        c = flush_line(stdin);
        if (res != 1) {
            printf("invalid input\n");
            if (c == EOF) {
                return -1;
            }
        } else {
            if (points >= 0 && points < 10)
                break;
            printf("number of points must be between 0 and 9\n");
        }
    }
    team->points = points;
    team->group = team->country[0];
    sponsor_generator(team->sponsor, team->country);
    return 0;
}

void print_team(const Team *team) {
    printf("country: %s, sponsor: %s, group: %c, points: %d\n",
           team->country, team->sponsor, team->group, team->points);
}

int main() {
    Team ec[64];
    int n;

    for (n = 0; n < 64; n++) {
        if (read_team(&ec[n]) < 0) {
            printf("premature end of file\n");
            break;
        }
    }
    for (int i = 0; i < n; i++) {
        print_team(&ec[n]);
    }
    return 0;
}

相关问题