2015-11-04 135 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。但是,始终确保代码是空的 - 终止您的字符串是一种良好的做法。

相关问题