如何优雅地遍历 C 中的字符串到最后



我正在研究一个 C 函数,该函数必须输入一个字符串并仅在开头删除所有非字母字符。 例如,如果输入字符串"123 456 My dog has fleas."则输出字符串必须是:"My dog has fleas."

这是我所拥有的,适用于上面的例子:

int isALetter(char x){
   // Checks to see is x is an ASCII letter
   if(  ((int)x>=65 && (int)x<=90)  ||  ((int)x>=97 && (int)x<=122)  )
      return 0;      // TRUE
   return 1;         // FALSE
}
char* removeNonLettersAtBeginning(char* str){
   while( isALetter(str[0]) == 1  &&  &str[0] != NULL )
      str++;
   return str;
}

这就是困扰我的地方... 如果字符串根本没有字母,则代码似乎不起作用。 如果我提交字符串" "(没有字母),那么我会得到" XDG_SESSION_ID=3818 "。 我不知道那个字符串是什么,但我假设它在系统中是"垃圾"。

但是我的removeNonLettersAtBeginning()函数应该返回一个"字符串,一个空字符串。 我无法弄清楚问题是什么,但我敢打赌它就在这里:

   while( isALetter(str[0]) == 1  &&  &str[0] != NULL )

该行"&str[0] != NULL"部分是确保我不会跑掉字符串的末尾;我正在尝试检查我是否点击了终止字符串的 Null 字符。 有人看到我哪里出错了吗?

您检查空终止符是错误的,空终止符''不是NULL

#include <stdio.h>
int isALetter(char x){
   // Checks to see is x is an ASCII letter
   if( (x>='A' && x<='Z') || (x>='a' && x<='z') )
      return 0;      // TRUE
   return 1;         // FALSE
}
char* removeNonLettersAtBeginning(char* str){
   if (str != NULL)
   {
      while( isALetter(*str) == 1  &&  *str != '' )
         str++;
   }
   return str;
}
int main (void)
{
    char test_string[] = "        testn";
    char *test_ptr = test_string;
    printf ("%s", test_ptr);
    test_ptr = removeNonLettersAtBeginning(test_ptr);
    printf ("%s", test_ptr);
}

作为旁注,为了使您的代码更具可读性,请避免使用幻数,如 6590 。如图所示,您可以轻松使用字符来执行此操作:'A''Z'...

你写:

while( isALetter(str[0]) == 1  &&  &str[0] != NULL ) //error in str[0] 
      str++;                                         //it must be *str

在这里,您使用了 char * str,它将指向要测试的字符串。

正如您所说,您要从字符串中删除所有非字符。但是,您以错误的方式使用了 char 类型的指针。

无错误代码:

 while( isALetter(*str) == 1  &&  *str != '')  
          str++;         

它应该为你工作

,有利于:)

这是另一种方法。

#include <ctype.h>
...
void stripNonAlpha( char *str )
{
  size_t r = 0, w = 0; // read and write indices
  /**
   * Find the first alpha character in the string
   */
  while ( str[r] && !isalpha( str[r] ) )
    r++;
  /**
   * Shift remaining characters to the left, including the 0 terminator
   */
  while ( (str[w++] = str[r++] ) )
    ; //empty loop
}

基本上,此代码搜索字符串中的第一个字母字符;一旦找到,该字符和所有后续字符将复制到字符串的初始部分。 例如,让我们将字符串"123 test" . 最初,一切看起来都是这样:

  r
  |
  v
+---+---+---+---+---+---+---+---+---+
|'1'|'2'|'3'|' '|'t'|'e'|'s'|'t'| 0 |
+---+---+---+---+---+---+---+---+---+
  ^
  |
  w

第一个循环检查索引r处字符的值;虽然它既不是字符串的末尾也不是字母字符,但前进r。 在循环结束时,我们有这个:

                  r
                  |
                  v
+---+---+---+---+---+---+---+---+---+
|'1'|'2'|'3'|' '|'t'|'e'|'s'|'t'| 0 |
+---+---+---+---+---+---+---+---+---+
  ^
  |
  w

第二个循环从r复制字符并将它们写入w(最多并包括 0 终止符),如下所示:

                      r
                      |
                      v
+---+---+---+---+---+---+---+---+---+
|'t'|'2'|'3'|' '|'t'|'e'|'s'|'t'| 0 |
+---+---+---+---+---+---+---+---+---+
      ^
      |
      w
                          r
                          |
                          v
+---+---+---+---+---+---+---+---+---+
|'t'|'e'|'3'|' '|'t'|'e'|'s'|'t'| 0 |
+---+---+---+---+---+---+---+---+---+
          ^
          |
          w
                              r
                              |
                              v
+---+---+---+---+---+---+---+---+---+
|'t'|'e'|'s'|' '|'t'|'e'|'s'|'t'| 0 |
+---+---+---+---+---+---+---+---+---+
              ^
              |
              w
                                  r
                                  |
                                  v
+---+---+---+---+---+---+---+---+---+
|'t'|'e'|'s'|'t'|'t'|'e'|'s'|'t'| 0 |
+---+---+---+---+---+---+---+---+---+
                  ^
                  |
                  w
                                      r
                                      |
                                      v
+---+---+---+---+---+---+---+---+---+
|'t'|'e'|'s'|'t'| 0 |'e'|'s'|'t'| 0 |
+---+---+---+---+---+---+---+---+---+
                      ^
                      |
                      w

一些示例输出:

$ ./stripper "123 345 this is a test"
before: "123 345 this is a test"
after:  "this is a test"
$ ./stripper "this is a test"
before: "this is a test"
after:  "this is a test"
$ ./stripper "          "
before: "          "
after:  ""
$ ./stripper "12345"
before: "12345"
after:  ""
$ ./stripper "12345 abc 23456"
before: "12345 abc 23456"
after:  "abc 23456"

显然,此操作具有破坏性 - 修改了输入字符串。 如果不希望这样做,则需要写入不同的目标字符串。 这应该很容易弄清楚,通过。

相关内容

  • 没有找到相关文章

最新更新