【问题标题】:strncmp/strcpy corrupting sourcestrncmp/strcpy 损坏源
【发布时间】:2011-07-14 06:23:29
【问题描述】:

今天我试图对 char * 字符串友好...但似乎我失败了 :) 每次我调用 strcmp/strncmp/strcpy 函数时,我的源代码都会损坏......

这里是sn-p

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

struct student
{
    int UID;
    char name[20];
    char surname[20];
};

char * getString(int minChars, int maxChars);

struct student * myStud;

int main(int argc, char** argv) {

    myStud = (struct student*)malloc(sizeof(struct student));
    while(1)
    {
        printf("\nEnter new name: ");
        strcpy(myStud->name,getString(1,19));
        printf("\n The values is now %s",myStud->name);
    }
    return (EXIT_SUCCESS);
}

char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];
scanAgain:
    scanf("%s",&string);
    if(strlen(string)<minChars)
    {
        printf("\nToo few symbols, try again: ");
        goto scanAgain;
    }
    if(strlen(string)>maxChars)
    {
        printf("\nToo many symbols, try again: ");
        goto scanAgain;
    }
    string[maxChars]='\0';
    return(string);
}

输出:

Enter new name: Alekasdasd

 The values is now Alekasda�#
Enter new name: 

我只是一个初学者,所以它可能非常简单......可能不是。 哦,顺便说一句,使用linux和netbeans作为SDK,gcc作为编译器。

【问题讨论】:

  • 写一个小程序来复现问题。 (另外,考虑重组你的程序,这样它就不会是一堆乱七八糟的标签和 goto ......)
  • 太棒了!源损坏!希望您不是指程序源 :)
  • 首先打开编译器上的警告。这应该让你重新考虑几件事。

标签: c strcpy


【解决方案1】:

240 行不是“sn-p”。 正如詹姆斯在他的评论中建议的那样,将代码减少到重现问题所需的最少行数。在那个阶段,问题的原因对您来说应该是显而易见的——如果没有,请尝试再次发布。

【讨论】:

  • 0: -1 表示没有答案; +1 非常好的建议。这使它总共为 0 :)
【解决方案2】:
char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];
    ...
    return(string);
}

这里的“字符串”数组只分配给 getString() 函数的作用域。一旦它返回(超出范围),它将不复存在,并将被您的程序的其余部分覆盖。 “return(string)”语句返回不再分配的数据的指针——而不是数据本身。这是由于 C 中隐式的数组到指针的转换。

您的 getString() 函数不应这样做,而是将 char* 作为参数,该参数在调用函数中分配。

【讨论】:

  • 谢谢,我刚刚写了这个 get string thingy,因为在使用 scanf() 时由于分段错误而烦恼,而且在 printf() 之后立即自动 scanf“读取”...
【解决方案3】:

您正在返回一个指向堆栈变量的指针。

char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];

当 getString 返回时,string 无效。你的返回值指向这个无效的字符串。

用途:

char * getString(int minChars, int maxChars, char * string) {

    return string;
}
...
char string[100];
getString(1, 2, string);

另外,goto?请停止使用 - 使用 forwhile dodo while 但不要使用 goto

【讨论】:

  • 是的,我知道 goto,我会改变它 :))
  • Erik 有一个很好的观点,即不依赖隐藏缓冲区的方法,这会导致代码缺陷。
  • 不要盲目地相信goto是不好的,理解为什么被认为是这样的。这很糟糕,因为它会导致代码的可读性降低。在某些(非常有限的)情况下可以使用(不是 this 特殊情况,因为您可以通过更结构化的循环来达到相同的目的)。
【解决方案4】:

我发现您的 getString() 函数存在两个问题:

  1. 字符串变量必须声明为static,以便函数返回时不会释放(堆栈、弹出)用于它的内存。
  2. scanf() 的参数不需要&amp; 标记,而只是指向缓冲区的指针string

即换行:

char string[maxChars+1];
scanf("%s",&string);

阅读

static char string[maxChars+1];
scanf("%s",string);

您不想在 scanf() 调用中使用与号的原因是手册页中的以下内容,man 3 scanf

s 匹配一系列非空白字符;下一个 指针必须是足够长的**指向字符数组**的指针 保存输入序列和终止空字符 ('\0'),它是自动添加的。输入字符串在 空白或最大字段宽度,以发生者为准 第一的。

【讨论】:

  • static 并不是一个很好的解决方案 - 当他例如致电foo(getString(), getString())
  • 只有程序员才能产生调用。因此,C 程序员理解static 是最重要的。 OP写道,他今天正在学习。我的结论是,与担心他目前没有的问题相比,他最好尝试静态,同时修复他的指针使用和学习。有趣的是,静态这个词用来表示停滞,并且已经开始表示火花的噪音。他有一天会遇到你描述的问题吗?那天会发生什么?
  • 静态很有用。但是 IMO 这个功能是错误的。此外,&amp;stringstring 在这种情况下是等效的 - 仅使用 string 会使源代码更漂亮。
猜你喜欢
  • 2013-03-17
  • 2013-11-12
  • 2020-02-12
  • 2011-02-08
  • 2018-12-01
  • 2017-12-20
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
相关资源
最近更新 更多