【问题标题】:Removing the Rest of a String删除字符串的其余部分
【发布时间】:2020-11-09 00:56:08
【问题描述】:

刚开始尝试使用 C,来自 Java 背景,我在尝试删除字符串的一部分时遇到了问题。这个的基本逻辑是我有一个字符串(我发现它是 C 中的一个字符数组,非常酷!),一旦在遍历这个字符串时满足某个条件,我想删除其余的细绳。例如,如果我的字符串是“hello world!”,并且我将条件设置为空格,我想删除该空格后面的所有内容,所以只需返回“hello”。我有一个想法,记下满足条件的索引,并创建第二个数组并填充它,然后删除前一个数组,但是我确信有更好的方法来做到这一点。如果有人可以提供帮助,将不胜感激,提前谢谢大家!

编辑: 想法是我想接受用户输入,我的具体情况是如果有一个点“。”它有一个“下一行”作为前一个元素和下一个元素,或者一个“下一行”作为前一个元素,一个空值作为下一个参数。所以基本上:

(if string[n] == ".") 
{ 
   if((string[n-1]==\n && string[n+1]==\n) || (string[n-1]==\n && string[n+1]== 
   null)
   { Then remove everything past this point} 
}
input: 
hello world 
this is ok.
.
Everything here will be deleted. 


Output: 
hello world 
this is ok.
.

编辑 2: 到目前为止,谢谢大家的一些很好的建议,但是我仍然遇到他程序的问题,所以在这里我将发布到目前为止的主要方法的代码(只是测试删除字符串部分的其余部分(尚未添加用户输入) )。

//main method
int main(void)
{
    char test = "This is a sample text.\
The file will be terminated by a single dot: .\
The program continues processing the lines because the dot (.)\
did not appear at the beginning.\
. even though this line starts with a dot, it is not a single dot.\
The program stops processing lines right here.\
.\
You wont be able to feed any more lines to the program.";
 int n =0; 
    while(test[n] != NULL)
    {
        if (test[n]=='.') 
        { 
           if ((test[n-1]=='\n' && test[n+1]=='\n') || (test[n-1]=='\n' && test[n+1]==NULL)) 
           { 
              test[n] = '\0';
           } 
        } 
        n++;
    }
    printf("%c\n",test);
    return 0;
}

这里的想法是,我最终会将字符串逐字发送到插入排序链表函数,并在删除指定的点之后的所有内容后按字母顺序对字符串进行排序。现在的问题是由于某种原因我遇到了错误,如果有人可以帮助解决它们,我将不胜感激。

Errors in main:  

345500375/source.c: In function ‘main’:
345500375/source.c:64:17: warning: initialization makes integer from pointer without a cast [-Wint-conversion]
     char test = "This is a sample text.\
                 ^~~~~~~~~~~~~~~~~~~~~~~~
 The file will be terminated by a single dot: .\
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 The program continues processing the lines because the dot (.)\
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 did not appear at the beginning.\
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 . even though this line starts with a dot, it is not a single dot.\
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 The program stops processing lines right here.\
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 .\
 ~~               
 You wont be able to feed any more lines to the program.";
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
345500375/source.c:73:15: error: subscripted value is neither array nor pointer nor vector
     while(test[n] != NULL)
               ^
345500375/source.c:75:17: error: subscripted value is neither array nor pointer nor vector
         if (test[n]=='.')
                 ^
345500375/source.c:77:21: error: subscripted value is neither array nor pointer nor vector
            if ((test[n-1]=='\n' && test[n+1]=='\n') || (test[n-1]=='\n' && test[n+1]==NULL))
                     ^
345500375/source.c:77:40: error: subscripted value is neither array nor pointer nor vector
            if ((test[n-1]=='\n' && test[n+1]=='\n') || (test[n-1]=='\n' && test[n+1]==NULL))
                                        ^
345500375/source.c:77:61: error: subscripted value is neither array nor pointer nor vector
            if ((test[n-1]=='\n' && test[n+1]=='\n') || (test[n-1]=='\n' && test[n+1]==NULL))
                                                             ^
345500375/source.c:77:80: error: subscripted value is neither array nor pointer nor vector
            if ((test[n-1]=='\n' && test[n+1]=='\n') || (test[n-1]=='\n' && test[n+1]==NULL))
                                                                                ^
345500375/source.c:79:19: error: subscripted value is neither array nor pointer nor vector
               test[n] = '\0';
                   ^

【问题讨论】:

  • 这一切都取决于字符串的存储方式以及您想要实际执行的操作,如果您可以写入它,只需在您希望它结束​​的字符串中戳一个 '\0'
  • 听起来你可能想要strtok: link to documentation
  • 是的,很抱歉漏掉了。想法是我想接受用户输入,我的具体情况是如果有一个点“。”它有一个“下一行”作为前一个元素和下一个元素,或者一个“下一行”作为前一个元素,一个 null 作为下一个参数。
  • 使用char test[]创建数组,而不是char
  • @abdcg 那是因为 NULL 是一个整数,而不是字符类型,我假设您正在寻找空字符,这意味着您可能想要更接近:test[n] != '\0';。此外,要输出一个以 null 结尾的字符串,您可以使用 %s; %c 输出单个字符。

标签: arrays c string gcc


【解决方案1】:

这样就可以解决问题(假设所有索引都在范围内):

if (string[n]=='.') { 
   if (string[n-1]=='\n' && string[n+1]=='\n') { 
      string[n+1] = '\0';
   } 
}

【讨论】:

  • 假设这是一个循环,它只需要一个break 就可以了。
  • 此解决方案的问题是在字符串的第一个位置找到.,并且您将访问第一个字符之前的字符,这是未定义的行为。我>
  • 另外,您将把 '\0' 字符放在最后一个 '\n' 的位置,而不是点的位置(在位置 n 或 @987654327 @ 语句不应该执行)
  • @LuisColorado 是的,但我的解决方案的重点是让 OP 了解如何实际解决问题。我已经说过我假设所有索引都在范围内,从这里很容易概括。
  • @MustafaQuraish,更重要的是要特别注意不要编写错误的代码。或者如果您是故意这样做的,请解释错误代码的确切范围。没有任何理由可以在没有解释的情况下编写糟糕的代码。
【解决方案2】:

我假设您使用char* 作为您的“字符串”。事实上,这根本不是一个可以与 Java 的字符串或大多数语言相比的字符串。

许多开发人员和库(和语言,可能除了 Pascal 之外)使用更接近结构的东西来存储字符串,例如:

struct string {
    char * pointer;
    unsigned short length;
};

这提供了一些优点,即 O(1) 时间复杂度长度查找。

在您的情况下,它可以让您从旧字符串快速创建子字符串或切片,而根本不修改内存。

如果我们使用我提供的那个非常基本的结构作为示例:

// note: you need the keyword struct behind every usage of a struct, many times structs are type aliased solely because of that 
struct string userInput = {
    .pointer = "words in str.ing",
    .length = 16
};
// ...
unsigned short whereDotIs = 13;

struct string result = {
    .pointer = userInput.pointer,
    .length = whereDotIs
};

此时,您可以读过去点 (.),但它不是我们现在建立的“字符串”抽象概念的一部分,它只是随机存储器.

尽管在某些情况下您需要使用以空字符结尾的字符指针,@Mustafa Quraish 的答案就足够了,除非字符串是 const 限定的,在这种情况下您必须坚持原来的解决方案:将数组复制到一个新数组中。

【讨论】:

    【解决方案3】:

    首先,您的编译错误与您声明了char 变量而不是char 数组这一事实背道而驰。你可以用char variable[]声明一个char数组并用一个字符串初始化它(在这种情况下你得到一个n元素的数组,其中n是以字符为单位的字符串大小,加上最后一个\0 char ) 或者你可以指定一个长度(在括号之间)然后也初始化(数组的未使用部分用\0 字符填充,如char variable[30] = "hello"; /* the five chars of "hello" plus 25 '\0' chars */

    在 java 中,Strings 是不可变的。您可以从中提取子字符串,但它们会成为 String 类的不同实例。在 C 中,字符串只是 chars 的数组。对于处理字符串的 C 函数,字符串会一直延伸,直到函数遇到字符 '\0',并且当找到 '\0' 时,数组的所有处理(仍然是相同的长度)终止。所以在某个时候剪切字符串的最好方法是放一个'\0'字符。

    顺便说一句,不要使用最后的\ 在下一行继续一个字符串,新的 C 语法已经过时了(比这里的一些读者更老,编译器将删除换行符和来自输入源的反斜杠,使续行继续字符串文字,就好像您将它写在前一行的末尾一样——恕我直言,这不是您想要的)。新语法允许字符串在下一行继续,只需终止它(使用")并在下一行重新开始(再次使用"),如下所示(所以这段代码相当于你写的) :

       char test[] = /* now test is a char array, you need the pair of [] brackets */
          "This is a sample text."
          "The file will be terminated by a single dot: ."
          "The program continues processing the lines because the dot (.)"
          "did not appear at the beginning."
          ". even though this line starts with a dot, it is not a single dot."
          "The program stops processing lines right here."
          "."
          "You wont be able to feed any more lines to the program.";
    

    也相当于这个:

       char test[] = /* now test is a char array, you need the pair of [] brackets */
          "This is a sample text.The file will be terminated by a single dot: .The program continues processing the lines because the dot (.)did not appear at the beginning.. even though this line starts with a dot, it is not a single dot.The program stops processing lines right here..You wont be able to feed any more lines to the program.";
    

    但如果您希望将换行符包含在字符串文字中,那么您有 包括明确的\n 字符,如下所示:

       char test[] = /* now test is a char array, you need the pair of [] brackets */
          "This is a sample text.\n"
          "The file will be terminated by a single dot: .\n"
          "The program continues processing the lines because the dot (.)\n"
          "did not appear at the beginning.\n"
          ". even though this line starts with a dot, it is not a single dot.\n"
          "The program stops processing lines right here.\n"
          ".\n"
          "You wont be able to feed any more lines to the program.\n";
    

    如果你想以 前后的单点结束字符串 \n,那么你可以使用strstr()函数找到你关注的序列的位置,并在合适的位置放置一个'\0'

        char *p = strstr(test, "\n.\n");
        /* p (if found, e.g. not NULL) will point to the first \n, so we must use the
         * address of the next char */
        /* we can do the following as we know that the string extends past the
         * position in which the dot is, because we have found (in the string) the
         * sequence, that extends past the place we are going to put it. */
        if (p)  /* this is the same as if (p != NULL) */
            p[1] = '\0';  /* put a \0 in the position of the dot */
        printf("The cut text is: %s", test);
    

    您的代码还有另一个错误,这次很严重,这将导致您出现运行时问题(编译器可能无法检测到或者直到代码已经使用了很长时间),因为您可以访问(而 C 没有如果您碰巧在数组的第一个位置找到一个点字符,则不要像 java 那样检查边界错误。 n 将是0,当您尝试在if 语句中访问test[n-1] 时,您将访问数组中的前一个到第一个元素(这是test[-1])。这会在 java 中抛出一个ArrayOutOfBoundsException,但 C 没有这种保护。这个问题不会发生在字符串的末尾(尽管您还可以访问点的下一个字符),因为即使您在字符串的末尾找到点,下面的字符(并且必须有一个)也会是最后一个\0 char,所以不会出现问题(因为它在其他一些答案中也被错误地指出)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 2015-09-16
      • 2015-11-12
      • 2022-12-03
      • 2017-07-02
      相关资源
      最近更新 更多