我目前是C学生的导师。在他的课程中,大学安装了一台运行Mooshak的服务器(一种能够接收代码并对其进行测试的软件)。
我们开发了一个代码,编译并在发送到服务器之前在本地进行了测试,一切都很顺利。但是,当我们尝试将其发送到服务器时,服务器声明"超出内存限制"。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <string.h>
#define LIMITE_CARACTERES 1000
#define LIMITE_GENES 100000
char genes[LIMITE_GENES][LIMITE_CARACTERES];
char* copiar_por_espaco(char* string, char* dest)
{
for(int i = 0; i < strlen(string); i++)
{
if(' ' == string[i])
{
strncpy(dest, string, i);
dest[i] ='\0';
if( i + 1 >= strlen(string))
return NULL;
else
return &string[i+1];
}
}
if(strlen(string) == 0)
{
return NULL;
}
else
{
strcpy(dest, string);
return NULL;
}
}
void genes_f()
{
char s[LIMITE_CARACTERES];
int numero_genes = 0;
while(scanf("%s", s) != EOF)
{
char *auxiliar = s;
while(auxiliar != NULL && strlen(auxiliar) != 0)
{
auxiliar = copiar_por_espaco(auxiliar, genes[numero_genes]);
numero_genes++;
}
}
if(numero_genes <= 20)
{
for(int i = 0; i < numero_genes; i++)
{
printf("%s\n", genes[i]);
}
}
else
{
for(int i = 0; i < 10; i++)
{
printf("%s\n", genes[i]);
}
for(int i = numero_genes - 10; i < numero_genes;i++)
{
printf("%s\n", genes[i]);
}
}
}
int main()
{
genes_f();
return 0;
}
请注意,值LIMITE_CARACTERES和LIMITE_GENES是一项分配要求(尚未告知有关内存分配的信息)。上面的代码给出了超过内存限制&#34;但如果我将第一个分成两行,服务器不会抛出该错误并接受我们的解决方案:
char* copiar_por_espaco(char* string, char* dest)
{
int len = strlen(string); //This line was taken out from the for
for(int i = 0; i < len; i++) //Now we used the variable instead
{
if(' ' == string[i])
{
strncpy(dest, string, i);
dest[i] ='\0';
if( i + 1 >= strlen(string))
return NULL;
else
return &string[i+1];
}
}
if(strlen(string) == 0)
{
return NULL;
}
else
{
strcpy(dest, string);
return NULL;
}
}
我不知道为什么。有人对此有解释吗?
编辑:在工作函数中添加注释,以便轻松发现唯一的更改。
编辑2:输入将有几行带有单词(应跳过空白行),用空格分隔。该计划应该分开并采用每个词:
输入
A BDD TES QURJ
test dog cat heart
cow
bird tree
输出
A
BDD
TES
QURJ
test
dog
cat
heart
cow
bird
tree
答案 0 :(得分:2)
您忘记在数组中包含空终止符的额外字节。如果LIMITE_CARACTERES
是作为输入提供的字符串的最大长度,那么您需要一个大小为LIMITE_CARACTERES + 1
的数组来存储它。所以你需要改变这一行
char genes[LIMITE_GENES][LIMITE_CARACTERES];
到
char genes[LIMITE_GENES][LIMITE_CARACTERES + 1];
答案 1 :(得分:1)
由于您是导师,我会提供反馈,以便您可以正确地教导您的学生(因此这不是您问题的答案)。
<强> copiar_por_espaco 强>
for(int i = 0; i < strlen(string); i++)
对循环中没有变化的变量重复调用strlen
是浪费CPU周期。实际上,您应该在循环之前计算长度并在循环中使用它。这也适用于if( i + 1 >= strlen(string))
if(' ' == string[i])...
请注意,保证字符串不包含空格,因为它是使用scanf
读取的。因此,该函数将始终返回NULL
。
if(strlen(string) == 0) return NULL;
你在循环之后测试它,但逻辑规定你在任何处理之前执行此操作并且可以缩短为if (!*string) return NULL;
这也会使代码更加美观,因为不需要else
部分(它不管怎样都不需要。)
<强> genes_f 强>
while(scanf("%s", s) != EOF)
scanf-guru可能在这里有所帮助,但我相信格式说明符中必须有一个空格,因此它将跳过前导空格" %s"
。我相信你的方式只会读取一个字符串,然后在每次scanf
调用时无限循环返回零。您应该测试scanf的结果,以获取格式说明符成功转换的数量,而不是EOF。因此,请检查1
。
if(numero_genes <= 20)
你的印刷很有趣。这一切都可以作为一个循环:
for(int i = numero_genes; i < numero_genes; i++)
printf("%s\n", genes[i]);
你必须对你的基因数进行边界检查:
numero_genes<LIMITE_GENES