将向量的值转换为字符指针以进行写入系统调用

Converting a vector's values to char pointer for write syscall

我在使用 write() 时遇到了一些问题。我有一个 vector<long>,里面有几个不同的 long 值。我的最终目标是将此向量转换为字符指针,以便我可以将其传递给 write 并将值打印到标准输出。

这是我的代码:

void print_vector(vec* v)
{
    int init_capacity = 10;
    char* output = (char*) malloc(init_capacity*sizeof(char));
    int cols = (int) sqrt(v->size);


    for (int i = 0; i < v->size; i++)
    {
        if(i==init_capacity)
        {
            init_capacity *= 2;
            output = (char*)realloc(output, init_capacity*sizeof(char));
        }
        const int n = snprintf(NULL, 0, "%l", v->data[i]);
        char buffer[n+1];
        int c = snprintf(buffer, n+1, "%l", v->data[i]);
        if ((i + 1) % cols == 0) {
            strcat(buffer, '\n');
        }

        output[i] = buffer;
    }

    write(1, output, init_capacity);
//    for (int i = 0; i < v->size; i++)
//    {
//        printf("%ld ", v->data[i]);
//        if ((i + 1) % cols == 0) {
//            puts("");
//        }
//    }

}

我首先初始化我计划作为缓冲区传递给 write 的 char*。我给它一个 10 的初始容量,当我循环遍历向量并将其值传递到我的缓冲区 output 时,如果我 运行 出来,我会重新分配 space。

在我的 for 循环中,我首先检查我的 output 是否有 运行 超出 space 并在需要时重新分配。

然后我将矢量的 ith 元素加载到 buffer 中(不要与 output 混淆)。我这样做是因为我想在列中最后一个值的末尾添加一个 "\n"(这应该看起来像一个矩阵)。您会在代码的第二个 if 语句中看到这一点,我在其中将“\n”连接到缓冲区。

我做错了一些事情,因为我遇到了段错误。

我认为发生这种情况有两个原因:

  1. 我怀疑我在 buffer 上做错了什么。虽然我不知道它可能是什么......也许 char buffer[n+1] 不开心?我真的不确定。

  2. 我可能误解了 strcat 的输入。缓冲区不属于那里吗?

  3. 我很确定output[i]= buffer是不正确的。

我需要这方面的帮助,希望得到一些解释。

这是一道作业题。你不必给我确切的答案。如果有解释就更好了——我真正想要的是一个例子。

我已经在下面的评论中添加了 write() 我想做的事情。

编辑:

新代码:

void print_vector(vec* v)
{
    int cols = (int) sqrt(v->size);
    for (int i = 0; i < v->size; i++)
    {
        int n = snprintf(NULL, 0, "%ld", v->data[i]);
        char buffer[n+1];
        sprintf(buffer, n+1, "%ld", v->data[i]);
        if ((i + 1) % cols == 0) {
            strcat(buffer, "\n");
        } else {
            strcat(buffer, " ");
        }

        write(1, buffer, n+1);
    }


//    for (int i = 0; i < v->size; i++)
//    {
//        printf("%ld ", v->data[i]);
//        if ((i + 1) % cols == 0) {
//            puts("");
//        }
//    }
}

当我 运行 gdb 时,我得到这个输出:

program received signal SIGSEGV, Segmentation fault.
__strchrnul_sse2 () at ../sysdeps/x86_64/multiarch/../strchr.S:32
32  ../sysdeps/x86_64/multiarch/../strchr.S: No such file or directory.
(gdb) 

我认为这没有帮助...

我在编译时得到的一些警告:

$ make
gcc -g -o ctp transpose.c vec.c -lm
transpose.c: In function ‘print_vector’:
transpose.c:59:25: warning: passing argument 2 of ‘sprintf’ makes pointer from integer without a cast [-Wint-conversion]
         sprintf(buffer, n+1, "%ld", v->data[i]);
                         ^
In file included from transpose.c:2:0:
/usr/include/stdio.h:320:12: note: expected ‘const char * restrict’ but argument is of type ‘int’
 extern int sprintf (char *__restrict __s,

第二次不用snprintf(),直接用sprintf()即可。第一个调用告诉您输出的长度,并且您在声明 buffer 时为此分配了足够的 space。所以你在实际写的时候就不用担心缓冲区溢出了

如果您确实使用 snprintf(),则不应使用 n+2 作为限制。由于您需要为换行留出空间,因此您应该使用 n+1.

if 语句需要一个 else 子句来写入 space,因此矩阵的列之间会有一些东西。

    if ((i + 1) % cols == 0) {
        strcat(buffer, "\n");
    } else {
        strcat(buffer, " ");
    }

另请注意,strcat() 的第二个参数必须是字符串,而不是 char

如果您真的希望它看起来像一个漂亮的矩阵,您应该在格式字符串中为输出指定一个宽度,这样所有列的大小都将相同。这也意味着您不需要动态指定 buffer 的大小,它只需要足够大即可达到该宽度。