在C字符串和printf%s中挣扎

时间:2019-10-21 05:36:07

标签: c string field

所以我很长时间以来一直在努力解决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”打印整个内容...但是在我的程序中,它几乎是一样的,但是没有不行。

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

2 个答案:

答案 0 :(得分:3)

您的代码有几个问题:

  • 数组的尺寸错误。 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已经对字符串进行了空终止,因此无需明确地执行此操作。
  • 正如Ruslan已经指出的那样,您的array_2指向未初始化的内存。函数strcat需要以空值结尾的字符串。通过将第一个字符设置为空字符array_2,可以使'\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);

答案 1 :(得分:2)

  

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

     

strcat(array_2, *array);

您已经分配了array_2,没有对其进行初始化,然后将*array附加到任何垃圾array_2上。在出现空字符之前,该垃圾可能包含许多控制字符,可打印字符以及诸如此类的东西,因此您会在控制台上获得所有这些字符(有时会发出哔声)。