限stdio.h
如果您仅限于使用stdio.h 中提供的功能,那么您只需编写与string.h 所需功能类似的字符串处理功能。对于排序,除非您想使用诸如快速排序或合并排序之类的分区排序,否则您将被限制为嵌套循环排序——它更易于编写——但速度要慢得多。 (但对于 1000 左右的字符串,没关系,100,000 - 然后会有可感知的差异)
要比较字符串,您可以编写一个简单的strcmp()like 函数,不需要额外的标头,例如
/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
if (!a && !b) return 0;
if ( a && !b) return 1;
if (!a && b) return -1;
for (; *a && *a == *b; a++, b++) {}
return (*a > *b) - (*a < *b);
}
如果您没有声明一组额外的排序指针,那么您将需要在二维数组的行(一维数组)之间复制字符串。您可以编写一个不需要标头的简单 strcpy() 类似函数:
/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
char *p = dest;
do {
*p++ = *src;
} while (*src++);
return dest;
}
最后,您唯一需要的就是排序函数。 (您将无法编写快速的qsort() 替换)微不足道的冒泡排序 就可以了。您可以编写一个函数来将您的二维字符串数组排序为:
#define NCHR 50
/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
size_t i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < (n-1); j++) {
if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
char temp[NCHR];
strcpy_nohdr (temp, a[j + 1]);
strcpy_nohdr (a[j + 1], a[j]);
strcpy_nohdr (a[j], temp);
}
}
}
}
如果您将这些全部放在一个简短的示例中(之前与 qsort() 使用的相同,您将:
#include <stdio.h>
#define NCHR 50
/** string compare without string.h */
int strcmp_nohdr (const char *a, const char *b)
{
if (!a && !b) return 0;
if ( a && !b) return 1;
if (!a && b) return -1;
for (; *a && *a == *b; a++, b++) {}
return (*a > *b) - (*a < *b);
}
/** string copy wihout string.h */
char *strcpy_nohdr (char *dest, const char *src)
{
char *p = dest;
do {
*p++ = *src;
} while (*src++);
return dest;
}
/** bubble sort of strings in 'a' (highly inefficient) */
void bubblesort2D (char (*a)[NCHR], size_t n)
{
size_t i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < (n-1); j++) {
if (strcmp_nohdr(a[j], a[j + 1]) > 0) {
char temp[NCHR];
strcpy_nohdr (temp, a[j + 1]);
strcpy_nohdr (a[j + 1], a[j]);
strcpy_nohdr (a[j], temp);
}
}
}
}
int main (void) {
char strings[][NCHR] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
size_t n = sizeof strings / sizeof *strings;
bubblesort2D (strings, n);
for (size_t i = 0; i < n; i++)
puts (strings[i]);
}
使用/输出示例
结果和之前一样:
$ ./bin/sort_2d_strings_stdio
alligators
frogs
opossums
racoons
zebra
由于我最初写了qsort() 答案,我将把它留在下面,作为您在实践中处理排序(无论您正在排序的数组)的方式。
实际使用qsort()
C 提供qsort(),它将根据您编写的compare 函数对任何对象的数组进行排序,以告诉qsort() 如何比较数组的元素。对于字符串,您只想返回strcmp() 的结果。 compare 函数的每个参数都有一个指向数组元素的 Pointers。由于它是一个void* 指针,因此您必须将指针转换回正确的类型。
在 C 中回想一下,二维数组只是 一维数组的数组。在您的情况下,它是一个包含 50 个字符的数组。指向 50 个字符数组的指针的类型为 char (*)[50],因此您的 qsort() compare 函数可以编写如下:
int cmpstr50 (const void *a, const void *b)
{
const char *pa = *(char (*)[50])a,
*pb = *(char (*)[50])b;
return strcmp (pa, pb);
}
其中每个参数都是指向char [50] 数组的指针。没有什么比这更容易了。此外,qsort() 使用的算法将比您使用嵌套循环编写的算法快几个数量级。
您的案例的完整示例是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmpstr50 (const void *a, const void *b)
{
const char *pa = *(char (*)[50])a,
*pb = *(char (*)[50])b;
return strcmp (pa, pb);
}
int main (void) {
char strings[][50] = { "zebra", "alligators", "frogs", "racoons", "opossums" };
size_t n = sizeof strings / sizeof *strings;
qsort (strings, n, sizeof *strings, cmpstr50);
for (size_t i = 0; i < n; i++)
puts (strings[i]);
}
在编写 compare 函数后,对字符串数组(或任何数组)进行排序所需的只是对 qsort() 的一次调用:
qsort (strings, n, sizeof *strings, cmpstr50);
比尝试重新发明轮子要简单得多。
使用/输出示例
$ ./bin/qsort_2d_strings
alligators
frogs
opossums
racoons
zebra
如果您还有其他问题,请告诉我。