C:与for循环交错?

时间:2014-01-25 20:25:11

标签: c

我需要创建一个程序,要求用户输入一个字符串然后在程序中的函数需要将它分成2个相同大小的字符串(用户总是输入偶数个字符),然后它必须“洗牌” “他们......

所以基本上应该这样做:

user inputs: A1B1C1D1

代码应该生成两个大小相同的字符串:A1B1C1D1,之后应该将它们“洗牌”,如下所示:A1C1B1D1

所以它需要取第一个字符串的前2个元素,然后是第二个字符串的前2个元素,依此类推......

我的问题是,当我输入A1B1C1D1时,在运行程序之后,我得到AC1BD1(它从第一个数组中省略了第二个字符)。

#include<stdio.h>
#include<string.h>

#define N 100

void shuffle(char *cards) {
    int i, n, x=0, c1=0, c2=0, j=0;
    char tmp1[N]={0}, tmp2[N]={0};

    n=strlen(cards);

    //divide to 2 arrays with same number of elements
    for(i=0; i<n; i++){
        if(i<(n/2)){
            tmp1[i]=cards[i];}
        else{
            tmp2[x]=cards[i];
            x++;
        }
     }

    //storing 2 elements from first array, then 2 elements from second array and so on
    for(i=0; i<n; i++){ 
        if(j>3){
            j=0;
        }
        if(j<=1){   // store 2 elements from 1st array
            cards[i]=tmp1[c1];
            c1++;
            j++;
        }
        if(j>=2){   // store 2 elements from 2nd array
            cards[i]=tmp2[c2];
            c2++;
            j++;
        }
    }

    printf("1st half:%s\n2nd half:%s", tmp1, tmp2);
    printf("\n\t%s",cards);

    return; 
}

int main() {
    char cards[N];

    scanf("%s", cards);
    shuffle(cards);

    return 0; 
}

3 个答案:

答案 0 :(得分:2)

问题出在这里

    if(j<=1){   // store 2 elements from 1st array
        cards[i]=tmp1[c1];
        c1++;
        j++;
    }
    if(j>=2){   // store 2 elements from 2nd array
        cards[i]=tmp2[c2];
        c2++;
        j++;
    }

将第二个if作为“else if”(只是“else”也足够)

当你将j从1增加到2之后,你会进入第二个if语句,然后在卡片上重写相同的索引。

答案 1 :(得分:2)

如果你不介意以更简单的方式“改变你的牌组”的替代建议:

void shuffle(char *cards)
{
    char tmp[N]={0};

    int n = strlen(cards);

    for (int i=0; i<n/2; i++)
        tmp[i*2+0] = cards[i];

    for (int i=0; i<n/2; i++)
        tmp[i*2+1] = cards[i+n/2];

    for (int i=0; i<n; i++)
        cards[i] = tmp[i];
}

答案 2 :(得分:0)

你称之为洗牌和卡牌。 制作一个有两个元素的卡片结构不是更好吗?

我认为你在for循环中的j表现不对。 我会仔细检查这个并编辑这个答案,如果它不是j。

编辑: 你的cradcount有点关闭,你写了错误的索引。 这是一些有效的代码:

j = 0;
i = 0;
while(i<n)
{ 
    ++j;
    if(j == 1 || j == 2)
    {   // store 2 elements from 1st array
        cards[i++]=tmp1[c1++];
    }
    else if(j == 3 || j == 4)
    {   // store 2 elements from 2nd array
        cards[i++]=tmp2[c2++];
    }
    else
    {
        j = 0;
    }
}

通常,您可以使用调试器查看索引发生的情况。我认为这是家庭作业,你必须写“最佳代码”。一般来说,使用具有更多含义的varaiblaenames是有益的。

EDIT2:

下面有一个很好的解决方案,说明时间优化代码。 我想添加一些我认为更容易阅读和维护的代码。

#include<stdio.h>
#include<string.h>

#define DECK_MAX 100

typedef struct 
{
    char group;
    int number;
}Tcard;

typedef struct
{
    Tcard card[DECK_MAX];
    int count;
}Tdeck;

int ReadDeck(Tdeck * deck, const char *cardstring);
int DeckAddCopy(Tdeck * deck, Tcard * card);
int PrintDeck(Tdeck * deck, const char *deckname);
int InterleaveDecksCopy(Tdeck * target, Tdeck * source[], int sourcecount);
int SplitDeckCopy(Tdeck * source, Tdeck * target[], int targetcount);

int main() {
    int e = 0;
    char cardstring[100];
    Tdeck deck, stackA, stackB, interleaved;
    Tdeck * stacks[] = {&stackA, &stackB};

    printf("Please input a cardstring: ");
    scanf("%s", cardstring);

    e |= ReadDeck(&deck, cardstring);
    e |= PrintDeck(&deck, "cardstring");
    e |= SplitDeckCopy(&deck, stacks, sizeof(stacks) / sizeof(Tdeck*) );
    e |= PrintDeck(&stackA, "1st half");
    e |= PrintDeck(&stackB, "2nd half");
    e |= InterleaveDecksCopy(&interleaved, stacks, sizeof(stacks) / sizeof(Tdeck*) );
    e |= PrintDeck(&interleaved, "interleaved");

    if( e != 0) printf("There was an error dureing execution.\n");

    return e; 
}

int ReadDeck(Tdeck * deck, const char *cardstring)
{
    int e = 0;
    int varCount, n, total = 0;
    Tcard card;
    memset(deck, 0, sizeof(Tdeck));
    do{
        n = 0;
        varCount = sscanf(&cardstring[total], "%c%i%n", &card.group, &card.number, &n);
        total += n;
        if( varCount == 2 )
        {
            //check if card is valid?
            e |= DeckAddCopy(deck, &card);
        }
        else
        {
            if(strlen(cardstring) != total)
            {
                //string was not read completely
                e |= 1;
            }
        }
    }while(varCount == 2);    
    return e;
}

int DeckAddCopy(Tdeck * deck, Tcard * card)
{
    int e = 0;
    if(deck->count >= DECK_MAX)
    {
        e |= 1;
    }
    else
    {
        memcpy(&deck->card[deck->count++], card, sizeof(Tcard));
    }
    return e;
}

int PrintDeck(Tdeck * deck, const char *deckname)
{
    int c;
    printf("%s contains %i cards%s", deckname, deck->count, (deck->count == 0)? ".\n":": ");
    for(c = 0; c < deck->count; ++c)
    {
        printf("%c%i%s", deck->card[c].group, deck->card[c].number, ( c+1 < deck->count) ? ", ":".\n");
    }
    return 0;

}

int InterleaveDecksCopy(Tdeck * target, Tdeck * source[], int sourcecount)
{
    int c, s, e = 0;
    memset(target, 0, sizeof(Tdeck));

    for(c = 0; c < DECK_MAX; ++c)
    {
        for(s = 0; s < sourcecount ; ++s)
        {
            if(c < source[s]->count)
            {
                e |= DeckAddCopy(target, &source[s]->card[c]);
            }
        }
    }    
    return e;
}

int SplitDeckCopy(Tdeck * source, Tdeck * target[], int targetcount)
{
    int c, t, e = 0;
    for(t = 0; t < targetcount ; ++t)
    {
        memset(target[t], 0, sizeof(Tdeck));
    }

    c = 0;
    for(t = 0; t < targetcount ; ++t)
    {
        int cMax = (source->count) - (((source->count)/targetcount) * targetcount - t - 1 );
        for( ; c < (t+1)*(source->count)/targetcount ; ++c)
        {
            e |= DeckAddCopy(target[t], &source->card[c]);
        }
    }
    return e;
}