堆栈粉碎
陷入循环。随机进入一个无限循环。有时在第一时间,有时在第二时间。然而,代码是一团糟。逻辑是将一个字符串分成三个字符串,交替三次。
#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("%dt",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("nn* * * * * split * * * * *nn");
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 groupn");
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("invalidn");
}
printf("n mstr valuesn");
for(k=0;k<21;k++)
{
printf("%dt",mstr[k]);
}
}
void printx(char strxyz[7])
{
int i;
printf("n");
for(i=0;i<7;i++)
{
printf("%dt",strxyz[i]);
}
}
第二次输出:
student@CSE-LAB3:~/桌面/fdrive$cc shuffle.cstudent@CSE-LAB3:~/桌面/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 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张牌。你把它分成三堆7张牌。你让你的朋友从三叠卡片中想出一张。然后你问哪一张牌有。包含卡片的堆叠被放置在其他两个堆叠的中间,并在不改变顺序的情况下合并。现在你必须把21张牌分成7张牌。该过程重复3次,即他必须选择堆栈3次。
您有几个基本问题。最糟糕的是,您没有使用' '
字符终止字符串。这会导致未定义的行为。此外,您正在连接,例如,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] = ' ';
stry[j] = ' ';
strz[j] = ' ';
听起来你想保留每次调用split()
时所做的更改,所以你应该从main()
中删除str[]
,而在这里使用全局mstr[]
,因为这是你存储混洗结果的字符串。不过,完全删除全局要好得多,因为最好只在有时使用全局。由于split()
函数将str1
的内容分布在每个字符串strx
、stry
和strz
中,因此可以将组合结果存储回str1
中。由于str1
是指向mstr[]
的第一个元素的指针,因此在调用函数中可以看到更改。为了实现这一点,需要将mstr[]
的声明移动到main()
中,并且组合字符串的代码应该如下所示:
case 1:
strcpy(str1,stry);
strcat(str1,strx);
strcat(str1,strz);
这里是修改后的代码,它或多或少地实现了我认为您的意图。我还添加了一些代码来打印对split()
:进行三次调用后得到的数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void split(char str1[22]);
void printx(char strxyz[8]);
int main(void)
{
int i,count=0;
char mstr[22];
for(i=0;i<21;i++)
{
mstr[i]=i+1;
printf("%dt",mstr[i]);
if((i+1)%7==0)
{
printf("n");
}
}
mstr[i] = ' ';
while(count<3)
{
split(mstr);
count++;
}
printf("nResults:n");
for(i=0;i<21;i++)
{
printf("%dt",mstr[i]);
if((i+1)%7==0)
{
printf("n");
}
}
}
void split(char str1[22])
{
int i,j,k,ans;
char strx[8],stry[8],strz[8];
printf("nn* * * * * split * * * * *nn");
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] = ' ';
stry[j] = ' ';
strz[j] = ' ';
printf("enter the groupn");
scanf("%d",&ans);
switch(ans)
{
case 1:
strcpy(str1,stry);
strcat(str1,strx);
strcat(str1,strz);
break;
case 2:
strcpy(str1,strx);
strcat(str1,stry);
strcat(str1,strz);
break;
case 3:
strcpy(str1,strx);
strcat(str1,strz);
strcat(str1,stry);
break;
default:
printf("invalidn");
}
printf("n str1 valuesn");
for(k=0;k<21;k++)
{
printf("%dt",str1[k]);
}
}
void printx(char strxyz[8])
{
int i;
printf("n");
for(i=0;i<7;i++)
{
printf("%dt",strxyz[i]);
}
}
在过程拆分中,您有j<=7
,但它应该是j<7
或j<=6
,以防止越界问题。
在我看来,可能存在未初始化的值或终止循环的错误条件。
我发现了一个问题,例如在函数中
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("nn* * * * * split * * * * *nn");
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 groupn");
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("invalidn");
}
printf("n mstr valuesn");
for(k=0;k<21;k++)
{
printf("%dt",mstr[k]);
}
}
在没有初始化的情况下声明j,然后在for循环中将其与7进行比较,其中n递增。每次程序启动时,它们都可能被初始化为一个随机值。这就是为什么你可能会收到未定义的行为。此外,j <= 7
应为j < 7