【问题标题】:how to return an script in c / gcc?如何在 c / gcc 中返回脚本?
【发布时间】:2009-07-14 14:39:38
【问题描述】:

自从我用 C 写最后一行以来已经有好几年了,现在我试图重新开始做一些功能和使用,而不是作为 php 的扩展。

这是一个创建“小网址”的简单功能

让我们说:

a0bg a0bf a0bh

我遇到的问题是当我必须“增加”像 zzz 这样的字符串时,我得到了:Bus Error

否则,如果我增加 abr,例如我会得到结果:abs

有时我认为我的问题是返回字符串结果

正如我在此处发布的那样,这两个代码都功能齐全。

编译我正在使用:gcc append_id_test.c -o append_id

我在 OS X leopard 上

当我这样做时,它可以工作:(请注意对函数 append_id 的调用)

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

char* append_id(char*);
int main(void) {
    char *x;
    char *incremented;

    x = "aaab";

    printf("%s\n", append_id(x)); // should print 00000 (lenght 5)


    incremented = (char *) malloc((strlen(x) + 2) * sizeof(char));
    incremented = append_id(x);

    printf("--->  %s\n", incremented); // should print 00000 (lenght 5)

}

char* append_id(char *id) {

    int x;
    char* new_id;
    int id_size = strlen(id);

    new_id = (char *) malloc((strlen(id) + 2) * sizeof(char));

    for ( x = 0; x < id_size; x++ )
    {
        new_id[x] = '0';
    }

    strcat(new_id, "0");

    return new_id;
}

但整个代码都不起作用(您可以看到 append_id 函数的调用方式与上述示例相同)

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


char* append_id(char*);
char* increment_id(char*, int);
char* get_next_id(char*);


int main(int argc, char *argv[]) {
    char *x;
    int a;

    x = "zz";

    printf("incrementando %s -> %s\n", "zz", get_next_id(x));

    return 0;
}


char * get_next_id(char *last_id)
{ 
    int x, pos;
    char *next_id;
    char is_alnum = 1;

    // if the last id is -1 (non-existant), start at the begining with 0
    if ( strlen(last_id) == 0 )
    {
        next_id = "0";
    }
    else
    {

        // check the input
        for(x = 0; last_id[x]; x++) 
        {
            if(!isalnum(last_id[x]))
            {
                is_alnum = 0;
                break;
            }
        }

        if (is_alnum == 0)
        {
            return "";
        }


        // all chars to lowercase
        for(x = 0; last_id[x]; x++) 
        {
            last_id[x] = tolower(last_id[x]);
        }


        // loop through the id string until we find a character to increment
        for ( x = 1; x <= strlen(last_id); x++ )
        {
            pos = strlen(last_id) - x;

            if ( last_id[pos] != 'z' )
            {
                next_id = increment_id(last_id, pos);
                break; // <- kill the for loop once we've found our char
            }
        }

        // if every character was already at its max value (z),
        // append another character to the string
        if ( strlen(next_id) == 0)
        {
            next_id = (char *) malloc((strlen(last_id) + 2) * sizeof(char));
            next_id = append_id(last_id);
        }

    }


    return next_id;
}



char* append_id(char *id) {

    int x;
    char* new_id;
    int id_size = strlen(id);

    new_id = (char *) malloc((strlen(id) + 2) * sizeof(char));

    for ( x = 0; x < id_size; x++ )
    {
        new_id[x] = '0';
    }

    strcat(new_id, "0");

    return new_id;
}



char* increment_id(char *id, int pos){
    char current, new_char;
    char * new_id ;
    int x;

    new_id = (char *) malloc((strlen(id) + 1) * sizeof(char));


    current = id[pos];

    if ( current >= 0x30 && current <= 0x39 )
    {
        if ( current < 0x39 )
        {
            new_char = current + 1;
        }
        else // if we're at 9, it's time to move to the alphabet
        {
            new_char = 'a';
        }
    }
    else // move it up the alphabet
    {
        new_char = current + 1;
    }


    for ( x = 0; x < strlen(id); x++ )
    {
        if (x == pos) {
            new_id[x] = new_char;
        }
        else {
            new_id[x] = id[x];
        }
    }


    // set all characters after the one we're modifying to 0
    if ( pos != (strlen(new_id) - 1) )
    {
        for ( x = (pos + 1); x < strlen(new_id); x++ )
        {
            new_id[x] = '0';
        }
    }

    return new_id;
}

【问题讨论】:

  • 我看到 malloc 的但我没有看到 free 的...
  • 说“我的一小部分代码可以工作,但是这个具有 4 倍大的其他 2 个函数的其他段不起作用”并不是很有帮助。
  • 我只是想向您展示问题的背景:我的想法(我不确定,问题从第二部分的第 74 行开始)
  • 您正在尝试修改常量字符串,请查看您的小写转换

标签: c string gcc


【解决方案1】:

下次请用 -Wall 编译 ;)

首先,在使用 tolower 和 isalnum 之前,

#include <ctype.h>

其次,您将 x(在主范围内)指定为指向字符串字面量,即 const。因此,当您尝试在小写时覆盖它时,您会遇到内存冲突。尝试初始化,比如说,

char x[] = "zz";

你还应该在 get_next_id 中初始化 next_id:

char *next_id = NULL;

稍后,不要在空指针上运行 strlen:

// if every character was already at its max value (z),
// append another character to the string
if (!next_id || !strlen(next_id))
{
    next_id = append_id(last_id);
}

在append_id中,使用strcat前需要null终止:

for ( x = 0; x < id_size; x++ )
{
    new_id[x] = '0';
}
new_id[id_size] = 0;

这只是让它工作。您的代码有很多问题。你提到

距离我用 C 写最后一行已经好几年了

我真的希望你几年前能更好地掌握它,好像你忘记了很多基本的 C 内存、字符串和指针概念。

【讨论】:

  • 在开发过程中,我经常用-pedantic -Wall -Wextra -Wshadow跑,有点吵,但还是有用的。
【解决方案2】:

除了忘记释放内存之外,您还有两个问题,在第 12 行和第 72 行。 在第 12 行,您必须将“zz”声明为字符数组,而不是字符串文字:

    char x[] = "zz";

在第 72 行,如果所有字符都处于最大值,则 next_id 将为空。 strlen(null) 将导致另一个段错误。

    if ( !next_id )

【讨论】:

    【解决方案3】:

    我可能会检查 get_next_id 中的 for 循环。您正在无限制地迭代指针。这在哪里结束?

        // check the input
        for(x = 0; last_id[x]; x++) 
        {
                if(!isalnum(last_id[x]))
                {
                        is_alnum = 0;
                        break;
                }
        }
    

    执行与 append_id 相同的操作。获取接收到的指针的大小 (int id_size = strlen(id);) 然后根据该长度迭代 last_id 指针。

    我认为你的循环永远不会结束。 last_id[x] 将返回一个字符,而不是一个条件。所以它总是正确的,除非存在当前字符为零的情况。

    【讨论】:

    • C 字符串以空值结尾。 last_id[x] 将在字符串末尾为 0。
    • 我认为这是一个问题,因为 char* x="zz" 不是空终止的(至少不能保证)。他正在为指针 x 分配一个值“zz”(无论这意味着什么)。我什至不知道那会是什么地址。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2011-12-07
    • 1970-01-01
    相关资源
    最近更新 更多