2011-03-05 28 views
6

C tarzı dizesi tüm boşlukları değiştirmek için bir yöntem yazın ve çözümünü anlamaya çalışan bazı yardım istiyorum:Bu görüşme soru karşılaştığınız

'ile bir dize tüm boşlukları değiştirmek için bir yöntem yazın % 20' . (Bir forumdan)

Çözüm:

char str[]="helo b"; 
int length = strlen(str); 
int spaceCount = 0, newLength, i = 0; 

for (i = 0; i < length; i++) { 
if (str[i] == ' ') { 
    spaceCount++; //count spaces... 
} 
} 

newLength = length + spaceCount * 2; //need space for 2 more characters.. 
str[newLength] = '\0'; 

for (i = length - 1; i >= 0; i--) { 
    if(str[i] == ' ') { 
     str[newLength - 1] = '0'; //??? 
     str[newLength - 2] = '2'; 
     str[newLength - 3] = '%'; 
     newLength = newLength - 3; 
    } else { 
     str[newLength - 1] = str[i]; 
     newLength = newLength - 1; 
    } 
} 

Bu program benim için çalışmıyor ... ben ilk kod dalmadan önce algoritmayı anlamak istiyorum.

+0

Ah, o zaman bozuldu. Sonuç için daha fazla bellek ayırmaz. – thkala

+0

true ... statik bir diziyi yeniden boyutlandırmaya çalışıyor ... ama sonra tekrar ..Bu soruyu çözmek için doğru algoritma ne olurdu? – maxpayne

+3

Bunu derledim ve denedim; ve çalışıyor. Ama başka bir hafızanın ayak parmaklarına bastığın için kırılmış ve tehlikeli. Böyle şeyler yapma; Çalışma zamanında daha fazla yere ihtiyacınız varsa, er ya da geç 'malloc 'kullanmak zorunda kalacaksınız. – darioo

cevap

12

Bu örnek bozuldu.

Arabellek taşması, Dizenin anlamsız bir taraması (strlen), Okunması zor. Bu C ise

int main() { 
    char src[] = "helo b"; 
    int len = 0, spaces = 0; 
    /* Scan through src counting spaces and length at the same time */ 
    while (src[len]) { 
    if (src[len] == ' ') 
     ++spaces; 
    ++len; 
    } 
    /* Figure out how much space the new string needs (including 0-term) and allocate it */ 
    int newLen = len + spaces*2 + 1; 
    char * dst = malloc(newLen); 
    /* Scan through src and either copy chars or insert %20 in dst */ 
    int srcIndex=0,dstIndex=0; 
    while (src[srcIndex]) { 
    if (src[srcIndex] == ' ') { 
     dst[dstIndex++]='%'; 
     dst[dstIndex++]='2'; 
     dst[dstIndex++]='0'; 
     ++srcIndex; 
    } else { 
     dst[dstIndex++] = src[srcIndex++]; 
    } 
    } 
    dst[dstIndex] = '\0'; 
    /* Print the result */ 
    printf("New string: '%s'\n", dst); 
    /* And clean up */ 
    free(dst); 
    return 0; 
} 
+0

Çalışıyor ... (dst [dstIndex] = '\ 0' yazıp hemen yeni dizgiyi yazdırmadan önce eklemeliyiz!) – maxpayne

+0

Bu çözüm, ikinci bir char dizisi tahsis eder, ters çevrimi korumaksızın ve uzatmaksızın yapılabilir ilki doğru. – krtek

+0

@Krtek: hayır yapamaz, orijinal str [] okunabilir kod ve strlen optimizasyonu için "helo% 20b" – Erik

1

Gördüğüm kadarıyla, ilk önce tüm boşlukları bulmak için dize boyunca arama yapar, sonra dize içinde boşluk başına 2 fazla karakter (20) sığdırmak için dizeyi uzatmaya çalışır (ancak sanırım uzayı tahsis eder), sonra tekrar dizgeden geçer, ama bu kez tersine, her karakterin yeni dizenin arkasındaki boşluk olmayan bir boşluk bırakması ve bir boşlukla karşılaşması durumunda bunun yerine% 20 yerleştirir, fakat tersine yapar.

üç karakterli bir tek karakterle (' ') değiştiriyorsanız yana
3
for (i = 0; i < length; i++) { 
    if (str[i] == ' ') { 
     spaceCount++; //count spaces... 
    } 
} 

, öncelikle boyut artışı hesaplamak için boşluk sayısını.

newLength = length + spaceCount * 2; //need space for 2 more characters.. 
str[newLength] = '\0'; 

Bu

size daha fazla bellek tahsis gerekir, böyle yapılamaz, ama burada biz dize değişkeni boyutunu genişletir. Bence en iyisi yeni bir değişken tahsis etmektir, çünkü bir sonraki adım bir diğeriyle daha kolay olacaktır.

for (i = length - 1; i >= 0; i--) { 
    if(str[i] == ' ') { 
     str[newLength - 1] = '0'; //??? 
     str[newLength - 2] = '2'; 
     str[newLength - 3] = '%'; 
     newLength = newLength - 3; 
    } else { 
     str[newLength - 1] = str[i]; 
     newLength = newLength - 1; 
    } 
} 

Son olarak, bu dize düzgün uzatılır eğer adım çalışmalıdır, ancak bunun daha net olması için yeniden yazılmış biraz olabiliyor.

Ben newstr varsayarak böyle bir şey önermek emsal adımında ayrılan yeni değişkendir: Eğer geriye döngü (bu bir başka dize ayırmaya gerek yoktur) tutmak istiyorsanız,

int j = 0; 
for(i = 0; i < length; i++, j++) { 
    if(str[i] == ' ') { 
     newstr[j] = '%'; 
     newstr[++j] = '2'; 
     newstr[++j] = '0'; 
    } else { 
     newstr[j] = str[i]; 
    } 
} 

Ya :

for (i = length - 1, j = newLength - 1; i >= 0; i--, j--) { 
    if(str[i] == ' ') { 
     str[j] = '0'; 
     str[--j] = '2'; 
     str[--j] = '%'; 
    } else { 
     str[j] = str[i]; 
    } 
} 
+0

3 dizenin kalan kısmını daha sonra nasıl kopyalayıp% 20 ekledim? – maxpayne

+0

Cevabımı başka bir çözümle düzenledim ... Ama aslında dizinin düzgün şekilde genişletilmesi durumunda verilen kodun çalışabileceğini düşünüyorum. – krtek

+0

Yani diziyi dinamik olarak ayırıp düzgün şekilde genişletmemiz koşuluyla orijinal kodun işe yarayacağını mı söylüyorsunuz? – maxpayne

2

algoritması, bu şekilde: birinci boşluk sayısını .. .. o 2 boşluk anlamına gelir, böylece dizge "ae rt" demek ve mevcut uzunluğu durumunda, c 6 (5 olduğu endeksi 0) .. çıkış dizgisi "% 20r% 20t" olmalıdır .. uzunluk = 10 (indeks = 0 durumunda 9) böylece yeni uzunluk 6 + '2' * 2 yani 10 ...

o boşluk karşılaştığında hiç o ters sırada orijinal dizisini gezinmesi beri tersten% 20 yerleştirdiğinde uzunluğu ayarlanır nasıl

bu .. o ... .. ters diğerine geçişler ve karakter karakter yerleştirir

1
/* program to replace the space with "%20" */ 
/* Author senthilkumar M */ 

eg str = "ab cd ef" 
    str1 = "ab%20cd%20ef" 


char *space_replace(char *str) 
{ 
     int l = strlen(str); 
     int i = 0, j =0; 
     int spc = 0, nl = 0; 
     char *str1 = NULL; 

     for(i = 0; i < l; i++) { 
       if(str[i] == ' ') { 
         spc++; 
       } 
     } 
     nl = l + 2*spc + 1; 
     str1 = (char *) malloc(sizeof(char) * nl); 
     if(!str1) { 
       fprintf(stdout, "malloc failed \n"); 
       return NULL; 
     } 
     for(i = 0; i < l; i++) { 
       if(str[i] == ' ') { 
         str1[j++] = '%'; 
         str1[j++] = '2'; 
         str1[j++] = '0'; 
       } else {`enter code here` 
         str1[j++] = str[i]; 
       } 
     } 
     str1[j] = '\0'; 
     return str1; 
}