为什么我在 C 中使用 strcat 会遇到这个问题?

问题描述

我对 C 完全陌生,我的代码如下所示:

//Initialize Global array variable title_char_cnt_array to char[26]
char title_char_cnt_array[26];
//Initialize SearchTitle array
char *SearchTitle[6] = { "uuul","dule","speed","spede","deul","cars" };

char *Compute_HashMapKey_for_each_title(char title[]) {
    //char *T;
    //T = title;
    Get_Individual_Character_Frequency_For_Each_Title(title);
    //Initialize alphabets array to char and assign a to z
    //Initialize HashMapKey to char
    char *HashMapKy;
    HashMapKy = malloc(sizeof(char));
    char default_str[] = { "0#" };
    char str[50];
    char ash[] = { "#" };
    int i;
    //Create HashMapKey by appending 0# to HashMapKey if a particular alphabet isn't in title or   count_of_alphabet plus # if the alphabet is in title (the format is   1#0#1#0#1#0#0#0#0#0#0#0#0#0#1#0#0#2#0#2 ... #1#0#0# for this title: Extractor for e.g)
    for (i = 0; i < 26; i++) {
        if (title_char_cnt_array[i] == 0) {
            //HashMapKey = HashMapKey . '0#';
            strcat(HashMapKy,default_str);
        } else {
            //First convert character frequency count to string
            sprintf(str,"%d",title_char_cnt_array[i]);
            //concat # to str
            strcat(str,ash);
            //HashMapKey =. title_char_cnt_array[i].'#';
            strcat(HashMapKy,str);
        }//end if
    }//End For
    return HashMapKy;
}

void Get_Individual_Character_Frequency_For_Each_Title(char Title[]) {
    int Title_Size;
    //get size of Title
    Title_Size = strlen(Title);
    int x,j;
    //Initialize current_char to char for character comparison in title_array
    char current_char;
    char Alphabets[][1] =  { "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z" };
    //Foreach character in title array,calculate individual character frequency here
    for (x = 0; x < Title_Size; x++) {
        //Initialize current_char_cnt to 0
        int current_char_cnt = 1;
        current_char = *(Title + x);//retrieve each character of Title array
        for (j = x; j < Title_Size; j++) {
            if (current_char == *(Title + j + 1)) {
                //increment current_char_cnt
                current_char_cnt++;
            }//End If
        }
        /*Insert current_char_cnt in title_char_cnt_array against index - index no. represents position of char in alphabetical order*/
        if (current_char == Alphabets[0][0])
            if (title_char_cnt_array[0] == 0)//if no prevIoUs value inserted,then insert
                title_char_cnt_array[0] = current_char_cnt;
        if (current_char == Alphabets[1][0])
            if (title_char_cnt_array[1] == 0)
                title_char_cnt_array[1] = current_char_cnt;
        if (current_char == Alphabets[2][0])
            if (title_char_cnt_array[2] == 0)
                title_char_cnt_array[2] = current_char_cnt;
        if (current_char == Alphabets[3][0])
            if (title_char_cnt_array[3] == 0)
                title_char_cnt_array[3] = current_char_cnt;
        if (current_char == Alphabets[4][0])
            if (title_char_cnt_array[4] == 0)
                title_char_cnt_array[4] = current_char_cnt;
        if (current_char == Alphabets[5][0])
            if (title_char_cnt_array[5] == 0)
                title_char_cnt_array[5] = current_char_cnt;
        if (current_char == Alphabets[6][0])
            if (title_char_cnt_array[6] == 0)
                title_char_cnt_array[6] = current_char_cnt;
        if (current_char == Alphabets[7][0])
            if (title_char_cnt_array[7] == 0)
                title_char_cnt_array[7] = current_char_cnt;
        if (current_char == Alphabets[8][0])
            if (title_char_cnt_array[8] == 0)
                title_char_cnt_array[8] = current_char_cnt;
        if (current_char == Alphabets[9][0])
            if (title_char_cnt_array[9] == 0)
                title_char_cnt_array[9] = current_char_cnt;
        if (current_char == Alphabets[10][0])
            if (title_char_cnt_array[10] == 0)
                title_char_cnt_array[10] = current_char_cnt;
        if (current_char == Alphabets[11][0])
            if (title_char_cnt_array[11] == 0)
                title_char_cnt_array[11] = current_char_cnt;
        if (current_char == Alphabets[12][0])
            if (title_char_cnt_array[12] == 0)
                title_char_cnt_array[12] = current_char_cnt;
        if (current_char == Alphabets[13][0])
            if (title_char_cnt_array[13] == 0)
                title_char_cnt_array[13] = current_char_cnt;
        if (current_char == Alphabets[14][0])
            if (title_char_cnt_array[14] == 0)
                title_char_cnt_array[14] = current_char_cnt;
        if (current_char == Alphabets[15][0])
            if (title_char_cnt_array[15] == 0)
                title_char_cnt_array[15] = current_char_cnt;
        if (current_char == Alphabets[16][0])
            if (title_char_cnt_array[16] == 0)
                title_char_cnt_array[16] = current_char_cnt;
        if (current_char == Alphabets[17][0])
            if (title_char_cnt_array[17] == 0)
                title_char_cnt_array[17] = current_char_cnt;
        if (current_char == Alphabets[18][0])
            if (title_char_cnt_array[18] == 0)
                title_char_cnt_array[18] = current_char_cnt;
        if (current_char == Alphabets[19][0])
            if (title_char_cnt_array[19] == 0)
                title_char_cnt_array[19] = current_char_cnt;
        if (current_char == Alphabets[20][0])
            if (title_char_cnt_array[20] == 0)
                title_char_cnt_array[20] = current_char_cnt;
        if (current_char == Alphabets[21][0])
            if (title_char_cnt_array[21] == 0)
                title_char_cnt_array[21] = current_char_cnt;
        if (current_char == Alphabets[22][0])
            if (title_char_cnt_array[22] == 0)
                title_char_cnt_array[22] = current_char_cnt;
        if (current_char == Alphabets[23][0])
            if (title_char_cnt_array[23] == 0)
                title_char_cnt_array[23] = current_char_cnt;
        if (current_char == Alphabets[24][0])
            if (title_char_cnt_array[24] == 0)
                title_char_cnt_array[24] = current_char_cnt;
        if (current_char == Alphabets[25][0])
            if (title_char_cnt_array[25] == 0)
                title_char_cnt_array[25] = current_char_cnt;
    }//End For
}

int main() {
    int i;
    //Foreach element in title_char_cnt_array,assign an in value of -1
    for (i = 0; i < 26; i++)
        title_char_cnt_array[i] = 0;

    //Initialize HashMap array
    struct node *HashMap[9];
    int HM_indx = 0;
    for (HM_indx = 0; HM_indx < 9; HM_indx++)
        HashMap[HM_indx] = NULL;
    int sz = 6; //6 titles to insert in hashmap
    //Initialize SearchTitle array
    //char *SearchTitle[6] = { "uuul","cars" };

    char *HMKey;
    int x;
    for (x = 0; x < sz; x++) {
        HMKey = Compute_HashMapKey_for_each_title(SearchTitle[x]);
        //printf("%s\n",HMKey);
        Insert_Title_To_HashMap_Using_HashMapKey(x,HMKey,HashMap);
    }

    free(HMKey);
    return 0;
}

我期望 Compute_HashMapKey_for_each_title(SearchTitle[x])HMKey 函数中返回 main 的是:

HashMapKey="0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#0#0#0#0#0#3#0#0#0#0#0#"

但我使用调试器看到的是:

HashMapKey=0xb41700 "À",'«' <repeats 16 times>,"þîþîþîþîþîþîþîþ0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#0#0#0#0#0#3#0#0#0#0#0#"

main函数中可以看出,一旦我得到HMKey;我将它传递给函数 Insert_Title_To_HashMap_Using_HashMapKey(x,HashMap),然后将我期望的字符串:"0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#0#0#0#0#0#3#0#0#0#0#0#" 分解为单个字符,将每个字符转换为它的 ASCII 数字,然后求和。所以我希望看到 0 作为第一个字符,# 作为第二个字符,0 作为第三个字符等等,但是我看到使用调试器的第一个字符是ÀCompute_HashMapKey_for_each_title(SearchTitle[x]) 返回值中地址后的第一个字符,返回到 HMKey

在这种情况下,即使我预期的 strlen 应该是 52,但我看到的是:84

我不知道发生了什么,请提供任何帮助,我们将不胜感激。

解决方法

HashMapKy = malloc(sizeof(char));

您只为单个字符分配空间。 C 语言中的数组或内存不是动态的,您不能通过附加到它们来“扩展”内存或数组。

此外,strcat 函数要求两个字符串都是以空字符结尾的字符串。由于 malloc 函数无论如何都不会初始化它分配的内存,它的内容将是不确定(最好将其视为垃圾或随机)。它的第一个位置不太可能包含零(空终止符)。

,

您应该将大小分配为 HashMapKy = (char*) malloc (sizeof(char) * 25);

,

Compute_HashMapKey_for_each_title 有一个主要问题:你没有为哈希字符串分配足够的空间,malloc(sizeof(char)) 分配了一个字节。

字符串可以是 5 加上空终止符的 26 倍(如果 title_char_cnt_arraychar 的数组,则为 5 个字节,但如果将其更改为 int,则为 12 个字节)。我建议使用本地数组并使用 strdup() 返回分配的副本:

char *Compute_HashMapKey_for_each_title(char title[]) {
    char buf[26 * 12 + 1];
    int pos = 0;
    Get_Individual_Character_Frequency_For_Each_Title(title);
    // Create HashMapKey by appending the number of occurrences for each character
    //  followed by a `#` char.
    for (int i = 0; i < 26; i++) {
        pos += sprintf(buf + pos,"%d#",title_char_cnt_array[i]);
    }
    return strdup(buf);
}

函数Get_Individual_Character_Frequency_For_Each_Title可以大大简化:

void Get_Individual_Character_Frequency_For_Each_Title(char Title[]) {
    const char *alphabet = "abcdefghijklmnopqrstuvwyxz";
    for (int i = 0; i < 26; i++) {
        title_char_cnt_array[i] = 0;
    }
    for (int i = 0; Title[i] != '\0'; i++) {
        char *p = strchr(alphabet,Title[i]);
        if (p != NULL) {
            title_char_cnt_array[p - alphabet] += 1;
        }
    }
}

如果您可以假设系统使用 ASCII 字符集,则该功能可以更简单:

void Get_Individual_Character_Frequency_For_Each_Title(char Title[]) {
    for (int i = 0; i < 26; i++) {
        title_char_cnt_array[i] = 0;
    }
    for (int i = 0; Title[i] != '\0'; i++) {
        char c = Title[i];
        if (c >= 'a' && c <= 'z') {
            title_char_cnt_array[c - 'a'] += 1;
        }
    }
}

请注意,title_char_cnt_array 应作为参数传递,并且应具有大于 char 的整数类型。