C - Strtok() ,将字符串拆分为 '\n' 但保留分隔符

C - Strtok() , split the string on '\n' but keep the delimiter

我的 C 程序有以下问题。它的部分功能是读取一些文本并将其拆分成句子,然后将这些句子写入文件。

我使用 Strtok() 来分割句子中的文本块(一个句子在出现 \n 时结束)但是当有一个句子只包含文本块中的 \n 字符时,例如:

////////////////////////////

您好,这是一些示例文本
这是第二句

上面这句话只是换行
这是最后一句话。

///////////////////////////

文件输出如下:

0 您好,这是一些示例文本
1 这是第二句
2 上面这句只是换行
3 这是最后一句。

////////////////////////////////////////// ///////

虽然应该是:

0 您好,这是一些示例文本
1 这是第二句
2
3 上面这句话就是\n
4 这是最后一句。

//////////////////////////////////

保存字符串的文件应该用作日志文件,这就是为什么我必须将文本块拆分为以 \n 分割的句子,并且在将每个句子写入文件之前在前面有一个整数。

这是与此功能相关的代码:

int counter = 0; // Used for counting
const char s[2] = "\n"; // Used for tokenization

// ............

char *token;
      token = strtok(input,s);
      while(token != NULL){
        fprintf(logs, "%d ", counter);
        fprintf(logs, "%s\n" , token); // Add the new line character here since it is removed from the tokenization process
        counter++;
        token = strtok(NULL, s);
      }

// .........

有什么方法可以让"empty sentence"(一个只是\n字符的句子)处理得当?

也许另一个函数可以代替 strtok()?

如果您正在从文件中读取输入,则可以使用流(使用 fopen())并使用 getline()

否则你可以编写一个函数来计算 \n 的数量,分配一个 char* 的数组,然后逐行填充它。

编辑:如果您不想自己编写代码,您可以通过一些小的研究轻松找到它

您在 strtok 的分隔符集中包含了换行符 \n

如果输入字符串是有效的读取,并且如果第一次调用 strtok returns NULL,那么它是一个空行,您可以随后处理它。

token = strtok(input,s);
if(token == NULL) {
    fprintf(logs, "%d\n", counter);
    counter++;
}
while(token != NULL){                   // the `while` serves as `else`
    fprintf(logs, "%d ", counter);
    fprintf(logs, "%s\n" , token);
    counter++;
    token = strtok(NULL, s);
}

您可能应该按照评论的建议使用 strstrstrchr,但是如果您的应用程序出于某种原因需要 strtok,您可以节省每个结尾的位置句子并确定多个换行符(\n)通过指针算法顺序出现。

未经测试的粗略示例代码:

int counter = 0; // Used for counting
const char* last_sentence;


// ............
      last_sentence = input;
      char *token;
      token = strtok(input,"\n");
      while(token != NULL){
        int i;
        for (i = (token - last_sentence);i > 1; i--){
          // this gets called once for each empty line.
          fprintf(logs, "%d \n", counter++);
        }
        fprintf(logs, "%d %s\n", counter++, token);

        last_sentence = token + strlen(token);
        token = strtok(NULL, "\n");
      }

// .........

编辑:添加了 strchr

示例

使用 strchr 即使不是更简单,也同样简单,尤其是因为您只有一个分隔符。下面的代码接受你的句子,并将它们拆分出来。它只是打印它们,但您可以根据自己的目的轻松扩展它。

#include <stdio.h>
#include <string.h>
const char* sentences = "Hello, this is some sample text\n"
                        "This is the second sentence\n"
                        "\n"
                        "The sentence above is just a new line\n"
                        "This is the last sentence.\n";

void parse(const char* input){
  char *start, *end;
  unsigned count = 0;

  // the cast to (char*) is because i'm going to change the pointer, not because i'm going to change the value.
  start = end = (char*) input; 

  while( (end = strchr(start, '\n')) ){
      printf("%d %.*s", count++, (int)(end - start + 1), start);
      start = end + 1;
  }
}

int main(void){
  parse(sentences);
}