堆栈在字符串和无限循环中粉碎

时间:2017-01-25 04:26:57

标签: c string loops segmentation-fault

  堆栈粉碎

陷入困境。 随机进入无限循环。 有时在第一次有时在第二次。 然而,代码是一团糟。逻辑是将一个字符串分成三个字符串或三次。

#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

          • split * * * * *

进入群组 2

mstr值 1 4 7 10 13 16 19 2 5 8 11 14 17 20 3 6 9 12 15 18 21

          • split * * * * *

进入群组 2

mstr值 1 4 7 10 13 16 19 2 5 8 11 14 17 20 3 6 2 5 8 11 14

          • split * * * * *

进入群组 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次。

3 个答案:

答案 0 :(得分:2)

你有几个基本问​​题。最糟糕的是,您没有使用'\0'个字符终止字符串。这导致未定义的行为。此外,您正在连接,例如strxstry。但是字符数组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()函数在每个字符串str1strxstry之间分发strz的内容,因此您可以将合并后的结果存储回{ {1}}。由于str1是指向str1的第一个元素的指针,因此更改在调用函数中可见。为实现此目的,需要将mstr[]的声明移至mstr[],并且组合字符串的代码应如下所示:

main()

这是修改后的代码,它或多或少地符合我的意图。我还添加了一些代码,在三次调用case 1: strcpy(str1,stry); strcat(str1,strx); strcat(str1,strz); 之后打印生成的数组:

split()

答案 1 :(得分:0)

在流程拆分中,您有j<=7,但它应该是j<7j<=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