在在线编译器上,该程序在输入"ABACABA"
时给出了完美的输出,但在Codeforces测试中,它只是发布了最后一行。在调试中,我发现当使用strstr()
时,指针u
指示地址0
。我无法理解为什么该函数在其他在线编译器上工作,而不是在Codeforces上。
编辑:好吧,所以感谢@Jeremy Friesner,我发现它实际上是strncpy不能正常工作,因为现在自定义测试用例编译器正在为'str'提供错误的输出。仍然不知道为什么它在两个不同的编译器上的行为会不同,我应该做什么改变。
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<stdlib.h>
using namespace std;
int main()
{
char *s;
int length=20;
s = (char *) malloc(length*(sizeof(char)));
char c;
int count=0;
while((c=getchar())>='A')
{
if(c<='Z')
{
//cout<<count;
if(length>=count)
{
s = (char *) realloc(s,(length+=10)*sizeof(char));
}
s[count++]=c;
//printf("%pn",s);
}
else
{
break;
}
}
char *u=s;
int o=1;
//printf("%pn",s);
while(u)
{
char *str = (char *) malloc(o*sizeof(char));
str = strncpy(str,s,o);
//cout<<str<<endl;
char *t;
u = strstr(s+1,str);
//printf("u %pn",u);
t=u;
int ct=0;
char *p;
while(t)
{
ct++;
p=t;
t = strstr(t+o,str);
}
ct=ct+1;
//cout<<"here"<<endl;
if(p==(s+count-o))
{
cout<<o<<" "<<ct<<endl;
}
//cout<<ct<<endl;
o++;
}
cout<<count<<" "<<1;
}
正如在注释中所指出的,一个主要问题是在读入字符串后没有以null结束,这会导致奇怪的结果。具体来说,它会导致您调用未定义行为,这总是一件坏事。malloc()
分配的内存和realloc()
分配的额外内存不能保证为零。
你可以通过添加:
来解决这个问题s[count] = ' ';
:前char *u = s;
严格地说,您还应该检查malloc()
和realloc()
的返回值。另外,您不应该使用以下习语:
x = realloc(x, newsize);
如果realloc()
失败,你丢失了指向原始数据的指针,所以你泄露了内存。安全的工作方式是:
void *space = realloc(x, newsize);
if (space == 0)
…report error etc…
x = space;
x_size = newsize;
可能还有其他问题;我没有仔细检查代码中的每个可能的问题。
不能在s
中输入的字符后面加上空终止符,因此s
不包含字符串。因此,它会导致未定义行为将其传递给期望字符串的函数,例如strncpy
。
另一个大问题是你对strncpy
的使用。
int o=1;
while(u)
{
char *str = (char *) malloc(o*sizeof(char));
str = strncpy(str,s,o);
u = strstr(s+1,str);
strncpy
函数不创建字符串,如果strlen(s) >= o
。在这种情况下,strstr
函数将只读取缓冲区的末尾,从而导致未定义的行为。(具体会发生什么取决于你的编译器和这块内存中是什么垃圾)
您需要在str
中放入一个以空结束的字符串。手动添加一个空终止符:
assert(o > 0);
strncpy(str, s, o-1);
str[o-1] = 0;
或者使用不同的函数:
snprintf(str, o, "%s", s);
您必须记住,字符串是一系列字符后跟一个空结束符。当您使用需要字符串的函数时,您需要确保null终止符的存在。
也要小心strstr(t+o,str);
这样的行。如果o > strlen(t)
,这将导致未定义的行为。你必须自己检查你没有超出字符串的边界