scanf用下一个scanf输入替换char数组中的最后一个元素

时间:2016-03-21 13:00:37

标签: c pointers

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

  

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

4 个答案:

答案 0 :(得分:2)

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

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的{​​{1}}指针数组。这些指针未初始化,可以指向任何地方。您通过char写入这些未初始化的指针,这将调用着名的未定义行为。

解决方案包括:

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

    malloc

答案 1 :(得分:2)

嗯,输出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  ?  ?  ?  ?  ?

但是八位字符也可能是64位架构上指针的大小......

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

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

这样程序就不再有错误。

答案 2 :(得分:1)

替换行

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

答案 3 :(得分:1)

假设value在通过之前已经完成了malloced:

只需将printf()语句更改为

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

和您的scanf()语句

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

实际上,printf("%s", &str)会调用未定义的行为,尽管它通常可以正常工作。这是因为str&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);?