Я должен написать программу, которая печатает текст на псевдоанглийском языке, анализируя существующий текст на английском языке и просматривая последние две напечатанные буквы, чтобы определить, какой из них, вероятно, будет следующая (первая, которая представляется как '.' а также ' ').Для этой задачи я придумал следующий код:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
short characters[256][256][256];
int main(int argc, char* argv[]){
if(argc<2){
printf("In addition to the input file and maybe output file, please enter the number of output sentences as a command line argument.\n");
return 1;
}
/*Different approach where I malloced the array instead, same result*/
/*short ***characters=malloc(256 * sizeof(short**));
for(int i=0; i<256; i++){
*characters[i]=malloc(256 * sizeof(short*));
for(int i2=0; i2<256; i++){
characters[i][i2]=malloc(256 * sizeof(short**));
}
}*/
/*Read text*/
char a='.', /*pre-previous character*/
b=' ', /*previous character*/
c; /*current character*/
int n=0;
while((c=getchar())!=EOF){
characters[a][b][c]++;
a=b;
b=c;
n++;
}
/*Check how many sentences should be printed*/
int sentences=0, multiplier=1;
for(int i=0; i<sizeof(argv[1])/8; i++){
sentences+=argv[1][i]*multiplier;
multiplier*=10;
}
/*Print text*/
int currentsentences=0, random, p1, p2;
a='.';
b=' ';
while(currentsentences<sentences){
int uninitialized;
srand(time(0)+p1+p2+uninitialized); /*adds a bit of entropy*/
random=rand()%n;
p1=0;
for(int i=0; ; i++){
p2=p1+characters[a][b][i];
if(random>p1 && random<=p2){
c=characters[a][b][i];
p1+=characters[a][b][i];
break;
}
}
putchar(c);
if(c=='.' || c=='?' || c=='!')
currentsentences++;
a=b;
b=c;
}
return 0;
}
Он компилируется без ошибок и предупреждений, однако, когда я пытаюсь запустить эту программу, он всегда возвращает ошибку segfault перед печатью чего-либо, если я не делаю этого.недостаточно ввести достаточное количество аргументов командной строки, и в этом случае оно входит в первое предложение if.Вот почему я думаю, что он должен что-то делать с 3D-массивом, так как кажется, что он не может даже войти в первый цикл (если я позволю ему напечатать что-то до этого, это не будет).Он должен быть таким большим, так как структура выглядит следующим образом: [pre-previous letter][previous letter][current letter]=how often did this constellation occur
.Поскольку мне, вероятно, не понадобится более высокий ASCII и диапазона char
, вероятно, было бы достаточно, я попытался char
вместо short
и массив 128 * 128 * 128 - тот же результат.Запуск его от имени root не сильно изменился, и то же самое касается увеличения ulimit
.Однако не сохраняются ли глобальные переменные в куче?Использование malloc()
, которое я прокомментировал выше, также ничего не изменило.Я пробовал это на двух машинах, одна ОС: X, 64-битная и 8 ГБ DDR3, другая Linux Mint 19.1, 64-битная и 32 ГБ DDR4.И тот же результат, опять же (MacOS сказал segmentation fault: 11
, Linux сказал segmentation fault (core dumped)
).Поскольку используемая память этого массива составляет около 33 МБ, моя оперативная память также не может быть проблемой.Так почему же есть сегфо?Нужно ли выделять больше оперативной памяти для кучи (я не думаю, что это вообще возможно)?Может быть, это что-то, что не имеет отношения к массиву и / или его размеру?
Это последняя версия программы;все еще показывает то же поведение:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
short characters[256][256][256];
int main(int argc, char* argv[]){
/*Check if number of sentences was given*/
if(argc<2){
printf("In addition to the input file and maybe output file, please enter the number of output sentences as a command line argument.\n");
return 1;
}
/*Different approach with malloc*/
/*short ***characters=malloc(256 * sizeof(short**));
for(int i=0; i<256; i++){
*characters[i]=malloc(256 * sizeof(short*));
for(int i2=0; i2<256; i++){
characters[i][i2]=malloc(256 * sizeof(short**));
}
}*/
/*Read input text*/
int a='.', /*pre-previous character*/
b=' ', /*previous character*/
c; /*current character*/
int n=0;
for(; (c=getchar())!=EOF; n++){
characters[a][b][c]++;
a=b;
b=c;
}
/*Check how many sentences should be printed*/
int sentences=0, multiplier=1;
for(int i=strlen(argv[1])-1; i>=0; i--){
sentences+=(argv[1][i]-'0')*multiplier;
multiplier*=10;
}
/*Print text*/
int currentsentences=0, random, p1=0, p2=0;
a='.';
b=' ';
srand(time(0));
while(currentsentences<sentences){
random=(rand()+p1+p2)%n;
p1=0;
for(int i=0; i<256; i++){
p2=p1+characters[a][b][i]; /*Determine range for character*/
if(random>p1 && random<=p2){ /*Cheack if random number is in range of character*/
c=characters[a][b][i];
p1+=characters[a][b][i];
break;
}
}
putchar(c);
if(c=='.' || c=='?' || c=='!')
currentsentences++;
a=b;
b=c;
}
return 0;
}
ОБНОВЛЕНИЕ: Интересное поведение, которое он показывает, заключается в том, что, если вы добавите что-то вроде printf(„here“)
в самое начало программы, она выведет „here“
если первый if
оператор, если введен.Однако, если это не так, программа возвратит ошибку segf перед печатью чего-либо.
ОБНОВЛЕНИЕ 2: Интересно, что если вы не дадите входной файл и введете все вручную, она не вернет ошибку segfault, но такженикогда не заканчивай так же.
ОБНОВЛЕНИЕ 3: Программа теперь работает, см. Ниже.Извините за все проблемы, которые я вызвал, и спасибо за помощь.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
unsigned int characters[128][128][128];
int main(int argc, char* argv[]){
/*Check if input file was given*/
if(argc<2){
printf("Please enter an input file as command line argument.\n");
return 1;
}
/*Check for input file, open it*/
FILE *fp=NULL;
fp=fopen(argv[1], "r");
if(!fp){
printf("Error 404: Input file not found.\n");
return 404;
}
/*Read input text*/
int a='.'; /*pre-previous character*/
int b=' '; /*previous character*/
int c; /*current character*/
while((c=fgetc(fp))!=EOF){
if(c<127 && c>='\t'){ /*All characters from higher ASCII and system codes ignored. Still uses letters, digits and typical special characters and formatting characters.*/
characters[a][b][c]++;
a=b;
b=c;
}
}
fclose(fp);
/*Check how many sentences should be printed*/
unsigned int sentences;
printf("How many sentences do you want to be printed? ");
scanf("%d", &sentences);
/*Print text*/
unsigned int currentsentences=0, random, p1=0, p2=0, n;
a='.';
b=' ';
srand(time(0));
while(currentsentences<sentences){
n=0;
for(int i='\t'; i<127; i++){
n+=characters[a][b][i];
}
random=(rand()+p1+p2+sentences+currentsentences+clock())%n;
p1=0;
for(int i='\t'; i<127; i++){
p2=p1+characters[a][b][i]; /*Determine range for character in combination with line 58*/
if(random>=p1 && random<p2 && characters[a][b][i]!=0){ /*Check if random number is in range of character and that character occured in that combination*/
c=i;
printf("%c", c);
characters[a][b][c]++; /*Experimental, language will change over time pseudo-randomly*/
break;
}
p1+=characters[a][b][i];
}
if(c=='.' || c=='?' || c=='!')
currentsentences++;
a=b;
b=c;
}
printf("\n");
return 0;
}