2017-06-17 153 views
0

我試圖編寫一個函數來獲取一個字符串並創建一個新的字符串,但沒有多個空格(在單詞之間只留下1個空格)。從字符串中刪除空格

到目前爲止,我寫了這個,但由於某種原因,它崩潰了,調試器什麼也沒有顯示。

我也不知道我在哪裏需要把自由功能...

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char* upgradestring(char* oldtext); 

int main() 
{ 
    char str1[] = "Chocolate  Can Boost Your Workout" ; 

    printf("%s\n", str1); 

    printf("\n%s\n", upgradestring(str1)); 

    return 0; 
} 

char* upgradestring(char* oldtext) 
{ 
    int i,j, count = 1; 
    char *newstr; 

    for (i = 0; oldtext[i] != '\0'; i++) 
    { 
     if (oldtext[i] != ' ') 
      count++; 
     else if (oldtext[i - 1] != ' ') 
      count++; 
    } 
    newstr = (char*)malloc(count * sizeof(char)); 
    if (newstr == NULL) 
     exit(1); 

    for (i = 0, j = 0; (oldtext[i] != '\0')|| j<(count+1); i++) 
    { 
     if (oldtext[i] != ' ') 
     { 
      newstr[j] = oldtext[i]; 
      j++; 
     } 
     else if (oldtext[i - 1] != ' ') 
     { 
      newstr[j] = oldtext[i]; 
      j++; 
     } 
    } 

    return newstr; 
} 
+0

是的,我需要返回一個新字符串相同oldstring,但只有1個詞語之間的空間 – 420Friendlly

+0

計數是新的字符串的大小與1個空間和計數+ 1是'\ 0' – 420Friendlly

回答

1

很好的嘗試,但讓我們關注,當你需要釋放你的記憶上。你動態地分配函數中的內存,然後在printf中調用函數,這將允許字符串打印,但是如何取消分配它?使用指針指定函數的返回值,將其打印出來,然後釋放它!

此外,你需要儘可能多的字符新的字符串了,加上一個用於空終止分配空間,因爲C字符串要求與來自頭未來的功能,如printf()工作的順利開展。

此外,我們不會在C中輸入什麼malloc(),請閱讀更多here

而且這樣的:

else if (oldtext[i - 1] != ' ') 

應該寫成:

else if (i != 0 && oldtext[i - 1] != ' ') 

,以避免訪問oldtext[-1]這是出界,當i爲0

最後,你條件在填充新字符串時使用,對於邏輯AND而不是OR來說會更好,因爲一旦條件爲假,我們就必須停止(我們要做n或者想要讀取原始字符串的空終止符或超過新字符串的大小)。

將所有內容放在一起,我們:

#include <stdio.h> 
#include <stdlib.h> 

char* upgradestring(char* oldtext) 
{ 
    int i, j, count = 0; 
    // compute 'count' 
    for(i = 0; oldtext[i]; i++) 
    { 
     if (oldtext[i] != ' ') 
      count++; 
     else if (i != 0 && oldtext[i - 1] != ' ') 
      count++; 
    } 
    char* newstr = malloc(count + 1); // PLUS ONE for the null terminator 
    if(!newstr) // check if malloc failed 
    { 
     printf("Malloc failed\n"); 
     return 0; 
    } 
    // populate 'newstr'. We need to stop when either condition is false 
    for (i = 0, j = 0; (oldtext[i]) && j<(count+1); i++) 
    { 
     // Same as your code 
    } 
    // Assign the null terminator! 
    newstr[j] = '\0'; 
    return newstr; 
} 

int main(void) { 
    char str1[] = "Chocolate  Can Boost Your Workout" ; 
    // store the result of your function into 'newstr' 
    char* newstr = upgradestring(str1); 
    // print it 
    printf("%s\n", newstr); 
    // free it, since you no longer need it! 
    free(newstr); 
    return 0; 
} 

輸出:

巧克力可以提高你的鍛鍊

+1

謝謝你,你幫了這麼多!現在我知道我的想法出了什麼問題 – 420Friendlly

+0

總是很高興回答好的問題@ 420Friendlly,繼續保持! =) – gsamaras

2

你解決[i-1],它不是原來的範圍內數組如果i==0

這裏是你如何能做到這一點:

只需通過一個複製一個,如果焦炭是「」,保持當它跳過「」,否則一個前進。

static size_t newlen(char const *o) 
{ 
    size_t r=0; 
    while(*o){ 
     r++; 
     if(*o==' ') 
      while(*o==' ') 
       o++; 
     else 
      o++; 
    } 
    return r; 

} 
char *upgradestring(char const *o) 
{ 
    char *r, *p; 
    size_t len = newlen(o); 
    if(0==(r = malloc(len+1))) 
     return 0; 
    r[len]=0; 
    for(p=r;*o;){ 
     *p++=*o; 
     if(*o==' ') 
      while(*o==' ') 
       o++; 
     else 
      o++; 
    } 
    return r; 
} 
int main() 
{ 
    char str1[] = "Chocolate  Can Boost Your Workout" ; 
    char *new; 
    printf("%s\n", str1); 
    if(0 == (new = upgradestring(str1))) 
     return 1; 
    printf("%s\n", new); 
    free(new); 
} 

分配失敗最好用返回碼錶示(如果失敗,你不希望庫函數放棄你的程序)。

爲了能夠釋放返回的字符串,您首先必須將其捕獲到一個變量中。

0

#include <stdio.h> 
#include <stdlib.h> 

char *upgradestring(char *oldtext) 
{ 
size_t len,src,dst,spc; 
char *result; 

     // First pass: count needed size 
for (len=src=spc=0;oldtext[src]; src++){ 
     if (oldtext[src] != ' ') spc=0;  // non-space needs space 
     else if(spc++) continue;    // skip non first space 
     len++; 
     } 

result= malloc (1+len); 

     // Second pass: copy(K&R style) 
for (dst=src=spc=0; (result[dst] = oldtext[src]) ; src++){ 
     if (oldtext[src] != ' ') spc=0;  // non-space: rest counter 
     else if(spc++) continue;    // skip non-first space 
     dst++; 
     } 

return result; 
} 

簡體版:不要計算第一遍大小,但具有相同尺寸與原來的開始,第二遍後調整大小。 (的strdup()可以通過strlen的+的malloc +的memcpy取代)


char * strdup(char *); 

char *upgradestring2(char *oldtext) 
{ 
size_t src,dst,spc; 
char *result; 

result= strdup (oldtext); 

     // edit the copy, skipping all spaces except the first 
for (dst=src=spc=0; result[src] ; src++){ 
     if (result[src] != ' ') spc=0; // non-space:reset counter 
     else if(spc++) continue;  // skip space,except the first 

     result[dst++] = result[src]; // Copy 
     } 
result[dst] = 0;// terminate string; 

// result=realloc(result, dst+1); 

return result; 
} 
0

對於初學者來說既不聲明從頭部<string.h>在程序中被使用。因此,這個指令

#include <string.h> 

可能會從程序中刪除。

按照C標準的功能main不帶參數應聲明如下

int main(void) 

與陌生的名字upgradestring功能:)不改變說法。因此,它應該被宣佈像

char* upgradestring(const char* oldtext); 
        ^^^^^ 

要考慮到源字符串可以用空格開始。在這種情況下,聲明這樣

else if (oldtext[i - 1] != ' ') 
     count++; 

導致不確定的行爲,因爲是訪問內存超出了字符串時i等於0的嘗試。

(oldtext[i] != '\0')|| j<(count+1); 

應至少這樣寫

(oldtext[i] != '\0') && j<(count+1); 
        ^^^ 

雖然它是足夠來檢查索引j,因爲它不能比源串的長度長的狀態。

您忘記追加結尾字符串與終止零'\0'

而且它不符合這個說法

exit(1); 

在這種情況下,你可以只返回一個空指針退出該功能是一個好主意。

在退出程序之前,分配的內存應該被釋放。

正如之前所提到的,源字符串可以以空格開始,並且還有一個冗餘的尾部空格。我認爲將它們從結果字符串中排除在邏輯上是一致的。

通常空格字符與製表符配對使用。此外,C在標頭<ctype.h>中聲明的特殊功能isblank檢查字符是空格還是空格。(據我所知,MS VS不支持此功能)

考慮到所有這些因素,可以按照以下方式定義函數,如演示程序中所示。

#include <stdio.h> 
#include <stdlib.h> 

char * trim_blanks(const char *s) 
{ 
    size_t n = 0; 

    const char *p = s; 

    // skip leading blanks 
    while (*p == ' ' || *p == '\t') ++p; 

    _Bool last_blank = 0; 

    for (; *p; ++p) 
    { 
     ++n; 
     if ((last_blank = (*p == ' ' || *p == '\t'))) 
     { 
      while ( p[1] == ' ' || p[1] == '\t') ++p; 
     }   
    } 

    if (last_blank) --n; 

    char *q = malloc(n + 1); 

    if (q) 
    { 
     p = s; 

     // skip leading blanks 
     while (*p == ' ' || *p == '\t') ++p; 

     size_t i = 0; 
     for (; i < n; i++, ++p) 
     { 
      q[i] = *p == '\t' ? ' ' : *p; 
      if (q[i] == ' ') 
      { 
       while ( p[1] == ' ' || p[1] == '\t') ++p; 
      } 
     } 

     q[i] = '\0'; 
    } 

    return q; 
} 

int main(void) 
{ 
    char s[] = "\t\tChocolate \t Can \t Boost Your Workout "; 

    printf("\"%s\"\n", s); 

    char *t = trim_blanks(s); 

    printf("\"%s\"\n", t); 

    free(t); 

    return 0; 
} 

程序輸出是

"  Chocolate  Can Boost Your Workout " 
"Chocolate Can Boost Your Workout"