На онлайн-компиляторе эта программа дает идеальный вывод при вводе "ABACABA"
, но в тестах Codeforces он просто публикует последнюю строку. При отладке я обнаружил, что указатель u
указывает на адрес 0
когда strstr()
используется. Я не могу понять, почему функция работает на другом онлайн-компиляторе, но не на 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("%p\n",s);
}
else
{
break;
}
}
char *u=s;
int o=1;
//printf("%p\n",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 %p\n",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;
}
Как отмечалось в комментариях, основная проблема заключалась в том, что после прочтения строки вы не заканчивали нулем, что приводит к странным результатам. В частности, это приводит к тому, что вы вызываете неопределенное поведение, что всегда плохо. Память, выделенная malloc()
и дополнительная память, выделенная realloc()
не гарантируется обнуление.
Вы можете решить проблему, добавив:
s[count] = '\0';
прямо перед:
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);
Вы должны иметь в виду, что строка представляет собой серию символов, за которыми следует нулевой терминатор. Всякий раз, когда вы работаете с функциями, которые ожидают строки, вы должны убедиться, что присутствует нулевой терминатор.
Также будьте осторожны с такими строками, как strstr(t+o,str);
, Если o > strlen(t)
это вызывает неопределенное поведение. Вы должны сами проверить, что вы не выходите за пределы строки.