首页 > 解决方案 > 挣扎于 C 字符串和 printf %s

问题描述

因此,很长一段时间以来,我一直在为 C 中的字符串(我猜很简单)问题而苦苦挣扎。

我想创建一个指针列表char并为每个指针分配malloc()一些内存以填充单个随机字符。最后我想对它们进行排序并用strcat().

所以在这段代码中,只有第一部分显示了一些测试函数:

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

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("Error, too few arguments!\n");
        return 0;
    }

    // initialize random generator
    srand((unsigned int)time(NULL));

    const int a = atoi(argv[1]);

    char *array[a];

    //--------------- generate random characters ----------------------------------------
    for (int i = 0; i < a; i++) {
        int r = rand() % 30 + 1;
        printf("%d ", r);

        array[i] = (char*)malloc(a + 1 * sizeof(char));

        sprintf(array[i], "%ls", &r);
        *(array[i] + 1) = '\0';
    }

    putchar('\n');
    printf("%d %d %d \n", *array[0], *array[1], *array[2]);

    char *array_2 = (char*) malloc(a * sizeof(char));

    strcat(array_2, *array);
    strcat(array_2, *(array + 1));
    strcat(array_2, *(array + 2));

    printf("Address array_2[0] : %p , value: %d \n", array_2, *array_2);
    printf("Address array_2[1] : %p , value: %d \n", &array_2[1], array_2[1]);
    printf("Address array_2[1] : %p , value: %d \n", &array_2[2], array_2[2]);

    // produces a lot a garbage and crap
    printf("array_2 with string : %s :\n", array_2);

    // rest of the code omitted because it is irrelevant to the issue
    return 0;
}

所以,我不明白的是:单独打印字符可以正常工作。如果我想将整个内容打印为字符串,我只会得到一个嘈杂的字符串。我怎样才能实现这个想法?

老实说,我不明白这个问题 - 如果我创建一个像char array[4] = {'a','b','c', '\0'}我可以用“%s”打印整个内容的字符数组......但在我的程序中它几乎相同但不起作用。

如果有人能给我一个提示,我会很高兴!

标签: cstringfield

解决方案


您的代码有几个问题:

  • 数组的尺寸是错误的。中的a字符串array将包含一个从 0 到 30 的随机数,因此每个字符串最多需要 3 个字节(两位数和空字符),但您分配a字节。这些数字是不相关的。array_2必须包含所有array字符串的串联,因此它最多为2*a字节长,并且最后需要一个额外的字节用于空字符。
  • sprintf错了:sprintf(array[i], "%ls", &r)试图将整数r的地址解释为宽字符数组的地址。(这看起来好像你一直在摆弄格式和参数,直到编译器保持沉默。)要将数字打印r到字符串,请使用sprintf(array[i], "%d", r).
  • sprintf将已经以空值终止您的字符串,因此无需明确执行此操作。
  • 正如鲁斯兰已经指出的那样,您array_2指向未初始化的内存。该函数strcat需要一个以 null 结尾的字符串。您可以array_2通过将第一个 char 设置为 null char 来生成有效的空字符串'\0'

为了修复您的代码,我建议以下内容:

  • array一个大小为3的字符串数组。不要在堆上分配,而是在栈上做自动变量,这样更容易管理。
  • 创建数字字符串时,请跟踪它们的长度。这些*printf函数有一个有用的返回值,即打印或写入字符串/文件的字符数。使用该长度为array_2.
  • 初始化array_2为有效的空字符串,然后将strcat所有array字符串初始化为array_2.
  • array_2用, 然后free分配的内存做有趣的事情。

这是代码:

int a = 8;
char array[a][3];
int len = 0;

for (int i = 0; i < a; i++) {
    int r = rand() % 30 + 1;

    printf("%d\n", r);
    len += sprintf(array[i], "%d", r);
}

char *array_2 = malloc(len + 1);

*array_2 = '\0';
for (int i = 0; i < a; i++) {
    strcat(array_2, array[i]);
}

printf("\"%s\"\n", array_2);
free(array_2);

推荐阅读