简体   繁体   English

C比较2个字符串变成内存分配问题

[英]C Comparing 2 strings turned into memory allocation issue

Let me start off by saying, I do realize there are a lot of questions with the exact same title, but I didn't find what I was looking for in any of them. 首先,我要说的是,我的确知道有很多题目完全相同的问题,但是我没有找到我所要查找的内容。 I tried to write the following code, in order to errorcheck the user's input, so he wouldn't give 2 variables the same name. 我试图编写以下代码,以便对用户的输入进行错误检查,因此他不会给2个变量使用相同的名称。 Needless to say, it failed, and that is why I am here. 不用说,它失败了,这就是为什么我在这里。 While printing the strings I was comparing out as strings, using printf("%s", temp[j].name); 在打印字符串时,我使用printf("%s", temp[j].name);作为字符串进行比较printf("%s", temp[j].name); was working fine, the character-by-character printing was outputting a series of characters that, from what I know, shouldn't be there. 工作正常,逐个字符打印输出了一系列字符,据我所知,这些字符不应该在那里。 I would like to know what this could all be about, and if there is anyway to solve it, so I can actually compare the 2, without using something from string.h 我想知道这可能是怎么回事,以及是否有解决的办法,因此我实际上可以比较2,而无需使用string.h

Here is the code: 这是代码:

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

#define ARRAYLENGTH 20

typedef struct{
    char name[ARRAYLENGTH];
    char type[ARRAYLENGTH];
    char value[ARRAYLENGTH];
}variable;


int main(){
    int amount = 3;
    int i, j, k;
    variable * varray;
    variable * temp;
    int flag;
    int added = 1;

    varray = malloc(amount*sizeof(variable));
    if (varray == NULL){
        printf("error");
        return 1;
    }
        temp = malloc(amount*sizeof(variable));
    if (temp == NULL){
        printf("error");
        return 1;
    }
    printf("Give the name of variable # 1 \n");
    scanf("%s", varray[0].name);

    for (i = 1; i < amount; i++){
        flag = 0;
        while (flag == 0){
            printf("Give the name of variable # %d \n", i + 1);
            scanf("%s", temp[i].name);

            for (j = 0; j < added; j++){
                for (k = 0; temp[i].name[k] != '\0'; k++){
                    printf("%c,", temp[i].name[k]);
                }
                printf("\n");
                for (k = 0; temp[i].name[k] != '\0'; k++){
                    if (varray[j].name[k] != temp[i].name[k]){
                        flag = 1;
                        break;
                    }
                    if (varray[j].name[k] == temp[i].name[k]){
                        flag = 0;
                    }
                }
            }
            if (flag == 0){
                printf("The variable name you gave already exists, please choose another one. \n");
            }
            if (flag == 1){
                for (j = 0; j < ARRAYLENGTH; j++){
                    varray[i].name[j] = temp[i].name[j];
                }
            }
            if(flag == 1){
                added +=1;
            }
        }
    }
    for (i = 0; i < amount; i++){
        printf("%s \n", varray[i].name);
    }
    free(varray);
    free(temp);
}

The code compiles without problem, but when I tried to run it, I found that, no matter what my, as a user, input was, the flag would always be 1 in the end. 代码可以毫无问题地编译,但是当我尝试运行它时,我发现,无论我作为用户输入什么内容,该标志的末尾始终为1。 The block of code 代码块

printf("\n");
for (k = 0; k < ARRAYLENGTH; k++){
    printf("%c,", temp[i].name[k]);
}
printf("\n");

And when the user input is the name John, outputs the following on Visual Studio 2013's Developer command prompt: 当用户输入的名称为John时,在Visual Studio 2013的Developer命令提示符下输出以下内容:

Give the name of variable # 1                                                                                                                         
John                                                                                                                                                  
Give the name of variable # 2                                                                                                                         
John                                                                                                                                                  
J,o,h,n,                                                                                                                                              
The variable name you gave already exists, please choose another one.                                                                                 
Give the name of variable # 2                                                                                                                         
George                                                                                                                                                
G,e,o,r,g,e,                                                                                                                                          
Give the name of variable # 3 
George                                                                                                                                                
G,e,o,r,g,e,                                                                                                                                          
G,e,o,r,g,e,                                                                                                                                          
The variable name you gave already exists, please choose another one.                                                                                 
Give the name of variable # 3                                                                                                                         
John                                                                                                                                                  
J,o,h,n,                                                                                                                                              
J,o,h,n,                                                                                                                                              
John                                                                                                                                                  
George                                                                                                                                                
John                 

What I am guessing this problem is about, is that the memory the system is allocating to temp and varray are already being used elsewhere. 我猜这个问题是关于系统分配给temp的内存,而varray已在其他地方使用。 This errorcheck is crucial for a project I have to do, so I would appreciate any help I can get in solving this problem greatly. 此错误检查对于我必须执行的项目至关重要,因此,我将在解决此问题方面大有帮助。 Thanks in advance, 提前致谢,

LukeSykpe LukeSykpe

The problem is with your printing logic. 问题出在您的打印逻辑上。

The scanf function writes the user input into the array, followed by a terminating `\\0' character. scanf函数将用户输入写入数组,后跟一个终止的\\ 0字符。 It does not know the size of your array (20), so it doesn't touch the part of the array that it doesn't actually write. 它不知道数组的大小(20),因此它不会触及实际上未写入的数组部分。

Instead of this: 代替这个:

for (k = 0; k < ARRAYLENGTH; k++){

write: 写:

for (k = 0; temp[i].name[k] != '\0'; k++) {

Note that you don't need to check for running off the end of the array here. 请注意,您无需在此处检查是否耗尽了数组的末尾。 Instead, make sure that the user string is not too big for your array. 相反,请确保用户字符串对于您的阵列而言不要太大。 See this for how to do that. 看到这个如何做。

Edit : This post is not to answer the original question, but to answer a follow-up question posted in comments. 编辑:这篇文章不是回答原始问题,而是回答评论中张贴的后续问题。 I tried to incorporate this into the previous answer, but the owner refused. 我试图将其合并到先前的答案中,但所有者拒绝了。 So here it is. 就是这样

The problem with your varray comparisons is that, with the code you are showing at least, varray is never initialized. varray比较的问题在于,至少在您显示的代码中,varray从未初始化。 So 所以

if (varray[j].name[k] != temp[i].name[k])

Is a bit like taking a random byte in memory, assigning it to a variable and doing this : 有点像在内存中获取随机字节,将其分配给变量,然后执行以下操作:

if (RandomByteValue != temp[i].name[k])

Which 90% of the time will be true thus setting your flag to 1. Essentially, you're missing a 哪90%的时间是正确的,因此将标志设置为1。本质上,您缺少

varray[i] = lastVariableGotFromUser

At the end of each main loop. 在每个主循环的末尾。

--- Edit : Added in minor corrections to general functionality --- ---编辑:对一般功能进行了较小的更正---

Try adding in this : 尝试添加:

int added = 1;

Then change this : 然后更改:

for (j = 0; j < amount; j++){

with : 与:

for (j = 0; j < added; j++){

and add in : 并添加:

        if (flag == 1){
            // Your for loop
            added += 1;
        }

What was happening was that you iterated through fields of varray that were uninitialized, and contained random memory. 发生的事情是,您遍历未初始化且包含随机内存的varray字段。 With those modifications (If i didn't forget one, it should work. Try to always limit your loops to only the useful iterations. If you know you only have one variable added in, don't iterate through the 3 fields. 进行了这些修改(如果我没有忘记一个修改,它应该可以工作。请尝试始终将循环限制为仅有用的迭代。如果您知道仅添加了一个变量,请不要遍历3个字段。

------- Last edit to correct a detail in his code ------- -------最后编辑以更正其代码中的细节-------

So, your whole : 所以,你整个:

for (k = 0; temp[i].name[k] != '\0'; k++){

Can be deleted. 可以删除。 Now i also know that you don't want to use string.h, However, recoding a strcmp ain't all that complicated. 现在我也知道您不想使用string.h,但是,重新编码strcmp并不是那么复杂。 Let's call it 叫它吧

int comp_str(str, str2) // Returns 1 if they don't match, zero if they do.

then just replace your whole for with : 然后只需将整个替换为:

if (comp_str(temp[i].name, varray[j].name) == 0) {
    flag = 0;
    break;
}
else
    flag = 1;

You only want to set the flag when a whole string has been analyzed. 您只想在分析了整个字符串后设置标志。 So pass it to another function, act upon the return value, and it works! 因此,将其传递给另一个函数,对返回值起作用,它就可以工作! Generally slice your code up. 通常将您的代码切成薄片。 Easier to act/think on. 更容易采取行动/思考。 (and also avoids having things like varray[j].name[k] != temp[i].name[k] which is long an not so pleasing to read, in your code.) (并且还避免在代码中出现类似varray[j].name[k] != temp[i].name[k] ,这样的时间长了一点也不varray[j].name[k] != temp[i].name[k] 。)

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

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