【问题标题】:C Comparing 2 strings turned into memory allocation issueC比较2个字符串变成了内存分配问题
【发布时间】:2015-07-11 20:47:55
【问题描述】:

首先让我说,我确实意识到有很多问题的标题完全相同,但我没有在其中任何一个中找到我想要的东西。我尝试编写以下代码,以错误检查用户的输入,因此他不会给 2 个变量提供相同的名称。不用说,它失败了,这就是我在这里的原因。在打印我作为字符串比较的字符串时,使用printf("%s", temp[j].name); 工作正常,逐字符打印输出一系列字符,据我所知,这些字符不应该存在。我想知道这可能是关于什么的,如果有办法解决它,那么我实际上可以比较两者,而无需使用 string.h

代码如下:

#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);
}

代码编译没有问题,但是当我尝试运行它时,我发现无论我作为用户输入什么,最终标志总是为1。代码块

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

当用户输入的是名字 John 时,在 Visual Studio 2013 的开发人员命令提示符下输出以下内容:

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                 

我猜这个问题是关于系统分配给tempvarray 的内存已经在其他地方使用了。这种错误检查对于我必须做的项目至关重要,因此我将不胜感激能在很大程度上解决这个问题的任何帮助。提前致谢,

卢克塞克佩

【问题讨论】:

  • 问题是您打印的字数超过了字尾。你总是打印ARRAYLENGTH 字符,即使这个词只有4 个字符长。当你到达空字符时,你需要停下来。
  • @Barmar 是正确的。试试for (k = 0; k &lt; ARRAYLENGTH &amp;&amp; temp[i].name[k] != '\0'; k++)

标签: c string dynamic-memory-allocation


【解决方案1】:

编辑:本帖不是回答原问题,而是回答cmets中发布的后续问题。我试图将其合并到之前的答案中,但所有者拒绝了。就是这样。

您的可变数组比较的问题在于,至少在您显示的代码中,可变数组永远不会被初始化。所以

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

有点像在内存中取一个随机字节,将它分配给一个变量并这样做:

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

哪 90% 的时间为真,因此将您的标志设置为 1。 本质上,你缺少一个

varray[i] = lastVariableGotFromUser

在每个主循环结束时。

--- 编辑:添加了对一般功能的小修正---

尝试添加:

int added = 1;

然后改变这个:

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

与:

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

并添加:

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

发生的情况是,您遍历了未初始化且包含随机内存的 varray 字段。通过这些修改(如果我没有忘记一个,它应该可以工作。尝试始终将循环限制为仅有用的迭代。如果您知道只添加了一个变量,请不要遍历 3 个字段。

------- 最后一次编辑以更正他的代码中的一个细节-------

所以,你的整个:

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

可以删除。现在我也知道您不想使用 string.h,但是,重新编码 strcmp 并不是那么复杂。让我们称之为

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

然后只需将整个 for 替换为:

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

您只想在分析整个字符串时设置标志。所以将它传递给另一个函数,根据返回值进行操作,它就可以工作了!通常将您的代码切片。更容易行动/思考。 (并且还避免在你的代码中出现像varray[j].name[k] != temp[i].name[k] 这样的东西,这很长,读起来不太愉快。)

【讨论】:

  • 但我确实有一个。 if (flag == 1){ varray[i].name[j] = temp[i].name[j]},应该是用户之前给的名字。起初,varray 不会被初始化,第一次循环,flag 将为 1,并且 varray[0].name 应该是“John”。如果是这种情况,下次循环运行时,对于 i = 1,“John”应该已经存在于 varray[] (varray[0].name) 中的至少一个位置,所以它应该给我一条错误消息.这不正确吗?如果不是,为什么?
  • 所以,我想我发现了它为什么不起作用。我第一次调用scanftemp[j].name 的值读取为“John”时,出于某种原因,它在其中保存了一个破折号。我发现通过在说scanf 之后立即调用printf,它输出 - 到命令提示符。知道为什么会这样吗?另外,我对您的答案进行了一些思考,并对其进行了更改,使其从 i=1 开始,并且在进入循环之前只需读取第一个值 for i=0。尽管 time 的值是 John 而不是 -,但标志检查仍然不适用于第三次循环。我已经更新了代码。
  • @LukeSykpe 我会更改一些内容,我会将它们添加到我的答案中。等我把它放在一起。 :-)
  • 感谢您的回答。我假设“//你的 for 循环”是指 for(j = 0; j &lt; added; j++),所以我做了这些修改。现在,当我执行代码时,它无限期地卡在一个循环中,要求我给出名字#2,不管名字是什么。 (例如,对于我的名字,我有 John,就像前面的例子一样。然后,我给了“George”,它只是再次给了我“Give name of variable #2”的输出。)此外,错误消息( “名称已存在等”)未显示。
  • 所以,为了纠正这个问题,我把你提出的条件单独放在我的 while 循环结束之前。当我执行那段代码时,给出名称#1 John,并作为名称#2 再次尝试 John,它起作用了,错误名称正确显示,它要求我输入一个新的 #2,无论我多少次“约翰”说。当我最终选择乔治时,它通常会继续命名为#3。在名字 3 上,每当我给 George,也就是我在 2 上给的名字时,它工作得很好,错误信息等等,但是当我说 John,或者我作为名字 1 给出的名字时,它通常会正常保存。更新代码。
【解决方案2】:

问题在于您的打印逻辑。

scanf 函数将用户输入写入数组,后跟一个终止符 `\0'。它不知道你的数组的大小 (20),所以它不会触及它实际上没有写入的数组部分。

而不是这个:

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

写:

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

请注意,您无需在此处检查是否超出数组末尾。相反,请确保用户字符串对于您的数组来说不是太大。请参阅this 了解如何执行此操作。

【讨论】:

  • @LukeSykpe +1 到这个答案,因为这是我会写的。这确实是因为即使用户只输入了 1 个字符,您也总是读取 20 个字符。 (至少对于印刷故障。)
  • 我更新了代码和命令提示符输出。它看起来比以前好多了(变量确实是“J,o,h,n”)。问题是,尽管这确实解决了我认为导致我的条件不起作用的原因(检查tempvarray 是否与name 具有相同的值),但没有使条件本身起作用。它仍然会在最后打印 3 个“Johns”,而不会出现错误。对于 while 循环,布尔标志不会变为 0...嗯,循环。它一直以 1 结束,打破了 while 循环。我似乎无法指出其中的逻辑错误。
猜你喜欢
  • 2019-11-10
  • 1970-01-01
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多