【问题标题】:C pointers to functions指向函数的 C 指针
【发布时间】:2010-01-13 17:00:23
【问题描述】:

我正在开发一个程序,该程序根据传递给 main 的参数按字母/数字对输入行进行排序。这是后续练习:

添加字段处理功能,因此可以对行内的字段进行排序,每个字段都根据一组独立的选项进行排序。 (这本书的索引使用 -df 表示索引类别和 -n 表示页码。)

我有点不明白它们对字段的含义。

field_of 函数究竟是做什么的?它是否会增加原始指针字段的时间,字段是非空白字符的字符串?

另外,如果输入了 num_fields,那么 compare 函数将在到达第一个非零比较时返回,对吗?如果结果为零(相等的字符串),那么它不会返回任何东西,因为不需要替换字符串。否则,它返回一个数字。

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

    #define MAX_FIELDS 10

    #define FLAG_DIRECTORY (0x01 << 0)
    #define FLAG_FOLD  (0x01 << 1)
    #define FLAG_NUMERIC (0x01 << 2)
    #define FLAG_REVERSE (0x01 << 3)

    int fieldarray[MAX_FIELDS];
    unsigned char flagarray[MAX_FIELDS];
    int num_fields = 0;

    #define MAXLINES 5000  /* max #lines to be sorted */
    char *lineptr[MAXLINES]; /* pointers to text lines */

    int readlines(char *lineptr[], int nlines);
    void writelines(char *lineptr[], int nlines);

    void qsort(void *lineptr[], int left, int right,
               int (*comp)(void *, void *));

    static char *field_of(char *s, int n);
    static isdir(int c);
    int compare(char *, char *);
    int stringcmp(char *, char *);
    int stringcmpi(char *, char *);
    int dircmp(char *, char *);
    int numcmp(char *, char *);
int main()

     if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
      qsort((void **) lineptr, 0, nlines-1, (int (*)(void *, void *)) compare);
      writelines(lineptr, nlines);
      return 0;
     } else {
      printf("input too big to sort\n");
      return 1;
     }
    }

    #define MAXLEN 1000 /* max length of any input line */
    int getline(char *, int);
    char *alloc(int);



    /* qsort:  sort v[left]...v[right] into increasing order */
    void qsort(void *v[], int left, int right,
               int (*comp)(void *, void *))
    {
     int i, last;
     void swap(void *v[], int, int);

     if (left >= right) /* do nothing if array contains */
      return;   /* fewer than two elements */
     swap(v, left, (left + right)/2);
     last = left;
     for (i = left+1; i <= right; i++)
      if ((*comp)(v[i], v[left]) < 0)
       swap(v, ++last, i);
     swap(v, left, last);
     qsort(v, left, last-1, comp);
     qsort(v, last+1, right, comp);
    }

    void swap(void *v[], int i, int j)
    {
     void *temp;

     temp = v[i];
     v[i] = v[j];
     v[j] = temp;
    }

    static char *field_of(char *s, int n)
    {
     while (isspace(*s))
      s++;
     while (--n > 0) {
      while (!isspace(*s)) {
       if (*s == '\0')
        return NULL;
       s++;
      }
     }

     return s;
    }

    static isdir(int c)
    {
     return isalpha(c) || isdigit(c) || isspace(c);
    }

    int compare_field(char *s1, char *s2, unsigned int flags)
    {
     int d;

     if (flags & FLAG_NUMERIC) {
      d = numcmp(s1, s2);
     } else if (flags & FLAG_DIRECTORY) {
      do {
       while (!isdir(*s1) && !isspace(*s1) && *s1 != '\0')
        s1++;
       while (!isdir(*s2) && !isspace(*s2) && *s2 != '\0')
        s2++;
       if (flags & FLAG_FOLD)
        d = toupper(*s1) - toupper(*s2);
       else
        d = *s1 - *s2;
      } while (d == 0 && !isspace(*s1) && !isspace(*s2)
               && *s1++ != '\0' && *s2++ != '\0');
     } else {
      do {
       if (flags & FLAG_FOLD)
        d = toupper(*s1) - toupper(*s2);
       else
        d = *s1 - *s2;
      } while (d == 0 && !isspace(*s1) && !isspace(*s2)
               && *s1++ != '\0' && *s2++ != '\0');
     }

     if (flags & FLAG_REVERSE)
      return -d;
     else
      return d;
    }

    /* compare:  compare s1 and s2 according to the values of the
     external variables numeric, reverse, fold, and directory. */
    int compare(char *s1, char *s2)
    {
     int i, d;
     char *f1, *f2;

     for (i = 0; i < num_fields; i++) {
      f1 = field_of(s1, fieldarray[i]);
      f2 = field_of(s2, fieldarray[i]);
      d = compare_field(f1, f2, flagarray[i]);
      if (d != 0)
       return d;
     }
     if (numeric)
      d = numcmp(s1, s2);
     else if (directory)
      d = dircmp(s1, s2);
     else
      d = stringcmp(s1, s2);

     if (reverse)
      return -d;
     else
      return d;
    }

    /* stringcmp:  compare s1 and s2 as strings */
    int stringcmp(char *s1, char *s2)
    {
     if (fold)
      return stringcmpi(s1, s2);
     else
      return strcmp(s1, s2);
    }

    /* stringcmpi:  compare s1 and s2 case-insensitively */
    int stringcmpi(char *s1, char *s2)
    {
     while (toupper(*s1) == toupper(*s2)) {
      if (*s1 == '\0')
       return 0;
      s1++;
      s2++;
     }

     return toupper(*s1) - toupper(*s2);
    }

    /* dircmp:  compare s1 and s2 in "directory order" */
    int dircmp(char *s1, char *s2)
    {
     int d;

     do {
      while (!isdir(*s1) && *s1 != '\0')
       s1++;
      while (!isdir(*s2) && *s2 != '\0')
       s2++;
      if (fold)
       d = toupper(*s1) - toupper(*s2);
      else
       d = *s1 - *s2;
     } while (d == 0 && *s1++ != '\0' && *s2++ != '\0');

     return d;
    }

    /* numcmp:  compare s1 and s2 numerically */
    int numcmp(char *s1, char *s2)
    {
     extern double atof(const char *);
     double v1, v2;

     v1 = atof(s1);
     v2 = atof(s2);
     if (v1 < v2)
      return -1;
     else if (v1 > v2)
      return 1;
     else
      return 0;
    }

【问题讨论】:

  • 你会考虑缩短你的代码示例吗?很难说你问的是哪一部分。
  • 老兄,没有冒犯,但你问这个问题的方式并没有帮助自己。 1)这个问题很模糊,没有明确定义的问题 2)这里的代码太多了。将其拉到您遇到问题或您想解释的简短 sn-ps。超过 10 或 15 行代码的问题很少能得到好的答案
  • 是的,对不起...我提到的所有功能都在代码的末尾。我对 field_of 函数和比较函数的一些解释很感兴趣。
  • 如果此代码来自 K&R,可以在这里发布吗?是否侵权?
  • 强指南:如果代码显示垂直滚动条,你必须在发布前缩短它。

标签: c pointers function


【解决方案1】:

字段的概念是该行的子部分。听起来您在询问分隔字段,因此如下一行:

a b 1 2 3

字段 1 为“a”,字段 2 为“b”,以此类推

假设你所有的行都像上面的例子。您可能希望根据字段 3 对行进行数字排序。

虽然我使用了空格分隔字段的示例,但还有其他方法可以定义字段。定义字段的另一种常用方法是使用绝对位置(可能字段 1 从偏移量 0 到 9,而字段 2 从偏移量 10 到 14)。

当您按字段排序时,您需要隔离每行的适当部分并比较这些隔离部分。

最后,当您有多个字段时,您可以进行多重比较。首先比较主要字段,但如果它们相等,则回退到第二个字段。在伪代码中:

# returns -1 if line1 < line2, 0 if line1 == line2, 1 if line1 > line2
int sort(line1, line2):
    foreach fielddefinition:
        line1_field = extract_field(line1)
        line2_field = extract_field(line2)

        if line1_field < line2_field:
            return -1
        elif line2_field < line1_field:
            return 1

        # this field is equal, continue checking with the next field

    # Since all fields are equal, the lines are equal
    return 0

【讨论】:

  • 例如,在行中: abab assd asd field 1 is abab field 2 is assd field 3 is asd 忽略它们之间的所有空格?
  • @Tool - 当然,这是一种完全可以接受的定义字段的方式。有一些变化,但这应该足以让你继续前进。
【解决方案2】:

到目前为止,您似乎一直将每一行视为一个实体。字段概念将允许您的排序程序在行内的子部分(字段)级别上工作。

要求是每个字段都能够接收自己的排序指令:例如。将字段 #2 处理为字符串,将字段 #4 处理为整数值等。

也可能会指定排序所基于的字段的有序列表(使用配置或命令行选项),例如允许通过区号(首先)对姓名和电话号码列表进行排序并按名称(第二个)产生一个排序列表,如

Bob Parker      201 365 7733
Charles Louis   201 123 4444
Alan Black      366 001 9876

等等

另一个含义是程序将收到一些关于如何定位字段的指令(即使用分隔符、固定长度等)。然而,此类信息可能是隐含的,即分配(我假设这是家庭作业),可以指定程序仅处理分隔符为制表符的文件。

顺便说一句:问题的标题(“C 指向函数的指针”)与这个问题有什么关系?

【讨论】:

    【解决方案3】:

    您的field_of 函数采用char *(字符串)指针,跳过它找到的所有空格,跳过一个包含n 空格的单词(字段),然后返回指向字符串中该位置的指针(奇怪的是,该领域的尽头)。如果它到达字符串的末尾,则返回NULL

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-08
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多