堆栈粉碎
陷入困境。 随机进入无限循环。 有时在第一次有时在第二次。 然而,代码是一团糟。逻辑是将一个字符串分成三个字符串或三次。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char mstr[21];
void split(char str1[21]);
void printx(char strxyz[7]);
void main()
{
int i,j,count=0;
char str[21];
for(i=1;i<=21;i++)
{
str[i-1]=i;
printf("%d\t",str[i-1]);
if(i%7==0)
{
printf("\n");
}
}
while(count<3)
{
split(str);
count++;
}
}
void split(char str1[21])
{
int i,j=0,k,ans,n;
char strx[7],stry[7],strz[7];
printf("\n\n* * * * * split * * * * *\n\n");
for(i=0;i<21;)
{
for(n=0;j<7;n++)
{
strx[j]=str1[i];i=i+1;
stry[j]=str1[i];i=i+1;
strz[j]=str1[i];i=i+1;
j=j+1;
}
}
printf("enter the group\n");
scanf("%d",&ans);
switch(ans)
{
case 1:
strcat(stry,strx);
strcat(stry,strz);
strcpy(mstr,stry);
break;
case 2:
strcat(strx,stry);
strcat(strx,strz);
strcpy(mstr,strx);
break;
case 3:
strcat(strx,strz);
strcat(strx,stry);
strcpy(mstr,strx);
break;
default:
printf("invalid\n");
}
printf("\n mstr values\n");
for(k=0;k<21;k++)
{
printf("%d\t",mstr[k]);
}
}
void printx(char strxyz[7])
{
int i;
printf("\n");
for(i=0;i<7;i++)
{
printf("%d\t",strxyz[i]);
}
}
第二次输出:
student @ CSE-LAB3:〜/ Desktop / fdrive $ cc shuffle.c student @ CSE-LAB3:〜/ Desktop / fdrive $ ./a.out
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
进入群组 2
mstr值 1 4 7 10 13 16 19 2 5 8 11 14 17 20 3 6 9 12 15 18 21
进入群组 2
mstr值 1 4 7 10 13 16 19 2 5 8 11 14 17 20 3 6 2 5 8 11 14
进入群组 1 分段错误(核心转储)
编辑:
the string
str = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
now we have to split the string into three.
so.
strx = 1 2 3 4 5 6 7
stry = 8 9 10 11 12 13 14
srtrz = 15 16 17 18 19 20 21
now based on the input (1 or 2 or 3 ) merge the string into a single string.
if the input is 1. place the string strx( first sub string ) in the middle. so it becomes
like stry+strx+strz
> output
> 1 4 7 10 13 16 19
> 2 5 8 11 14 17 20
> 3 6 9 12 15 18 21
逻辑: 想象一下现实生活中的问题。你有21张牌。你把它分成3堆7张牌。你问你的朋友想到三个堆栈中的一张卡片。然后你会问哪个堆栈有卡片。包含卡的堆栈放置在其他两个堆栈的中间并合并而不更改顺序。现在你必须将21张卡的堆叠分成7个卡堆栈。该过程重复3次,即他必须选择堆叠3次。
答案 0 :(得分:2)
你有几个基本问题。最糟糕的是,您没有使用'\0'
个字符终止字符串。这导致未定义的行为。此外,您正在连接,例如strx
到stry
。但是字符数组strx[]
中没有空间来容纳其他字符。
您可以通过将大小为21
的数组的所有声明更改为22
来修复这些问题,例如char mstr[22];
,并将大小为7
的数组的所有声明更改为8
,例如char strx[8];
。然后,您需要确保在每个字符串的末尾添加NUL
个终结符。实现此目的的一种方法是对每个阵列进行零初始化。另一种方法是显式添加NUL
字符,这就是我在下面的代码中所做的。
然后,您需要更改组合字符串的代码。此代码应将第一个子字符串复制到mstr[]
,然后连接下两个子字符串:
case 1:
strcpy(mstr,stry);
strcat(mstr,strx);
strcat(mstr,strz);
分割字符串的代码中也存在严重的逻辑错误。你拥有的双循环超出了数组范围。请注意,当i
到达20
时,您将拥有:strz[j]=str1[22];i=22+1;
,因为i
已经增加了两次。这应该简化为:
for(i=0, j=0; j < 7; j++, i += 3)
{
strx[j] = str1[i];
stry[j] = str1[i + 1];
strz[j] = str1[i + 2];
}
strx[j] = '\0';
stry[j] = '\0';
strz[j] = '\0';
听起来您希望保留每次调用split()
期间所做的更改,因此您应该从str[]
删除main()
,而在此处使用全局mstr[]
,因为这是你存储混洗结果的字符串。但是,完全删除全局会好得多,因为当你拥有时最好只使用全局变量。由于split()
函数在每个字符串str1
,strx
和stry
之间分发strz
的内容,因此您可以将合并后的结果存储回{ {1}}。由于str1
是指向str1
的第一个元素的指针,因此更改在调用函数中可见。为实现此目的,需要将mstr[]
的声明移至mstr[]
,并且组合字符串的代码应如下所示:
main()
这是修改后的代码,它或多或少地符合我的意图。我还添加了一些代码,在三次调用case 1:
strcpy(str1,stry);
strcat(str1,strx);
strcat(str1,strz);
之后打印生成的数组:
split()
答案 1 :(得分:0)
在流程拆分中,您有j<=7
,但它应该是j<7
或j<=6
,以防止越界问题。
答案 2 :(得分:0)
对我来说,可能存在未初始化的值或终止循环的错误条件。
我发现了一个问题,例如在函数中,
void split(char str1[21])
{
//i, k and n are later initialized but j is not.
int i,j,k,ans,n;
char strx[7],stry[7],strz[7];
printf("\n\n* * * * * split * * * * *\n\n");
for(i=0;i<21;)
{
//j is not initialized, how do you know compiler will initialize it to 0 for sure?
//j <= 7 should be j < 7
for(n=0;j<=7;n++)
{
strx[j]=str1[i];i=i+1;
stry[j]=str1[i];i=i+1;
strz[j]=str1[i];i=i+1;
j=j+1;
}
}
printf("enter the group\n");
scanf("%d",&ans);
switch(ans)
{
case 1:
strcat(stry,strx);
strcat(stry,strz);
strcpy(mstr,stry);
break;
case 2:
strcat(strx,stry);
strcat(strx,strz);
strcpy(mstr,strx);
break;
case 3:
strcat(strx,strz);
strcat(strx,stry);
strcpy(mstr,strx);
break;
default:
printf("invalid\n");
}
printf("\n mstr values\n");
for(k=0;k<21;k++)
{
printf("%d\t",mstr[k]);
}
}
如果没有初始化则声明j,然后在for循环中将其与7进行比较,其中n递增。每次启动程序时,它们都可以初始化为随机值。这就是为什么你可能会收到未定义的行为。 j <= 7
也应为j < 7