简体   繁体   English

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

[英]scanf replaces last elements in char array with the next scanf input

I've come a cross a problem where, when I'm using scanf to store a string into a char pointer, I have 3 inputs - name, surname, and age, that surname's last char value get replaced by age here's the output to better explain. 我遇到了一个问题,当我使用scanf将字符串存储到char指针中时,我有3个输入-名称,姓氏和年龄,那个姓氏的最后一个char值将替换为age,这是输出更好地解释。

Q-riosity v0.0.1 Q-riosity v0.0.1
Enter your name 输入你的名字
Evgeny 叶夫根尼

Enter your surname 输入您的姓
Danilenko 达尼连科

Enter your age 输入您的年龄
22 22

Evgeny Danilenk22, you are 22 years old Evgeny Danilenk22,您今年22岁

Here's the code 这是代码

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

EDIT 编辑

Enter your name 输入你的名字
Evgeny 叶夫根尼

Enter your surname 输入您的姓
Danilenko 达尼连科

Enter your age 输入您的年龄
22 22

Segmentation fault 分段故障

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

You are passing a char** to both printf and scanf . 您正在将char**传递给printfscanf The %s s expect char* s, not char** s. %s期望的是char* ,而不是char** So, replace the following: 因此,替换以下内容:

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

with

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

The new code has one problem: 新代码有一个问题:

char* value[keySize];

creates an array of size keySize of pointers to char . 创建大小的数组keySize指针的char These pointers are uninitialized and could be pointing to anywhere. 这些指针未初始化,可能指向任何地方。 You write to these uninitialized pointers via scanf and this invokes the famous Undefined Behavior. 您通过scanf写入这些未初始化的指针,这将调用著名的Undefined Behavior。

Solutions for this include: 解决方案包括:

  1. malloc memory for each pointer. 每个指针的malloc内存。
  2. Make the pointers point to some valid memory location as shown in @SergeBallesta 's answer . 使指针指向某个有效的内存位置,如@SergeBallesta答案所示
  3. Use a 2D array: 使用二维数组:

     char value[keySize][64]; 

Hmm, the output Danilenk22 suggests that your value variable was declared in caller as consecutive char arrays with size 8. 嗯,输出Danilenk22建议您在调用方中将您的value变量声明为大小为8的连续char数组。

When you read Danilenko as surname, you write 10 characters (including the terminating \\0 . The first 8 fill the reserved array, the last 2 go in array for age. When you later read the age, it overrides those 2 characters. 当您将Danilenko读为姓时,您写了10个字符(包括结尾的\\0前8个填充了保留数组,后2个填充了age数组。后来您阅读了age,它将覆盖这2个字符。

Lets look at memory (? represent unitialized or don't care characters): 让我们看一下内存(?代表单元化字符或无关字符):

   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  ?  ?  ?  ?  ?

But eight characters could also be the size of a pointer on a 64 bits architecture... 但是在64位体系结构上,指针的大小也可能是八个字符。

Your edit shows that you fail to initialize correctly the value array of pointers. 您的编辑显示您无法正确初始化指针的value数组。 Assuming that you want to have 32 characters for name and surname, and 4 for the age, you could do: 假设您要在名称和姓氏中使用32个字符,并在年龄中使用4个字符,则可以执行以下操作:

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

That way the program no longer seg fault. 这样,程序就不再出现段错误。

Replace line 更换线

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

with

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

Remember, you want to print a value, not its address. 请记住,您要打印一个值,而不是其地址。

NOTE : scanf() requires a pointer in order to read properly, so its syntax is 注意: scanf()需要一个指针才能正确读取,因此其语法为

scanf("%s", &str);

Assuming value is well-malloced before it's passed: 假设value在传递之前分配正确:

Simply change the printf() statement to 只需将printf()语句更改为

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

and your scanf() statement to 和你的scanf()语句

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

In fact, printf("%s", &str) invokes undefined behaviour, although it usually works properly. 实际上,尽管通常可以正常运行,但printf("%s", &str)调用未定义的行为。 This is because str and &str have different types, despite the fact that their values are identical. 这是因为,尽管str&str的值相同,但它们的类型不同。 To verify this, simply run 要验证这一点,只需运行

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

See also: Why scanf("%s",&str); 另请参见: 为什么用scanf(“%s”,&str); behaves as scanf("%s",str);? 表现为scanf(“%s”,str);?

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

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