2015-11-04 105 views
1

我想問一下,如果我有一個字符串「abcdefgh」,我希望它的一半成爲「abcd」和「efgh」並將它存儲到自己的字符串中,稱它爲「UpperHalf」和「LowerHalf」。所以要這樣做的方法是首先使用strlen()來找出我的輸入的長度和一半呢?那麼我需要使用strcpy()並將其複製到它們各自的字符串中嗎?把一個字符串分成了兩半,再加上另一個字符串

其實我甚至不知道我的代碼是否有意義。任何人都可以給我一些評論呢?

我意識到我只需要考慮即使是輸入數字,這意味着我不必擔心奇數輸入。以前我試圖把一個1d的字符串分成兩半,然後用另一個字符串進行strcat。但是現在我得到了一系列以二維數組格式存儲的輸入字符串。在這種情況下,我如何檢索這些字符串並將其操作,就好像它與前面的1d案例一樣?我不認爲我需要使用循環?我可以指向行嗎?

int d = strlen(str); // just an example where str = the characters inside my string 
strcpy(temp, &str[0]); // store original string into a temp string starting from 0 to \0 
str[d/2] = '\0'; 
strcpy(UpperHalf, &str[0]); // starts copying from position 0 to \0 which is the half way point 
str[0] = temp; //revert back to normal -> Does this line even make sense? 
strcpy(LowerHalf, &str[d/2]); 
+2

替換 '/μ0' 與 '\ 0' – user3159253

+0

感謝。我糾正了它,但邏輯明智的任何意見?有點第一次做絃樂。 – Morde

+1

你*知道陣列自然衰減指向他們的第一個元素?這意味着如果你有一個數組'str'並將它傳遞給一個帶指針的函數,編譯器將傳遞的內容與'&str [0]'實際上是一樣的。所以你不必明確說明它,只要通過'str'就可以工作。 –

回答

1

是的,你絕對需要考慮奇數字符串長度。有代碼方法會將其向上或向下舍入(以便第一個或第二個字符串將具有額外的字符),但是您需要決定您想要的方式。

看着你的代碼,我會建議使用臨時字符串是不需要的。您可以直接從原始'str'中複製,並節省內存和處理器開銷。需要進行一些更改: 目前,您正在使用'\ 0'字符覆蓋源字符串中的一個字符,並且第二個strcpy從'\ 0'開始,它將返回零長度的字符串。 要複製固定數量的字符,您可以使用strncpy,它可以比strcpy更好地工作,方法是簡化代碼並保持清晰。 不要忘記用\ 0終止你的字符串,或者你可以用0值初始化緩衝區,就像我在這裏。

所以,一個例子可能是這樣的:

char UpperHalf[MAX_LENGTH]; 
char LowerHalf[MAX_LENGTH]; 

int l = strlen(str); 
int half = l/2; 
memset(LowerHalf, '\0', MAX_LENGTH); 
strncpy(LowerHalf, str, half); 
memset(UpperHalf, '\0', MAX_LENGTH); 
strncpy(UpperHalf, str + half, l - half); 

這將會把一個奇怪的長串的較長部分進入UpperHalf字符數組。 爲了使代碼安全,您還應該考慮進行長度比較,以確保所有字符串都適合所提供的緩衝區(對於字符串終止\ 0字符,至少留下一個字符)。

+0

表達式'L/2'是一個整數除法並且將產生一個整數。我不認爲你需要這裏的浮點運算。只要左邊的子字符串爲'L/2',右邊的爲'L - L/2'。 (我用一個大寫ELL這裏,否則它看起來太像分數的一半。) –

+0

是,將工作過。爲了保持它的整潔,我想將第一部分存儲到一個臨時變量中:int lowHalf = L/2;然後對另一半的減法將被清除爲L - lowHalf。如果只有其中的一個被四捨五入,那麼通過兩個單獨的劃分進行操作可能會導致錯誤。請注意,如果完全按照描述完成,則此方法將較短的字符串放入LowerHalf中。 – PeteB

+1

你對「太」有什麼意思?你的方法不起作用。 (或者,更輕輕的說,它只能在理論上)說'L'是7.然後'L/2'是3,而不是3.5,因爲這是一個整數除法。 3 + 0.5是3.5,在轉換爲int時將被再次截斷爲3。你可以說'L/2.0 + 0.5'將中間元素移動到左邊的子數組中。但是這可以表示爲「(L + 1)/ 2」,對此您不需要任何浮點數學運算。 –

0

是的,你必須首先使用strlen得到輸入字符串的長度,減少一半給予的upper_half長度:

size_t length = strlen(str); 
size_t upper_length = length/2; 
size_t lower_length = length - upper_length; 

在這種情況下,如果輸入的字符串的長度爲奇數,那麼由於整數除法,upper_length將等於lower_length - 1,如:

length == 3 
upper_length == 3/2 == 1 
lower_length == 3 - 1 == 2 

它更容易做實際的複製,而無需修改原始字符串,因爲你的代碼做什麼。

您必須分配空間來存儲字符串半的副本,與空終結:

char *upper_half = malloc(upper_length + 1); 
char *lower_half = malloc(lower_length + 1); 

然後使用memcpy複製字符串數據:(同樣爲lower_half

memcpy(upper_half, &str[0], upper_length); 
upper_half[upper_length] = '\0'; 

strcpy副本字符,直到一個空字節,而memcpy拷貝給定數目的字節。

+0

嗨,你能解釋一點memcpy和memset?因爲我只學習了正常的strcpy,strlen,strcmp和strcat。 – Morde

+0

@Morde:'memcpy(destination,source,count)'''''''''''''從'source'到'destination'複製'count'字節。如果你想用* only *'strcpy'來完成這個工作,你需要按照你的想法來做:用第一個字符串結尾的字符替換爲空終止符,然後在完成時恢復它。 'char temp = str [upper_length]; str [upper_length] ='\ 0'; strcpy(upper_half,&str [0]); str [upper_length] = temp; strcpy(lower_half,&str [upper_length]);'然而,這個代碼比直接複製數據的版本有點難以推理。 –

+0

「......而'memcpy'複製給定數量的字節......」但也有一個'strncpy' :)(哦,我發現它已經從OPs短名單中丟失了。) – usr2564301

0

雖然蠻好用的所有標準功能,以降低/上半部分拷貝到單獨的字符串,也可以拆分只用三分球和一個單獨的緩衝區來存放字符串的下半部分的字符串。

基本上,你可以找到字符串的長度,調整中點的奇數/偶數位置(如果需要總是,但下半部分奇數長度的附加字符),然後使用一個簡單的循環複製到下半部分。在循環結束時,使用的指針指向上半部分(或者您可以簡單地使用指針來指定中點的位置)。一個簡短的例子是:

#include <stdio.h> 

#define MAXC 64 

int main (int argc, char **argv) { 

    if (argc < 2) { 
     fprintf (stderr, "error: insufficient input, usage: %s string\n", 
       argv[0]); 
     return 1; 
    } 

    char lower_half[MAXC] = {0}; /* array to hold lower_half */ 
    char *p = argv[1];    /* poiter to string   */ 
    char *pl = lower_half;   /* pointer to lower_half */ 
    char *split = NULL;    /* pointer to split point */ 
    size_t len = 0;     /* string length   */ 

    for (; *p; p++);  /* find end of string */ 
    len = p - argv[1];  /* get string length */ 
    p = argv[1];   /* reset pointer  */ 
    split = p + len/2;  /* set split at middle */ 
    if (len & 1) split++; /* if odd, add 1  */ 

    for (; p < split; p++) /* for each ch < split */ 
     *pl++ = *p;   /* copy to lower_half */ 
    *pl = 0;    /* null-terminate  */ 

    /* print results */ 
    printf ("\n lower_half : '%s' upper_half : '%s'\n", 
      lower_half, split); 

    return 0; 
} 

輸出不管你是否使用指針或使用strlenstrncpy,或memcpy

$ ./bin/str_half 123456789 

lower_half : '12345' upper_half : '6789' 

$ ./bin/str_half 1234567890 

lower_half : '12345' upper_half : '67890' 

,只要確保你null-terminate分離的字符串。以上,顯式空終止不需要因lower_half之初全部被初始化爲0。但是,始終確保代碼是空的 - 終止您的字符串是一種良好的做法。

相關問題