C数组排序忽略特殊字符

时间:2017-11-16 23:33:47

标签: c sorting

char temp[size];
int b, z;
for (b = 0; b < size; b++) {
    for (z = 0; z < size; z++) {
        if (strcmp(processNames[b], processNames[z]) < 0) {
            strcpy(temp, processNames[b]);
            strcpy(processNames[b], processNames[z]);
            strcpy(processNames[z], temp);
        }         
    }
}

我正在排序char ** processNames;

的列表

我希望它像这样排序:

abc 
bee
george
(sally)
saw
thomas
zebra

然而,它是这样排序的:

(sally)
abc 
bee
george
saw
thomas
zebra

谢谢,我不知道如何否定特殊字符,只对字母表进行排序。谢谢!

2 个答案:

答案 0 :(得分:2)

您可以预处理字符串并使用strcmp来比较已处理的字符串:

// Inside the two-layer for loop
char newb[size], newz[size];
int ib, iz, tb = 0, tz = 0;
for (ib = 0; processNames[b][ib] != '\0'; ib++){
    if (isalpha(processNames[b][ib])) {
        newb[tb++] = processNames[b][ib];
    }
}
newb[tb] = 0;
for (iz = 0; processNames[z][iz] != '\0'; iz++){
    if (isalpha(processNames[z][iz])) {
        newz[tz++] = processNames[z][iz];
    }
}
newz[tz] = 0;

if (strcmp(newb, newz)) {
    // swap the ORIGINAL string here
}

上面的代码是我最初提出的。这是非常低效的,不推荐。或者,您可以编写自己的mystrcmp()实现:

int mystrcmp(const char* a, const char *b){
    while (*a && *b) {
        while (*a && !isalpha(*a)) a++;
        while (*b && !isalpha(*b)) b++;
        if (*a - *b) return *a - *b;
        a++, b++;
    }
    return *a - *b;
}

答案 1 :(得分:2)

“排序”的意思是“把事情整理好”。什么顺序?订单由一些 thing 定义,告诉我们哪两个项首先出现。

在您的代码中,您使用strcmp来决定首先使用哪个项目。这是决定订单的事物。由于strcmp正在发出您不想要的订单,因此您需要其他功能。在这种情况下,您必须编写自己的函数。

您的函数应该使用两个字符串(通过指向char),检查字符串,并返回一个值以指示第一个字符串应该在第二个字符串之前还是之后(或者它们是否相等)。

由于这可能是课堂作业,我会留给你思考必要的比较功能。

替代

在适当的情况下,有一种替代方法可能会在专业部署的代码中使用。我推荐上面的内容,因为它适用于类赋值 - 它解决了这个赋值似乎所针对的关键原则。

另一种方法是在进行排序之前预处理所有列表项。由于您要对名称的非特殊字符进行排序,因此您可以通过创建删除了特殊字符的名称副本来扩充列表。这些新版本将是您的“排序键” - 它们是您用来决定订单而不是原始名称的值。您可以将它们与strcmp进行比较。

此方法需要为新版本的名称分配新内存,在排序时管理密钥和名称,并在排序后释放内存。在开始排序之前需要一些开销。但是,如果有大量的东西可以用相当多的特殊字符排序,那么预先做额外的工作可以带来更好的整体性能。

(同样,我只是为了完整性而提到这一点。它可能在这类课程作业中没用,只是计算机科学专业的学生应该学习的东西。)

奖金备注

你说你正在排序char **ProcessNames的数组。在这种情况下,可能没有必要使用strcpy移动字符串本身。相反,您可以简单地将指针移动到字符串。例如,如果要交换ProcessNames[4]ProcessNames[7],只需复制指针ProcessNames[4],将ProcessNames[4]设置为指针{{1} },并将ProcessNames[7]设置为您创建的临时副本。这通常比移动字符串更快。

正如其他人所说,使用ProcessNames[7]开始z循环可能不是一个好主意。您可能想要z = 0

您的代码使用z = b+1表示字符串缓冲区(size)的大小和char temp[size]数组(ProcessNames)的大小。要排序的字符串数量不太可能与字符串的最大长度相同。您应该确保在每个实例中使用正确的大小。