2014-01-25 2 views
1

Мне нужно создать программу, которая будет запрашивать у пользователя ввод строки, а затем в программе необходимо разделить ее на две строки одинакового размера (пользователь всегда вводит четное количество символов), после чего он должен «перетасовать», их ...C: чередование с петлей?

Так оно и должно в принципе сделать это:

user inputs: A1B1C1D1 

код должен сделать 2 одинаковые строки размера: A1B1 и C1D1 и после того, что он должен «перетасовать», чтобы они выглядели так: A1C1B1D1.

Так что нужно принимать первые 2 элементы первой строки, затем первые 2 элементы второй строки и так далее ...

Моя проблема заключается в том, что, когда я ввод A1B1C1D1, после того как я запустить программу, я получаю AC1BD1 (он не учитывает 2-го символа из первого массива).

#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; 
} 
+0

Это «перетасовать», который не случайно переставить массив? –

+0

нет, вот почему я сказал «shuffle», он должен просто взять 2 элемента из первого массива, затем 2 со второго и так далее, но я не знал, что еще назвать его, поэтому я сказал «shuffle» – user3236093

+0

English is not my первый язык, но я уверен, что операция, которую вы описываете, «чередуется» и не перетасовывается. Http: //cs.stackexchange.com/questions/332/in-place-algorithm-for-interleaving-a-array – odedsh

ответ

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++; 
    } 

Сделать второй, если в качестве «еще, если» (просто «еще» также достаточно)

Что происходит, что после увеличения J от 1 до 2, вы переходите во второе утверждение if и переписываете один и тот же индекс на карточках.

+0

Это сработало, спасибо большое :) – user3236093

+0

хороший ответ !. ... –

0

Вы называете это shuffle и cards. Не было бы лучше создать структуру карты, которая имеет два элемента?

Я думаю, что ваш j в цикле for ведет себя неправильно. Я дважды проверю это и отредактирую этот ответ, если он не был j.

РЕДАКТИРОВАТЬ: Ваш взломщик был выключен, и вы написали неправильный указатель. Вот некоторые рабочий код:

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; 
} 
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]; 
} 
+0

+1 для скорости этот код выполняется быстрее, потому что в нем нет утверждений if/else. – Johannes

+0

Спасибо :) P.S .: интересной задачей было бы выполнить эту «перетасовку» без дополнительного буфера ... –

Смежные вопросы