1

我正在解决有关 USACO 的问题。在这个问题中,我必须将两个字符串作为输入并计算模数 47 的数值。如果值相同,则要打印 GO,否则必须打印 STAY。初始数值将通过取字母表的数值的乘积来计算(A 为 1,Z 为 26),然后使用模数计算最终数字。

我的程序正在编译,没有任何错误,并且在我的计算机上运行良好。但是,它显示分段错误作为分级计算机的执行错误。程序和输出如下:-

程序:-

#include<stdio.h>
#include<string.h>
main()
{
    int cal(char *ptr);
    char *comet,*group;
    int a,b;
    scanf("%s",comet);
    a=cal(comet);
    scanf("%s",group);
    b=cal(group);
    if(a==b)
        printf("GO");
    else
        printf("STAY");
    return 0;
}
int cal(char *ptr)
{
    int i=0,c,prod=1,mod;
    while(ptr[i]!='\0')
        {
            if(ptr[i]>='A'&&ptr[i]<='Z')
            {
                c=ptr[i]-'@';
                prod=prod*c;
                i++;
            }
        }
    mod=prod%47;
    return mod;
}

输出:-

在此处输入图像描述

我的问题是如何查明分段错误。我已阅读有关此故障的信息,但不知道在此程序中该做什么。任何帮助都会很棒。

4

5 回答 5

1
char *comet,*group;
int a,b;
scanf("%s",comet);

comet指针未初始化。您需要分配内存并comet在此分配的内存上做点,否则scanf将在随机位置写入字节,这可能会使您的系统崩溃。

于 2013-02-02T01:22:55.370 回答
1

comet您永远不会为or分配空间group。使用malloc()或类似方法为这些指针留出内存,以便您可以实际存储它们指向的内容。

#define MAX_STRING_LENGTH 256

...

char *comet, *group;
int a, b;

comet = NULL;
comet = malloc(MAX_STRING_LENGTH);
if (!comet) {
   fprintf(stderr, "ERROR: Could not allocate memory to comet\n");
   return EXIT_FAILURE;
}
scanf("%s",comet);

/* repeat for other pointers, as needed */

/* ... */

/* free up allocated memory at the end of the program to help prevent leaks */

free(comet);
comet = NULL;
于 2013-02-02T01:26:11.953 回答
1

comet 和 group 都是未初始化的指针,它们没有分配任何内存来存储输入字符串。

你的程序至少应该这样做。根据您的需要增加 MAX_STRING_SIZE 的大小。

#define MAX_STRING_SIZE 100
char comet[MAX_STRING_SIZE];
char group[MAX_STRING_SIZE];

scanf 仍然存在缓冲区溢出的风险。您可以查看这篇文章,了解避免缓冲区溢出的一些可能方法。

于 2013-02-02T01:26:50.120 回答
1

while的高度可疑:i仅当ptr[i]是大写字母时才增加。如果不是,应该怎么办?如果你有一个铁定的保证只有大写字母会出现,你可以写:

prod = 1;
while(*ptr) {
  prod *= *ptr - 'A' + 1;
  ptr++;
}

(在我破解 ascii(7) 之前,你ptr[i] - '@'让我摸不着头脑。我相信我的版本更清晰,任何能胜任一半的编译器都会给出相同的代码。)或者,更惯用:

int cal(char *ptr)
{
    int prod = 1;

    while(*ptr)
       prod *= *ptr++ - 'A' + 1;
    return prod % 47;
}

请注意产品不会溢出,也许对每个字符进行模数:

int cal(char *ptr)
{
    int prod = 1;

    while(*ptr) {
       prod *= *ptr++ - 'A' + 1;
       prod %= 47;
    }
    return prod;
}
于 2013-02-02T01:51:17.677 回答
0

“在我的计算机上运行良好”在您的情况下这是不可能的,因为您没有使用任何编译器特定的代码(例如 turbo c 的 getch)

您没有为存储字符串分配内存。指针 comet 和 group 不指向任何东西。scanf 需要一个地址来写入输入,但指针不包含地址,这就是您遇到分段错误的原因。您可以使用 malloc(或 calloc)分配内存,也可以定义字符数组。

更正后的代码是

#include<stdio.h>
#include<string.h>
#define MAXLENGTH 100
int main()
{
    int cal(char *ptr);
    char comet[MAXLENGTH],group[MAXLENGTH];
    int a,b;
    scanf("%s",comet);
    a=cal(comet);
    scanf("%s",group);
    b=cal(group);
    if(a==b)
        printf("GO");
    else
        printf("STAY");
    return 0;
}
int cal(char *ptr)
{
    int i=0,c,prod=1,mod;
    while(ptr[i]!='\0')
    {
        if(ptr[i]>='A'&&ptr[i]<='Z')
        {
            c=ptr[i]-'@';
            prod=prod*c;
            i++;
        }
    }
    mod=prod%47;
    return mod;
}
于 2013-02-02T02:05:17.430 回答