我有一个C字符串数组:
char test[6] = {'\n', 't', 'e', 's', 't', '\0'}
我想测试字符串是否以空格字符开头(\ n,\ t,\ r),如果是,则重新排列数组,以便将非空白字符移到数组的前面,对于需要删除的每个空格字符,将cstring缩短1。
所以,如果我从一个看起来像的字符串开始:
\n, \t, t, e, s, t, \0
or
\r, t, e, s, t, \0
之后,两个数组的函数将如下所示:
t, e, s, t, \0
t, e, s, t, \0
我有两个问题。我的第一个是我对特殊字符的条件测试不能正常工作
int idx = 0;
if (test[idx] != '\n' || test[idx] != '\r' || test[idx] != '\t')
return;
即使它确实以其中一个特殊字符开头,也会返回。
然而,这似乎也需要进行重大改进。
之后,我不确定如何剪辑字符串。例如,如果字符串以空白字符开头,我需要基本上删除该字符,将其他字符向上移动,并且每次将字符串缩短一次。
基本上,我正在努力解决如何做到这一点的逻辑。
非常感谢任何和所有帮助。提前致谢!
答案 0 :(得分:4)
为什么不向前递增指针直到找到非空白字符?
char* cstr = test;
while (*cstr && (*cstr == '\n' || *cstr == '\r' || *cstr == '\t'))
++cstr;
答案 1 :(得分:2)
正如所写的那样,你的测试是检查角色是否不等于任何空白字符。您需要检查它是否与所有这些不相等。你想要:
int idx = 0;
if (test[idx] != '\n' && test[idx] != '\r' && test[idx] != '\t')
return;
假设idx
是第一个非空白字符的索引,或者是空终结符,你可以像这样缩短字符串:
int i;
for (i = 0; test[idx+i] != '\0'; i++)
test[i] = test[idx+i];
test[i] = '\0';
正如其他人所说,有更优雅的方法可以用isspace()
和指针完成所有这些,但这应该给你基本的想法。
答案 2 :(得分:2)
首先,使用isspace
代替它,它会使代码更简单,并确保代码找到你想不到的空白字符。
其次,如果你必须使用char[]
或必须实际删除空格,那么你将不得不做更多的工作。如果您只需要一个指向字符串开头的指针,它将使生活变得更加容易。字符仍然在内存中,但如果使用指针,它们将不会出现在字符串的开头。
char test[] = "\ntest";
char *test_ptr = test;
while (*test_ptr && isspace(*test_ptr)) {
++test_ptr;
}
/*test_ptr now points to the first non-whitespace character in test, or the NULL character at the end of the string if it was all whitespace.*/
如果在char数组本身的开头需要这个字符串,可以在上面的代码之后使用memmove
来移动字符串(strcpy
将不起作用,因为范围重叠):
/* to be placed after block of code above */
memmove(test, test_ptr, strlen(test)-(test_ptr-test)+1); /* +1 for NULL not automatically copied with memmove */
/* test[0] is now the first non-whitespace character or NULL */
或者由于您使用的是C ++,因此可以使用std::string
路径:
std::string test = "\ntest";
size_t start_pos = test.find_first_not_of("\r\n\t");
if (start_pos != std::string::npos) {
test = test.substr(start_pos, std::string::npos);
} else {
test = "";
}
//test now contains no whitespace in the beginning