我正在尝试执行外观序列(wiki),但被卡住了。
我认为这些行是char数组。
首先,我通过数组line
进入for循环,找到“边界/差异”(在1211:1 | 2 | 11中),并在int数组diff
中将它们记为位置。然后,我计算count
并找出范围内的数字,并在新数组line_new
中记下它。然后,我需要将新数组line_new
复制到旧数组line
,这就是我认为问题所在。
我相信有更好的方法可以完全做到这一点,但我正在努力使其尽可能简单。
预期结果:
1
11
21
1211
111221
312211
实际结果:
1
11
21
1211 \\line_new
12 \\line
代码:
#include<stdio.h>
#include <string.h>
#define length(x) (sizeof(x) / sizeof((x)[0]))
void spocitej(int n){
int count = 1;
char line[] = {"21"};
char line_new[] = {" "};
int diff[] = {0};
char num;
int len, len_d;
int i, j, k, l, X, m;
printf("1\n");
printf("11\n");
printf("21\n");
for(i = 4; i < n; i++){
j = 0;
len = strlen(line)-1;
for(i = 0; i < len; i++){
if(line[i] != line[i+1]){
diff[j] = i;
j++;
}
}
len_d = length(diff);
l = 0;
for(k = 0; k < len_d; k++){
if(k == 0){
count = diff[k]+1;
num = line[0];
line_new[l] = count+'0';
line_new[l+1] = num;
l = l+2;
}else if(k!=0 && k!=len_d-1){
count = diff[k]-diff[k-1];
line_new[l] = count+'0';
line_new[l+1] = line[diff[k]];
l = l+2;
}
if(k == len_d-1){
count = (len - diff[k]);
num = line[len];
line_new[l] = count+'0';
line_new[l+1] = num;
line_new[l+2] = '\0';
}
}
puts(line_new);
// strcpy(line, line_new);
strncpy(line, line_new, sizeof(line_new));
puts(line);
printf("\n");
}
}
int main()
{
int n = 5;
spocitej(n);
fflush(stdin);
getchar();
return 0;
}
答案 0 :(得分:1)
阵列的大小可能与您预期的不一样
line
包含3个字符(以'2','1'和'\ 0'初始化)line_new
仅包含2个字符(以''和'\ 0'初始化)diff
仅包含1个int(用0初始化),一个数组无用,可以是int diff;
因此length(diff)
始终为1,实际上您将其放入循环中可能意味着您假设它已更改,但事实并非如此。
当您填充line_new
时,并不总是放置空字符终止符,因此puts(line_new);
可以继续从数组中移出,直到找到'\ 0',这是未指定的行为
如果 n 代表您计算的最大位数,则需要数组 n + 1 个字符,不仅是3个字符,而且是2个字符。但是我不确定目标是什么的 n ,因为您期望 n = 5
的 111221一个提案,第一个参数是第一个数字,第二个是循环数:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char ** argv)
{
if (argc != 3)
return -1;
int f = atoi(argv[1]); /* the first digit */
int n = atoi(argv[2]); /* the number of turn */
if ((f < 1) || (f > 9) || (n < 1))
return -1;
/* grow in length is like 30% per generation */
size_t maxsz = (int) pow(1.4, n+1) + 1;
/* the two arrays and their used size */
char * arr1 = malloc(maxsz);
char * arr2 = malloc(maxsz);
size_t sz1, sz2;
/* starting with 1 time first digit */
arr1[0] = f;
sz1 = 1;
while (n--) {
size_t i;
for (i = 0; i != sz1; ++i)
printf("%d", arr1[i]);
putchar('\n');
/* add a final not possible 10 to not have a special case for the last digit */
arr1[sz1] = 10;
sz2 = 0;
i = 1;
/* counts */
do {
arr2[sz2] = 1;
while (arr1[i] == arr1[i-1]) {
arr2[sz2] += 1;
i += 1;
}
arr2[sz2 + 1] = arr1[i-1];
sz2 += 2;
} while (++i <= sz1);
/* exchange role between arr1 and arr2 to avoid to copy arr2 into arr1 */
char * arr = arr1;
arr1 = arr2;
arr2 = arr;
sz1 = sz2;
}
free(arr1);
free(arr2);
return 0;
}
编译和执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -g cc.c -lm
pi@raspberrypi:/tmp $ ./a.out 1 1
1
pi@raspberrypi:/tmp $ ./a.out 1 2
1
11
pi@raspberrypi:/tmp $ ./a.out 1 3
1
11
21
pi@raspberrypi:/tmp $ ./a.out 1 4
1
11
21
1211
pi@raspberrypi:/tmp $ ./a.out 1 5
1
11
21
1211
111221
pi@raspberrypi:/tmp $ ./a.out 1 6
1
11
21
1211
111221
312211
pi@raspberrypi:/tmp $ ./a.out 1 10
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
pi@raspberrypi:/tmp $ ./a.out 3 10
3
13
1113
3113
132113
1113122113
311311222113
13211321322113
1113122113121113222113
31131122211311123113322113
在 valgrind
下执行pi@raspberrypi:/tmp $ valgrind ./a.out 1 20
==5026== Memcheck, a memory error detector
==5026== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5026== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==5026== Command: ./a.out 1 20
==5026==
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221
11131221131211131231121113112221121321132132211331222113112211
311311222113111231131112132112311321322112111312211312111322212311322113212221
132113213221133112132113311211131221121321131211132221123113112221131112311332111213211322211312113211
11131221131211132221232112111312212321123113112221121113122113111231133221121321132132211331121321231231121113122113322113111221131221
31131122211311123113321112131221123113112211121312211213211321322112311311222113311213212322211211131221131211132221232112111312111213111213211231131122212322211331222113112211
1321132132211331121321231231121113112221121321132122311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112311332111213122112311311123112111331121113122112132113213211121332212311322113212221
11131221131211132221232112111312111213111213211231132132211211131221131211221321123113213221123113112221131112311332211211131221131211132211121312211231131112311211232221121321132132211331121321231231121113112221121321133112132112312321123113112221121113122113121113123112112322111213211322211312113211
==5026==
==5026== HEAP SUMMARY:
==5026== in use at exit: 0 bytes in 0 blocks
==5026== total heap usage: 3 allocs, 3 frees, 3,368 bytes allocated
==5026==
==5026== All heap blocks were freed -- no leaks are possible
==5026==
==5026== For counts of detected and suppressed errors, rerun with: -v
==5026== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
答案 1 :(得分:1)
基于行21
,下一条要生成的行是1211
。要将这一行存储在计算机的内存中,需要4个字节作为可见字符,再加上1个字节作为终止NUL字符'\0'
。
在当前代码中,您将保留一个固定长度的数组,其中包含1个可见字符的空间以及结尾的'\0'
。这还不够。
您的代码将覆盖此数组及其后的内存,这将调用未定义的行为,并且可能会或可能不会导致您的程序现在或以后崩溃。在这方面,C是一种讨厌的编程语言。
可悲的是,C不提供任何数据结构,例如StringBuffer
或StringBuilder
,因此您必须自己做。基本成分是malloc
函数,该函数为您分配内存。一个安全的选择就是:
char *line_new = malloc(2 * strlen(line) + 1);
这给您足够的空间。当您不再需要此空间时,必须调用free(line_new)
,否则您的程序将很快耗尽计算机的所有内存。