修剪C中的字符串

简述:

我使用win32和标准C api(使用MSVC2008进行编译,因此我可以访问所有C ++的东西,如果需要,但我只是试图修剪一个char* ),相当于.NET中的.NET的String.Trim

鉴于存在strchrstrtok和各种其他字符串函数,当然应该有一个trim函数,或者可以重新调整的函数…

谢谢

没有标准的库函数可以做到这一点,但是推出自己的函数并不难。 关于这样做的问题有一个现有的问题 ,用源代码回答。

这让我想写自己的 – 我不喜欢那些提供的。 在我看来应该有3个function。

 char *ltrim(char *s) { while(isspace(*s)) s++; return s; } char *rtrim(char *s) { char* back = s + strlen(s); while(isspace(*--back)); *(back+1) = '\0'; return s; } char *trim(char *s) { return rtrim(ltrim(s)); } 

您可以使用ctype.h中的标准isspace()函数来实现此目的。 只需比较字符数组的开头和结尾字符,直到两端都不再有空格。

“空间”包括:

”(0x20)空格(SPC)

‘\ t’(0x09)水平标签(TAB)

‘\ n’(0x0a)换行符(LF)

‘\ v’(0x0b)垂直制表符(VT)

‘\ f’(0x0c)feed(FF)

‘\ r’(0x0d)回车(CR)

虽然没有任何function可以为您完成所有工作,但您必须使用自己的解决方案来重复比较给定字符数组的每一侧,直到没有剩余空格。

编辑:

由于您可以访问C ++,Boost有一个修剪实现等着您,让您的生活更轻松。

很惊讶看到这样的实现。 我通常会这样修剪:

 char *trim(char *s) { char *ptr; if (!s) return NULL; // handle NULL string if (!*s) return s; // handle empty string for (ptr = s + strlen(s) - 1; (ptr >= s) && isspace(*ptr); --ptr); ptr[1] = '\0'; return s; } 

它快速可靠 – 为我服务多年。

 /* Function to remove white spaces on both sides of a string ie trim */ void trim (char *s) { int i; while (isspace (*s)) s++; // skip left side white spaces for (i = strlen (s) - 1; (isspace (s[i])); i--) ; // skip right side white spaces s[i + 1] = '\0'; printf ("%s\n", s); } 
 #include "stdafx.h" #include  #include  char* trim(char* input); int _tmain(int argc, _TCHAR* argv[]) { char sz1[]=" MQRFH "; char sz2[]=" MQRFH"; char sz3[]=" MQR FH"; char sz4[]="MQRFH "; char sz5[]="MQRFH"; char sz6[]="M"; char sz7[]="M "; char sz8[]=" M"; char sz9[]=""; char sz10[]=" "; printf("sz1:[%s] %d\n",trim(sz1), strlen(sz1)); printf("sz2:[%s] %d\n",trim(sz2), strlen(sz2)); printf("sz3:[%s] %d\n",trim(sz3), strlen(sz3)); printf("sz4:[%s] %d\n",trim(sz4), strlen(sz4)); printf("sz5:[%s] %d\n",trim(sz5), strlen(sz5)); printf("sz6:[%s] %d\n",trim(sz6), strlen(sz6)); printf("sz7:[%s] %d\n",trim(sz7), strlen(sz7)); printf("sz8:[%s] %d\n",trim(sz8), strlen(sz8)); printf("sz9:[%s] %d\n",trim(sz9), strlen(sz9)); printf("sz10:[%s] %d\n",trim(sz10), strlen(sz10)); return 0; } char *ltrim(char *s) { while(isspace(*s)) s++; return s; } char *rtrim(char *s) { char* back; int len = strlen(s); if(len == 0) return(s); back = s + len; while(isspace(*--back)); *(back+1) = '\0'; return s; } char *trim(char *s) { return rtrim(ltrim(s)); } 

输出:

 sz1:[MQRFH] 9 sz2:[MQRFH] 6 sz3:[MQR FH] 8 sz4:[MQRFH] 7 sz5:[MQRFH] 5 sz6:[M] 1 sz7:[M] 2 sz8:[M] 2 sz9:[] 0 sz10:[] 8 
 static inline void ut_trim(char * str) { char * start = str; char * end = start + strlen(str); while (--end >= start) { /* trim right */ if (!isspace(*end)) break; } *(++end) = '\0'; while (isspace(*start)) /* trim left */ start++; if (start != str) /* there is a string */ memmove(str, start, end - start + 1); } 

当返回值总是等于参数时,我喜欢它。 这样,如果字符串数组已经分配了malloc() ,它可以再次安全地free()

 /* Remove leading whitespaces */ char *ltrim(char *const s) { size_t len; char *cur; if(s && *s) { len = strlen(s); cur = s; while(*cur && isspace(*cur)) ++cur, --len; if(s != cur) memmove(s, cur, len + 1); } return s; } /* Remove trailing whitespaces */ char *rtrim(char *const s) { size_t len; char *cur; if(s && *s) { len = strlen(s); cur = s + len - 1; while(cur != s && isspace(*cur)) --cur, --len; cur[isspace(*cur) ? 0 : 1] = '\0'; } return s; } /* Remove leading and trailing whitespaces */ char *trim(char *const s) { rtrim(s); // order matters ltrim(s); return s; } 
 void ltrim(char str[PATH_MAX]) { int i = 0, j = 0; char buf[PATH_MAX]; strcpy(buf, str); for(;str[i] == ' ';i++); for(;str[i] != '\0';i++,j++) buf[j] = str[i]; buf[j] = '\0'; strcpy(str, buf); } 

这个怎么样……它只需要对字符串进行一次迭代(不使用strlen,它遍历字符串)。 当函数返回时,你得到一个指向修剪后的字符串开头的指针,该字符串为空终止。 该字符串从左侧修剪空格(直到找到第一个字符)。 在最后一个非空格字符之后,该字符串也会被修剪掉所有尾随空格。

 char* trim(char* input) { char* start = input; while (isSpace(*start)) { //trim left start++; } char* ptr = start; char* end = start; while (*ptr++ != '\0') { //trim right if (!isSpace(*ptr)) { //only move end pointer if char isn't a space end = ptr; } } *end = '\0'; //terminate the trimmed string with a null return start; } bool isSpace(char c) { switch (c) { case ' ': case '\n': case '\t': case '\f': case '\r': return true; break; default: return false; break; } } 
 /* iMode 0:ALL, 1:Left, 2:Right*/ char* Trim(char* szStr,const char ch, int iMode) { if (szStr == NULL) return NULL; char szTmp[1024*10] = { 0x00 }; strcpy(szTmp, szStr); int iLen = strlen(szTmp); char* pStart = szTmp; char* pEnd = szTmp+iLen; int i; for(i = 0;i < iLen;i++){ if (szTmp[i] == ch && pStart == szTmp+i && iMode != 2) ++pStart; if (szTmp[iLen-i-1] == ch && pEnd == szTmp+iLen-i && iMode != 1) *(--pEnd) = '\0'; } strcpy(szStr, pStart); return szStr; } 

这是我的实现,表现得像libc中的内置字符串函数(也就是说,它需要一个c字符串,它会修改它并将其返回给调用者)。

它修剪前导空格并将剩余的字符向左移动,因为它从左到右解析字符串。 然后它标记字符串的新结尾并开始向后解析它,用’\ 0’替换尾随空格,直到找到非空格字符或字符串的开头。 我相信这些是这项特定任务的最小可能迭代次数。

 // ---------------------------------------------------------------------------- // trim leading & trailing spaces from string s (return modified string s) // alg: // - skip leading spaces, via cp1 // - shift remaining *cp1's to the left, via cp2 // - mark a new end of string // - replace trailing spaces with '\0', via cp2 // - return the trimmed s // char *s_trim(char *s) { char *cp1; // for parsing the whole s char *cp2; // for shifting & padding // skip leading spaces, shift remaining chars for (cp1=s; isspace(*cp1); cp1++ ) // skip leading spaces, via cp1 ; for (cp2=s; *cp1; cp1++, cp2++) // shift left remaining chars, via cp2 *cp2 = *cp1; *cp2-- = 0; // mark new end of string for s // replace trailing spaces with '\0' while ( cp2 > s && isspace(*cp2) ) *cp2-- = 0; // pad with '\0's return s; } 

不是最好的方式,但它的工作原理

 char* Trim(char* str) { int len = strlen(str); char* buff = new char[len]; int i = 0; memset(buff,0,len*sizeof(char)); do{ if(isspace(*str)) continue; buff[i] = *str; ++i; } while(*(++str) != '\0'); return buff; } 
 void inPlaceStrTrim(char* str) { int k = 0; int i = 0; for (i=0; str[i] != '\0';) { if (isspace(str[i])) { // we have got a space... k = i; for (int j=i; j 

最简单的事情就是简单的循环。 我将假设您希望修剪后的字符串返回原位。

 char * strTrim(char * s){ int ix, jx; int len ; char * buf len = strlen(s); /* possibly should use strnlen */ buf = (char *) malloc(strlen(s)+1); for(ix=0, jx=0; ix < len; ix++){ if(!isspace(s[ix])) buf[jx++] = s[ix]; buf[jx] = '\0'; strncpy(s, buf, jx); /* always looks as far as the null, but who cares? */ free(buf); /* no good leak goes unpunished */ return s; /* modifies s in place *and* returns it for swank */ } 

这也消除了嵌入的空白,如果String.Trim没有,那么它需要更多的逻辑。