【发布时间】:2019-01-30 21:53:27
【问题描述】:
我有一个项目,我需要根据每行中的第二个、第三个等单词而不是第一个单词对多行文本进行排序。例如,
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() 将每一行拆分为第二个单词,但这会将整个字符串更改为该单词并将其存储在我的数组中。我的标记位代码如下所示:
for (i = 0; i < numLines; i++) {
char* token = strtok(labels[i], " ");
token = strtok(NULL, " ");
labels[i] = token;
}
这会给我每行的第二个单词,因为我调用了 strtok 两次。然后我对这些词进行排序。 (line, this, there) 但是,我需要将字符串以原始形式重新组合在一起。我知道 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);
}
【问题讨论】:
-
最简单的做法是先复制字符串。
-
Waring:如果你把字符串重新组合在一起,那么
labels[i]将不会指向一个好的子字符串。你确定要这个吗? -
如果我复制了字符串,那么我怎样才能让它进入新的顺序?
-
我注意到您在调用
strtok()时使用了一个分隔符,即一个空格。您可以提供一个定界符列表,但您以后无法分辨出这些定界符中的哪一个是被空字节删除的定界符。因此,在一般情况下,您无法分辨strtok()做了什么。如果您记录了数据的原始长度并且只使用了一个分隔符,那么您可以安排将strtok()添加的空字节替换为分隔符,从而恢复字符串。在一般情况下,您不能这样做。在标记之前复制字符串,或避免使用strtok()。 -
while (n > 0) { len = strspn(s, " "); s += len; }是一个无限循环。