簡體   English   中英

如何在使用strtok()后恢復字符串

[英]How to restore string after using strtok()

我有一個項目,我需要根據每行中的第二個,第三個等單詞排序多行文本,而不是第一個單詞。 例如,

this line is first

but this line is second

finally there is this line

而你選擇按第二個單詞排序,它會變成

this line is first

finally there is this line

but this line is second

(因為線在此之前有)

我有一個指向包含每一行的char數組的指針。 到目前為止,我所做的是使用strtok()將每一行拆分為第二個單詞,但這會將整個字符串更改為該單詞並將其存儲在我的數組中。 我的tokenize位代碼如下所示:

 for (i = 0; i < numLines; i++) {
   char* token = strtok(labels[i], " ");
   token = strtok(NULL, " ");
   labels[i] = token;
 }

這會給我每一行的第二個字,因為我兩次打電話給strtok。 然后我對那些話進行排序。 (行,這,那里)但是,我需要將字符串重新組合成原始形式。 我知道strtok會將標記轉換為'\\ 0',但我還沒有找到一種方法來恢復原始字符串。

我確定答案在於使用指針,但我很困惑接下來我需要做什么。

我應該提一下,我正在讀取輸入文件中的行,如下所示:

for (i = 0; i < numLines && fgets(buffer, sizeof(buffer), fp) != 0; i++) {
  labels[i] = strdup(buffer);

編輯:我的find_offset方法

size_t find_offset(const char *s, int n) {
  size_t len;
  while (n > 0) {
     len = strspn(s, " ");
     s += len;
  }

  return len;
} 

編輯2:用於排序的相關代碼

//Getting the line and offset
for (i = 0; i < numLines && fgets(buffer, sizeof(buffer), fp) != 0; i++) {
   labels[i].line = strdup(buffer);
   labels[i].offset = find_offset(labels[i].line, nth);
}


int n = sizeof(labels) / sizeof(labels[0]);
qsort(labels, n, sizeof(*labels), myCompare);
for (i = 0; i < numLines; i++)
  printf("%d: %s", i, labels[i].line); //Print the sorted lines


int myCompare(const void* a, const void* b) { //Compare function
  xline *xlineA = (xline *)a;
  xline *xlineB = (xline *)b;

  return strcmp(xlineA->line + xlineA->offset, xlineB->line + xlineB->offset);
}

也許不是亂用strtok() ,使用strspn(), strcspn()來解析字符串的標記。 那么原始字符串甚至可以是const

#include <stdio.h>
#include <string.h>

int main(void) {
  const char str[] = "this line is first";
  const char *s = str;
  while (*(s += strspn(s, " ")) != '\0') {
    size_t len = strcspn(s, " ");

    // Instead of printing, use the nth parsed token for key sorting
    printf("<%.*s>\n", (int) len, s);

    s += len;
  }
}

產量

<this>
<line>
<is>
<first>

要么

不要排序

排序結構

typedef struct {
  char *line;
  size_t offset;
} xline;

偽代碼

int fcmp(a, b) {
  return strcmp(a->line + a->offset, b->line + b->offset);
}

size_t find_offset_of_nth_word(const char *s, n) {
  while (n > 0) {
    use strspn(), strcspn() like above
  }
}

main() {
  int nth = ...;
  xline labels[numLines];
  for (i = 0; i < numLines && fgets(buffer, sizeof(buffer), fp) != 0; i++) {
     labels[i].line = strdup(buffer);
     labels[i].offset = find_offset_of_nth_word(nth);
  }

  qsort(labels, i, sizeof *labels, fcmp);

}

要么

讀完每一行后,找到帶有strspn(), strcspn()nth標記strspn(), strcspn() "aaa bbb ccc ddd \\n"改為"ccd ddd \\naaa bbb " ,然后排序,然后重新排序。


在所有情況下,不要使用strtok() - 丟失太多信息。

我需要將字符串重新組合成原始形式。 我知道strtok會將標記轉換為'\\ 0',但我還沒有找到一種方法來恢復原始字符串。

更好的是避免,如果你想保持他們破壞在首位的原始字符串,特別是能避免丟失指向他們。 假設可以安全地假設每行中至少有三個單詞,並且第二行與第一行和第三行分開,每側只有一個空格,則可以撤消strtok()用字符串終止符替換分隔符。 但是,一旦失去整個字符串,就沒有安全或可靠的方法來恢復整個字符串的開頭。

我建議創建一個輔助數組,在其中記錄每個句子的第二個單詞的信息 - 在不損壞原始句子的情況下獲得 - 然后對輔助數組和句子數組進行共同排序。 要記錄在輔助陣列中的信息可以是句子的第二個單詞的副本,它們的偏移和長度,或類似的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM