【问题标题】:C, function too long for the normC、函数过长不规范
【发布时间】:2014-03-13 07:04:24
【问题描述】:

我需要你的帮助。

首先,这不是我要评分的练习,它来自编程学校,但我这样做只是为了训练。所以帮助我不会是不道德的:)

我正在尝试做一个练习(称为ft_print_comb)。我的功能应该这样做:

$ ./a.exe | cat -e
012, 013, 014, 015, 016, 017, 018, 019, 023, 024, 025, 026, 027, 028, 029, 034, 035, 036, 037, 038, 039, 045, 046, 047, 048, 049, 056, 057, 058, 059, 067, 068, 069, 078, 079, 089, 123, 124, 125, 126, 127, 128, 129, 134, 135, 136, 137, 138, 139, 145, 146, 147, 148, 149, 156, 157, 158, 159, 167, 168, 169, 178, 179, 189, 234, 235, 236, 237, 238, 239, 245, 246, 247, 248, 249, 256, 257, 258, 259, 267, 268, 269, 278, 279, 289, 345, 346, 347, 348, 349, 356, 357, 358, 359, 367, 368, 369, 378, 379, 389, 456, 457, 458, 459, 467, 468, 469, 478, 479, 489, 567, 568, 569, 578, 579, 589, 678, 679, 689, 789
$

如果其中三个数字的组合尚未出现,它基本上会显示 000 到 999 之间的每个数字。例如没有 978,因为 7、8 和 9 已经出现在 789 中。

我写了一些已经有效的东西,看起来像这样:

#include <unistd.h>


void            ft_putchar(char c)
{
    write ( 1, &c, 1);
}

void            ft_print_comb(void)
{
    int     a;
    int     b;
    int     c;

    a = 0;

    while (a < 8)
    {
            b = a + 1;
            while (b < 9)
            {
                    c = b + 1;
                    while (c <= 9)
                    {
                            ft_putchar('0' + a%10);
                            ft_putchar('0' + b%10);
                            ft_putchar('0' + c%10);
                            if (a < 7 || b < 8 || c < 9)
                            {
                                    ft_putchar(',');
                                    ft_putchar(' ');
                            }
                            c++;
                    }
                    b++;
            }
            a++;
    }
    ft_putchar('\n');
}


int             main()
{
    ft_print_comb();
    return(0);
}

但问题是,我有一个非常严格的规范要遵循(Epitech 的规范): - 我不允许使用库中的任何函数,但可以写入(并且写入仅用于 ft_putchar)(无 printf); - 我不能使用'for'; - 我不允许写 'int a, b, c = 0' 或 ft_putchar(a, b, c),它必须像我写的那样(意味着每次都在新行上重写 ft_putchar) ; - 我的函数最长必须为 25 行。 - 我在 main 中调用的函数必须是 void ft_print_comb(void); - 我最多可以有 5 个函数。

差不多就是这样。这个练习是人们在这所学校学习 C 语言的第一天,所以理论上我只需要循环和增量,但我已经尝试了几个小时来拥有 25 行函数,我觉得它超出了我的范围抵达。我考虑过将该函数划分为我会在“void ft_print_comb(void)”中调用的其他函数,但这还不是我掌握的足够多的东西(我在这里是个新手)。

无论如何,感谢您的帮助和您的时间,并为我的英语远非完美感到抱歉。

(编辑) 我做到了,感谢您的回答。这是它的样子:

#include <unistd.h>


void            ft_putchar(char c)
{
    write ( 1, &c, 1);
}

void            ft_printabc(int a, int b, int c)
{
    ft_putchar('0' + a%10);
    ft_putchar('0' + b%10);
    ft_putchar('0' + c%10);
    if (a < 7 || b < 8 || c < 9)
    {
            ft_putchar(',');
            ft_putchar(' ');
    }
}

void            ft_print_comb(void)
{
    int     a;
    int     b;
    int     c;

    a = 0;

    while (a < 8)
    {
            b = a + 1;
            while (b < 9)
            {
                    c = b + 1;
                    while (c <= 9)
                    {
                            ft_printabc(a, b, c);
                            c++;
                    }
                    b++;
            }
            a++;
    }
    ft_putchar('\n');
}


int             main()
{
    ft_print_comb();
    return(0);
}

我不知道你是否理解我被允许这样做,用一种不是我母语的语言来解释规范是相当困难的。归根结底,它远没有我们想要的复杂,但是您的 cmets 帮助了我很多(假设我在 C 中有一些概念,但不多)。

再次感谢大家。

【问题讨论】:

  • 行可以折叠,C不介意:} c++; } b++; } a++; } ft_putchar('\n'); } int main() {
  • 是的,但“他们”会。规范也不允许这样做。他们规范的目标是尽可能拥有最易读的代码,因此禁止破坏行。
  • 尽管这是我看到的唯一方式,但我必须承认。
  • 我认为,如果这个“Epitech 的规范”真的是一个东西,我可以获得比仅仅找到这个问题更好的搜索结果。还有,whilefor 好多少?
  • 我足够好,可以有一个真实的意见,我认为这些规则中的大多数都非常愚蠢。我得到了其中一些的教学价值,但是“没有 cmets”、“空白行计数”、“声明时没有初始化”?这些与良好做法背道而驰。

标签: c function


【解决方案1】:

通过摆脱 ft_putchar 并使用递归辅助函数,我做到了 :)

/* 01 */ #include <unistd.h>
/* 02 */
/* 03 */ void ft_helper(int a, int b, int c) {
/* 04 */     if (a == 10) return;
/* 05 */     else if (b == 10) ft_helper(a + 1, a + 2, a + 3);
/* 06 */     else if (c == 10) ft_helper(a, b + 1, b + 2);
/* 07 */     else {
/* 08 */         write(1, ", ", 2);
/* 09 */         write(1, "0123456789" + a, 1);
/* 10 */         write(1, "0123456789" + b, 1);
/* 11 */         write(1, "0123456789" + c, 1);
/* 12 */         ft_helper(a, b, c + 1);
/* 13 */     }
/* 14 */ }
/* 15 */
/* 16 */ void ft_print_comb(void) {
/* 17 */     write(1, "012", 3);
/* 18 */     ft_helper(0, 1, 3);
/* 19 */     write(1, "\n", 1);
/* 20 */ }
/* 21 */
/* 22 */ int main(void) {
/* 23 */     ft_print_comb();
/* 24 */     return 0;
/* 25 */ }

共25行(包括空行)

【讨论】:

  • 我不能摆脱 ft_putchar。我要编辑主帖。我必须使用 write 来创建我的 putchar,但我不能在其他地方使用它:/
  • 那我放弃了!很高兴我不必按照如此严格的要求编写代码。
  • 哈哈我明白了,还是谢谢你,这对我研究递归函数会有很大帮助:)
  • 这表示你的函数最多可以有 25 行,但如果你愿意,你的程序可以更长:)
  • @pmg: +1 一个不错的解决方案。对不断变化的非理性规则感到遗憾:)
【解决方案2】:

您在一组我们不知道的任意人为约束条件下工作。

按照我现在的理解,规则是:

  1. 每行不得超过一个语句
  2. 大括号必须单独一行
  3. 变量必须在单独的行中声明和初始化
  4. 您必须使用while 进行迭代,而不是for 语句
  5. 不能调用除stdlib.h:write() 以外的库函数
  6. 您必须在名为ft_print_comb() 的函数中实现该功能
  7. 最多可以定义 5 个函数
  8. 任何函数的长度不得超过 25 行
  9. 空行数
  10. 只包含大括号的行数
  11. 禁止评论 (!)

为了尽可能保守(冗长!),我假设了以下未明确说明的规则:

  1. ifs 必须使用大括号(单独一行)

我已经编辑了几次,因为我在玩它。这似乎可行,并且符合我目前对规则的理解。

如果您调整循环边界,则原始代码中最里面的if 是不必要的。

我已经定义了ft_puts(),一个本地等效于stdio:puts(),并删除了ft_putchar()

根据 chux 的建议,我删除了用于数字和从整数到字符的转换的单独变量。

void ft_puts(char *s)
{
    char *p;
    p = s;
    while( *(p++) != '\0' )
        ;
    write(STDOUT_FILENO, s, (p-s));
}                                              // 8 lines


void ft_print_comb(void) 
{
    char digit[6];                             // ="/--, " breaks Rule 3.
    digit[0] = '0'-1;
    digit[3] = ',';
    digit[4] = ' ';
    digit[5] = '\0';
    while (digit[0]++ < '7') 
    {
        digit[1] = digit[0];
        while (digit[1]++ < '8') 
        {
            digit[2]=digit[1];
            while (digit[2]++ < '9') 
            {
                if( digit[0]=='7' && digit[1]=='8' && digit[2]=='9' ) 
                {
                    digit[3] = '\n';
                }
                ft_puts(digit);
            }
        }
    }
}                                              // 24 lines

如果你完全忽略了这些愚蠢的规则,你可以用 15 行代码完成它:

#include <unistd.h>
int main(void) {
    char digit[6] = "/--, ";
    while (digit[0]++ < '7') {
        digit[1] = digit[0];
        while (digit[1]++ < '8') {
            digit[2]=digit[1];
            while (digit[2]++ < '9') {
                if( digit[0]=='7' && digit[1]=='8' && digit[2]=='9' )
                    digit[3] = '\n';
                write(STDOUT_FILENO, digit, 5);
            }
        }
    }
}

【讨论】:

  • 只有", " 的写入才能工作。所有其他人都通过char 需要char*
  • 公平点。固定的。我不确定我是否也没有引入一个或多个 off-by-1 错误。我更想弄清楚这些解决方案是否违反了愚蠢的规则。
  • 我必须写 int a; a = 0;在不同的线路上。每次打开括号时,我都必须跳过一行。这就是说,它似乎可以解决问题,我会试试这个并告诉你。
  • +1 不错。次要:为什么%10 似乎不需要。 char buf[6] = "___, "; 可以是 char buf[] = "___, ";
  • 纠缠附加评论。将buf[0] 用于a 等,并将数学偏移为“0”而不是0。而不是a = -1;buf[0] = '0' -1;
【解决方案3】:

我从声望中了解 Epitech。

不能直接拆分函数吗?

#include <unistd.h>


void ft_putchar(char c)
{
    write ( STDOUT_FILENO, &c, 1); /*Magic numbers are evil*/
}

void ft_print_inner(int a, int b, int c)
{
    ft_putchar('0' + a%10);
    ft_putchar('0' + b%10);
    ft_putchar('0' + c%10);
    if (a < 7 || b < 8 || c < 9)
    {
        ft_putchar(',');
        ft_putchar(' ');
    }
}

void ft_print_comb(void)
{
    int     a;
    int     b;
    int     c;

    a = 0;

    while (a < 8);
    {
        b = a + 1;
        while (b < 9)
        {
            c = b + 1;
            while (c <= 9)
            {
                ft_print_inner(a, b, c);
                c++:
            }
            b++;
        }
        a++;
    }
    ft_putchar('\n');
}

【讨论】:

  • 那么你是否可以拥有任意数量的函数,只要它们都不超过 25 行?这有很大的不同!
  • 不起作用,但这是我想做的事情。但正如我所说,我远非好(还!)所以我不知道该怎么做。无论如何,当我 gcc -Werror -Wextra -Wall my_file.c 我没有收到任何错误,但我得到的只是: $ ./a.exe |猫-e
  • @Emmet 是的,我被允许这样做,正如我所说的“只有库中的其他函数被禁止”,但我最多可以拥有 5 个自己的函数(不包括 int main() ),只要它们不使用禁止的函数,例如“printf”。
  • +1 表示STDOUT_FILENO。我已经相应地更新了自己的答案。
【解决方案4】:

这实在是太傻了,大概也违背了练习的精神,但是这样单行合法吗?

#include <unistd.h>

char *a = "012, 013, 014, 015, 016, 017, 018, 019, 023, 024, 025, 026, 027, 028, 029, 034, 035, 036, 037, 038, 039, 045, 046, 047, 048, 049, 056, 057, 058, 059, 067, 068, 069, 078, 079, 089, 123, 124, 125, 126, 127, 128, 129, 134, 135, 136, 137, 138, 139, 145, 146, 147, 148, 149, 156, 157, 158, 159, 167, 168, 169, 178, 179, 189, 234, 235, 236, 237, 238, 239, 245, 246, 247, 248, 249, 256, 257, 258, 259, 267, 268, 269, 278, 279, 289, 345, 346, 347, 348, 349, 356, 357, 358, 359, 367, 368, 369, 378, 379, 389, 456, 457, 458, 459, 467, 468, 469, 478, 479, 489, 567, 568, 569, 578, 579, 589, 678, 679, 689, 789\n";

void ft_putchar(char c)
{
    write ( 1, &c, 1);
}

void ft_print_comb(void)
{
    while(*a) ft_putchar(*a++);
}

【讨论】:

  • 哈哈不,我不允许这样做。程序必须通过自己的方式找到它。无论如何谢谢:)
【解决方案5】:

好的,这是我第一次尝试的另一个版本。

总行数:32
空白和#include 行:5
main 的行数:4
ft_putchar 的行数:3

其余行:32 - 5 - 4 - 3 = 20

ft_helper 的行数:13
ft_print_comb 的行数:7
“个人”功能的总行数:20

/* 01 */ #include <unistd.h>
/* 02 */
/* 03 */ void ft_putchar(char c) {
/* 04 */     write(1, &c, 1);
/* 05 */ }
/* 06 */
/* 07 */ void ft_helper(int a, int b, int c) {
/* 08 */     if (a == 10) return;
/* 09 */     else if (b == 10) ft_helper(a + 1, a + 2, a + 3);
/* 10 */     else if (c == 10) ft_helper(a, b + 1, b + 2);
/* 11 */     else {
/* 12 */         ft_putchar(',');
/* 13 */         ft_putchar(' ');
/* 14 */         ft_putchar("0123456789"[a]);
/* 15 */         ft_putchar("0123456789"[b]);
/* 16 */         ft_putchar("0123456789"[c]);
/* 17 */         ft_helper(a, b, c + 1);
/* 18 */     }
/* 19 */ }
/* 20 */
/* 21 */ void ft_print_comb(void) {
/* 22 */     ft_putchar('0');
/* 23 */     ft_putchar('1');
/* 24 */     ft_putchar('2');
/* 25 */     ft_helper(0, 1, 3);
/* 26 */     ft_putchar('\n');
/* 27 */ }
/* 28 */
/* 29 */ int main(void) {
/* 30 */     ft_print_comb();
/* 31 */     return 0;
/* 32 */ }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 2021-02-26
    相关资源
    最近更新 更多