繁体   English   中英

如何在C中声明char的动态数组

[英]How to declare a dynamic array of char in c

我试图动态声明一个char数组,我需要做的是将最新的字符添加到可以正常工作的字符串中,问题是当我尝试将其打印出来时,在字符串的开头有一些未知字符。

char add[2];
char str2[200];
char c;
int temp = -1;
int num = 0;
char *str3;
str3 = malloc( (size_t)count ); //str3 = malloc(sizeof(char)) not working
while((c= getch()) !='\r')
{
    for (int i = 0;i<200;i++)
    {
        if (str2[i] =='\0')
        {
            num = i;
            break;
        }
    }
    //printf("Num: %d\n",num);

    if ((temp == -32) || (temp == 0))
    {
    }
    else
    {
        if(isalnum((char)c) == 0)
        {
            if((c == '\'') || (c == -118) || (c == -115) || (c == -107) || (c == -123) || (c == -105)|| (c == 32))
            {
                realloc(str3,sizeof(char)+2);
                printf("true: %c\n",c);
                //realloc(str2,sizeof(char)+1);
                add[1] = '\0';
                add[0] = c;
                strcat(str3,add);
                strcat(str2,add);
                printf("%s\n",str2);
                printf("%s\n",str3);
            }
            else if (c == 8)
            {
                printf("Deleting something...\n");
            }
        }
        else
        {
            realloc(str3,sizeof(char)+2);
            printf("true: %c\n",c);
            //realloc(str2,sizeof(char)+1);
            add[1] = '\0';
            add[0] = c;
            strcat(str3,add);
            strcat(str2,add);
            printf("%s\n",str2);
            printf("%s\n",str3);
        }
    }
    printf("ASCII Code: %d\n",c);
    temp = c;
}

要为字符串获取一些内存,您必须告诉malloc您想要多少字节的内存。 sizeof(char)返回1 ,因此,您只有1个字节。 在C语言中,字符串以NULL字节( \\0 )终止,并且printf和其他字符串将打印,直到找到该NULL终止符。

如果您执行以下操作:

char *str = malloc(1);
*str = 'a';
printf("%s", str);

因为您没有NULL终止符,您可能会得到非常奇怪的输出。

当您使用unsigned x; str = malloc(x); unsigned x; str = malloc(x); ,实际上尚未定义您有多少字节,因为该x变量未初始化。

由于您的问题很清楚,我可以告诉你(从我想你问)是如何实际为63个字符的字符串加上获得空间NULL终止字节。

char *str = malloc(64);
strcpy(str, "Stack Overflow");
printf("%s", str);

这样就可以了。

还要注意,由malloc返回的内存块不会归零,因此您可能无法知道其中的内容(这可能是打印时出现垃圾的原因)。

我建议您在一本不错的C书或Wikipedia中读到有关内存分配的信息...


编辑后,点击“ MCVE”

我对您想要的内容进行了一些编辑。 修改在源注释中进行了说明。 如果您有任何疑问,请告诉我。

#include <stdio.h>  /* printf */
#include <stdlib.h> /* malloc, free, realloc */
#include <string.h> /* strcat */
#include <ctype.h>  /* isalnum */
#include <conio.h>  /* getch */

int main(void)
{
    char add[2];
    char str2[200];
    char c;
    int temp = -1;
    int num = 0;
    char *str3;

    /* I just think 'count' is an int, since you didn't put it in the code, 
     * I also deduced that @count will be used as the length of @str3 
     */
    int count;

    /* Here, count is not initialized, so you MUST initialize it in order 
     * to call malloc with it! Since it seems you want to add character by
     * character using realloc, then we just malloc() 2 bytes - 1 for a 
     * character and one for the NULL terminator.
     */
    count = 2;
    str3 = malloc(count);

    /* You will be using @strcat to append strings to @str3, so you need
     * to put a NULL terminator in it, because strcat will look for that
     * NULL byte to find where it should append
     */
    *str3 = 0x0;

    while((c = getch()) != '\r') {
        for (int i = 0;i < 200; i++) {
            if (str2[i] =='\0') {
                num = i;
                break;
            }
        }

        if ((temp == -32) || (temp == 0)) {
            /* empty */ 
        } else {
            if(isalnum((char)c) == 0)
            {
                if((c == '\'') || (c == -118) || (c == -115) || (c == -107) || (c == -123) || (c == -105)|| (c == 32))
                {
                    /* this is not the optimal way of using realloc, because
                     * you should first check for errors, but will do for
                     * this example.
                     * You must assign the returned value of realloc to str3. 
                     *
                     * Also, since @count contains the length
                     * of @str3, you need to increment it.
                     */
                    str3 = realloc(str3, ++count);
                    printf("true: %c\n",c);
                    add[1] = '\0';
                    add[0] = c;
                    strcat(str3,add);
                    strcat(str2,add);
                    printf("str2: %s\n",str2);
                    printf("str3: %s\n",str3);
                } else if (c == 8) {
                    printf("Deleting something...\n");
                }
            } else {
                /* see notes above on realloc */
                str3 = realloc(str3, ++count);
                printf("true: %c\n",c);
                add[1] = '\0';
                add[0] = c;
                strcat(str3,add);
                strcat(str2,add);
                printf("str2: %s\n",str2);
                printf("str3: %s\n",str3);
            }
        }
        printf("ASCII Code: %d\n",c);
        temp = c;
    }
    return 0;
}

在前两种情况下,您只为单个char分配了足够的空间。 如果您尝试向该内存块写入多个内存,则会超出为您分配的内存末尾。 这样做会引起未定义的行为 ,在这种情况下,这表现为打印奇怪的字符。

在第三种情况下,您分配了x个字节的内存,但是x未初始化并且具有不确定的值。 读取不确定的值也是未定义的行为。 在这种情况下,它之所以起作用,是因为不确定值恰好是一个有效值,并且足够容纳所需的字符串,但是您不能依赖该行为。

您需要为每个需要的字符分配一个字节,外加以1结尾的空字节(以C结尾的字符串)。

注意第一个分配,这个

str = malloc(sizeof(char));

完全等于1

str = malloc(1);

因此,除了一个字符之外,您没有空间,这是一个问题,因为它仅表示一个空字符串。

如果分配了如此多的空间,很可能会在分配的空间之外访问内存,从而导致无法定义和不可预测的行为。 您需要了解的字符串是什么,

  • 中的字符串是一个非空字符序列,后跟一个空字符,因此对于具有N个字符的字符串,您需要N + 1个数组元素(对于ascii,它等于字节)

根据字符串的定义,如果要存储字符串"Hello" ,则至少需要以下代码

char *str = malloc(6);
if (str != NULL) {
    str[0] = 'H';
    str[1] = 'e';
    str[2] = 'l';
    str[3] = 'l';
    str[4] = 'o';
    str[5] = '\0'; // Or equivalently str[5] = 0;
}

如您所见,最后一个字符为'\\0'0相同 )非常重要。

标准库中所有期望字符串参数的函数都期望存在终止符。 例如strlen()将对字符进行计数,直到达到'\\0'为止,如果不存在,则无法预测将要停止计数的位置,这将导致不确定的行为


1 sizeof(char)标准定义,始终等于1。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM