Strip first and last character from C string
我有一个c字符串,看起来像"Nmy stringP",其中n和p可以是任何字符。如何在C中编辑成"my string"?
- 作业?如果是的话,加上"家庭作业"标签。
- 不,不是家庭作业-只是为了好玩而学C。
- 在纯C中没有"字符串"这样的东西。您有指向缓冲区(char *或字符数组(char[]的指针吗?
要"删除",第一个字符指向第二个字符:
1 2 3
| char mystr[] ="Nmy stringP";
char *p = mystr;
p++; /* 'N' is not in `p` */ |
若要删除最后一个字符,请将其替换为" "
1
| p [strlen(p )-1] = 0; /* 'P' is not in `p` (and it isn't in `mystr` either) */ |
- 这可能不起作用,因为通过将"nmy stringp"初始化为文本,编译器/链接器可以将其放在只读内存中,从而导致编辑失败。
- @suppressingfire:"nmy stringp"实际上是一个文本字符串,但它被复制(逐字符)到数组mystr。数组mystr是可修改的。
- @PMG:你在哪里复制?char *p = mystr指向p到mystr,不复制mystr。
- @PMG:我可以推荐strdup吗?
- 文本字符串被复制到名为"mystr"的变量的位置。mystr不是指向文本的指针,它是文本的副本。
- @Bryan Oakley:mystr指向文本数组,但该数组可以在只读内存中,不是吗?
- strdup()不是标准函数。它在那些提供它作为扩展的实现上的工作,可能在不同的实现之间有所不同。在需要的时候,我更喜欢malloc()和strcpy()。不需要演示如何删除字符串的第一个和最后一个字符。
- mystr不是指针,它是一个用字符串文本内容初始化的数组。他的密码是正确的。
- char sz[]="你好";您的sizeof(sz)=6,而不是sizeof(sz)=4。
- @pmd:re:strdup对malloc和strcpy注。
- @PMD和其他人:让我困惑的是PMD使用了"copy"。我假设您的意思是字符串是放在堆栈上的,而不是放在静态(可能是只读)内存中。我忘记了。
- @夸克:做char arr[] ="hi";和char arr[3]; arr[0] = 'h'; arr[1] = 'i'; arr[2] = '\0';是一样的。
- @布赖恩邦迪:不,mystr不是指针,但它还是指数组的开头。问题不在于数组的大小(编译器可以告诉您,不管数组在哪里被分配),而是它被分配了什么类型的内存。
- @ PMD:对。我习惯于将字符串文本制作为const,并使它们成为全局的,而不是本地的。本地数组放在堆栈上,我忘记了这一点。很抱歉,我的争吵。
- 不管它是不是全球性的。char arr[] ="foo";将字符串文字(逐字符:'f'、'o'、'o'和' ')的元素复制到数组arr中。当你有指针的时候就很重要了:char *arr ="foo";这里不复制,不管它是全局的还是非全局的。
- 我只是想把char arr[] = { 'f', 'o', 'o', '\0' };投入到混合中,以便更好地测量,有点巩固初始化部分。谢谢。
- 在上面的问题中,我认为缺少以下步骤,strcpy(mystr,p);,不是吗?…请评论!
- @不,什么都没有丢失。mystr是一个数组,p指向该数组中的某个位置。
- @PMG:先生,但是字符串mystr的第一个术语还是一样的。字符串mystr只是Nmy string,p是my string。要更改实际字符串mystr,需要使用strcpy(mystr,p)。
- "代码杰克:啊!好啊。。。但是你不能在同一个物体内的物体之间进行交互。要更改数组mystr的内容,可以使用memmove(mystr, mystr+1, sizeof mystr - 1);
另一个选项,再次假设"编辑"意味着要就地修改:
1 2 3 4 5 6
| void topntail (char *str ) {
size_t len = strlen(str );
assert(len >= 2); // or whatever you want to do with short strings
memmove(str , str +1, len -2);
str [len -2] = 0;
} |
这将在适当的位置修改字符串,而不会像PMG的解决方案那样生成新地址。不是说PMG的回答有什么问题,但在某些情况下,这不是你想要的。
关于@pmg的答案,请注意,您可以在一个语句中同时执行这两个操作:
1 2 3
| char mystr [] ="Nmy stringP";
char *p = mystr ;
p ++[strlen(p )-1] = 0; |
这可能如预期的那样工作,但行为在C标准中是未定义的。
- 最好不要依赖未定义的行为。
- @Xav0989同意了,我打算多加一点,作为评论(强调不这样做的原因),而不是作为替代答案。我对这个有点陌生。
最有效的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| //Note destroys the original string by removing it's last char
// Do not pass in a string literal.
char * getAllButFirstAndLast (char *input )
{
int len = strlen(input );
if(len > 0)
input ++;//Go past the first char
if(len > 1)
input [len - 2] = '\0';//Replace the last char with a null termination
return input ;
}
//...
//Call it like so
char str [512];
strcpy(str ,"hello world");
char *pMod = getAllButFirstAndLast (str ); |
最安全的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void getAllButFirstAndLast (const char *input , char *output )
{
int len = strlen(input );
if(len > 0)
strcpy(output , ++input );
if(len > 1)
output [len - 2] = '\0';
}
//...
//Call it like so
char mod [512];
getAllButFirstAndLast ("hello world", mod ); |
第二种方法效率较低,但更安全,因为您可以将字符串文本传入输入。如果不想自己实现,也可以使用strdup作为第二种方法。
- 我在第二个实现中看到的问题是,在调用getAllBufferStandlast()之前,需要确保输出足够大,能够处理副本。在这种情况下,我建议在调用中添加一个outputLength变量,并让被调用函数使用strn*函数操纵输出。
- 是的,这是一个先决条件,可以添加长度参数。