【问题标题】:scanf replaces last elements in char array with the next scanf inputscanf 用下一个 scanf 输入替换 char 数组中的最后一个元素
【发布时间】:2016-03-21 13:00:37
【问题描述】:

我遇到了一个问题,当我使用 scanf 将字符串存储到 char 指针中时,我有 3 个输入 - 姓名、姓氏和年龄,姓氏的最后一个 char 值被年龄替换这里是输出更好地解释。

Q-riosity v0.0.1
输入您的姓名
叶夫根尼

输入您的姓氏
丹尼连科

输入您的年龄
22

Evgeny Danilenk22,你 22 岁

这是代码

void getUserDetails(char** value)
{
    char *key[3] = {"name", "surname", "age"};
    int keySize = sizeof(key)/sizeof(char*);
    printf("Q-riosity v0.0.1\n");

    int i = 0;

    for(i = 0; i<keySize; i++)
    {
        printf("Enter your %s \n", key[i]); // name, surname, age
        scanf("%s", &value[i]);             //stores value at index i
    }

    printf("%s, %s, you are %s years old\n", &value[0], &value[1], &value[2]);
}

编辑

输入你的名字
叶夫根尼

输入您的姓氏
丹尼连科

输入您的年龄
22

分段错误

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

    char *key[3] = {"name", "surname", "age"};
    int keySize = sizeof(key)/sizeof(char*);
    printf("Q-riosity v0.0.1\n");
    char* value[keySize];

    int i = 0;
    for(i = 0; i<keySize; i++)
    {
        printf("Enter your %s \n", key[i]);
        scanf("%s", value[i]);
    }


    for(i = 0; i<keySize; i++)
    {
        printf("%s : %s \n", key[i], value[i]);
    }


    return 0;
}

【问题讨论】:

  • 从最后一个printf中删除所有&amp;
  • 价值声明在哪里?你为此分配了多少内存?
  • Nadir,如果我这样做,会出现分段错误
  • char* value[keySize]; 是一个由 3 个指针组成的数组,指向谁知道什么。 scanf("%s", value[i]); 肯定会失败。需要分配/定义空间来保存输入。

标签: c pointers


【解决方案1】:

嗯,输出 Danilenk22 表明您的 value 变量在调用者中声明为大小为 8 的连续 char 数组。

当您将Danilenko 读取为姓氏时,您写入10 个字符(包括终止的\0。前8 个填充保留数组,后2 个进入数组作为年龄。当您稍后读取年龄时,它会覆盖这两个字符。

让我们看看内存(?表示未初始化或无关字符):

   0  1  2  3  4  5  6  7  0  1  2  3  4  5  6  7  0  1  2  3  4  5  6  7
   E  v  g  e  n  y \0  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
   E  v  g  e  n  y \0  ?  D  a  n  i  l  e  n  k  o \0  ?  ?  ?  ?  ?  ?
   E  v  g  e  n  y \0  ?  D  a  n  i  l  e  n  k  2  2 \0  ?  ?  ?  ?  ?

但是 8 个字符也可以是 64 位架构上的指针大小...

您的编辑显示您未能正确初始化value 指针数组。假设您希望姓名和姓氏有 32 个字符,年龄有 4 个字符,您可以这样做:

char _v0[32], _v1[32], _v2[4];
char* value[keySize] = { _v0, _v1, _v2 };

这样程序就不会出现段错误了。

【讨论】:

  • 是的,我认为这是原因之一。我尝试先写姓氏,然后写名字等,现在姓氏与名字连接在一起......我该怎么做?我正在运行 64 位机器
【解决方案2】:

您将char** 传递给printfscanf%ss 期望 char*s,而不是 char**s。因此,替换以下内容:

scanf("%s", &value[i]);
printf("%s, %s, you are %s years old\n", &value[0], &value[1], &value[2]);

scanf("%s", value[i]);
printf("%s, %s, you are %s years old\n", value[0], value[1], value[2]);

新代码有一个问题:

char* value[keySize];

创建一个大小为keySize 的数组,其中包含指向char 的指针。这些指针未初始化,可能指向任何地方。您通过scanf 写入这些未初始化的指针,这会调用著名的未定义行为。

解决方案包括:

  1. malloc 每个指针的内存。
  2. 使指针指向某个有效的内存位置,如@SergeBallestaanswer 所示。
  3. 使用二维数组:

    char value[keySize][64];
    

【讨论】:

  • 实际上,在我提出该解决方案之前,我的代码与您建议的完全相同,但是,我遇到了分段错误。我也没有在任何地方使用 malloc,我只是将传递的输入传递给 vars。我会用我以前的代码更新帖子,所以你自己看看。
【解决方案3】:

换行

printf("%s, %s, you are %s years old\n", &value[0], &value[1], &value[2]);

printf("%s, %s, you are %s years old\n", value[0], value[1], value[2]);

记住,你想打印一个值,而不是它的地址。

注意: scanf() 需要一个指针才能正确读取,所以它的语法是

scanf("%s", &str);

【讨论】:

  • 如果str 被定义为char str[SOME_SIZE];scanf("%s", &amp;str); 是错误的。
【解决方案4】:

假设 value 在通过之前分配良好:

只需将printf() 语句更改为

printf("%s, %s, you are %s years old\n", value[0], value[1], value[2]);

和你的scanf() 声明

scanf("%s", value[i]);

事实上,printf("%s", &amp;str) 会调用未定义的行为,尽管它通常可以正常工作。这是因为str&amp;str 具有不同的类型,尽管它们的值相同。要验证这一点,只需运行

printf("%p\n%p\n%p\n%p", (void *)str, (void *)(str + 1), (void *)&str, (void *)(&str + 1));

另请参阅:Why scanf("%s",&str); behaves as scanf("%s",str);?

【讨论】:

    猜你喜欢
    • 2012-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    相关资源
    最近更新 更多