如何修复char*和char的格式错误**

如何修复char*和char的格式错误**,c,C,我正在编写一种电话簿程序,我正在使用typedef struct存储联系人的姓名和电话号码。用户将以字符串格式输入名称和数字,但当我尝试扫描它时,编译器会告诉我一个错误,即“format指定类型char*,但参数的类型为char**。有什么解决办法吗?我真的不明白这是什么意思两次扫描的第一个循环都有错误如有任何帮助,将不胜感激。谢谢 #include <stdlib.h> #include <string.h> typedef struct { char *na

我正在编写一种电话簿程序,我正在使用
typedef struct
存储联系人的姓名和电话号码。用户将以字符串格式输入名称和数字,但当我尝试扫描它时,编译器会告诉我一个错误,即“format指定类型
char*
,但参数的类型为
char**
。有什么解决办法吗?我真的不明白这是什么意思两次扫描的第一个循环都有错误如有任何帮助,将不胜感激。谢谢

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

typedef struct
{
    char *name;
    char *number;
}
person;

int main(void)
{
    int n;
    scanf("%i", &n);
    person people[n];

    for(int i = 0; i < n; i++)
    {
        scanf("%s", &people[i].name); // these 2 lines are buggy
        scanf("%s", &people[i].number);
    }

    char *findName;
    scanf("%s", &findName);

    for(int i = 0; i < n; i++)
    {
        if(strcmp(people[i].name, findName) == 0)
        {
            printf("%s\n", people[i].number);
        }
        else
        {
            return 1;
        }
    }

    return 0;
}
#包括
#包括
类型定义结构
{
字符*名称;
字符*数字;
}
人;
内部主(空)
{
int n;
scanf(“%i”和“&n”);
人;人;
对于(int i=0;i
findname
已经是
字符*
。 您请求引用此值,它表示
char**

scanf(“%s”和&findName)

试试这个:

scanf(“%s”,findName)

语句

scanf("%s", &people[i].name);
错误的原因有两个:

  • 首先,
    %s
    格式需要一个
    char*
    参数。通过使用运算符的地址,可以得到类型为
    char**
    的值。格式说明符和参数类型不匹配会导致未定义的行为

  • 如果删除运算符的地址,您将传递一个未初始化的指针,它不会指向任何有效的位置。这意味着
    scanf
    将把字符串写入内存中某个看似随机的位置。这同样会导致未定义的行为

  • 解决第二个问题的简单方法是,可以将结构改为包含字符数组,如中所示:

    typedef struct
    {
        char name[64];
        char number[64];
    }
    person;
    
    然后在格式中使用限制,以便
    scanf
    函数不会尝试读取比数组长的字符串:

    scanf("%63s", people[i].name);  // The array decays to a pointer to its first element
    

    请注意,格式中的长度是63,因此字符串空终止符将适合数组。

    这里是一个动态分配内存和
    scanf
    %ms
    的示例:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    typedef struct
    {
        char *name;
        char *number;
    }
    person;
    
    int main(void)
    {
        int n = 0;
        char *findName ;
        scanf("%i", &n);
        if (n == 0) return 1;
        
        person* people = (person*)malloc(n * sizeof(person));
        
        if (people == NULL) return 1;
        
        for(int i = 0; i < n; i++)
        {
            person p = people[i];
            printf("Enter Name and number:\n");
            printf("Number: ");
            scanf("%ms", &(p.number));
            printf("Name: ");
            scanf("%ms", &(p.name));
            people[i] = p;
        }
        
        printf("Enter name to search: ");
        scanf("%ms", &findName);
        printf("Searching for: %s\n", findName);
    
        for(int i = 0; i < n; i++)
        {
            person p = people[i];
            
            if(strcmp(p.name, findName) == 0)
            {
                printf("Number for %s is %s\n", p.name, p.number);
            }
        }
        free(findName);
    
        for(int i = 0; i < n; i++)
        {
            //notice how we have to free the strings for each name and number, 
            // and not just the people array 
            free(people[i].name);
            free(people[i].number);
        }
        free(people);
        return 0;
    }
    
    #包括
    #包括
    #包括
    类型定义结构
    {
    字符*名称;
    字符*数字;
    }
    人;
    内部主(空)
    {
    int n=0;
    char*findName;
    scanf(“%i”和“&n”);
    如果(n==0)返回1;
    person*people=(person*)malloc(n*sizeof(person));
    如果(people==NULL)返回1;
    对于(int i=0;i
    切勿将
    “%s”
    格式与
    scanf()一起使用。您无法安全使用它。

    问题是,用户控制将写入内存缓冲区的字符数,但程序需要提供内存缓冲区,而不知道用户实际要输入多少字符。其结果是程序始终存在缓冲区溢出漏洞。不要这样做

    相反,使用分配输入函数。对于
    scanf()
    ,您需要添加
    “m”
    修饰符:

    scanf("%ms", &people[i].name);
    
    这将预期的参数类型从
    char*
    更改为
    char**
    ,它将
    malloc()
    为您提供足够大的缓冲区,并将地址存储在给定位置。也就是说,此呼叫正是您希望它执行的操作。只要别忘了在处理完结果字符串后
    free()

    “m”
    修饰符与
    %ms”
    %m[“
    %mc”
    转换说明符一起使用,即可以输出未知长度字符串的所有转换


    (您应该记住的其他分配输入函数是
    getline()
    getdelim()

    您可能需要
    char*name
    ->
    char name[100]“100”是“名称”的最大大小。“代码> >编号< /COD>和 FordNo.<代码>同样也忘记了<代码>包含< <代码> >:在C++中,您不需要<代码> TyPulfF在C++中。AGS,只使用实际编程的一个。特别是因为您的代码在一个标记语言中无效。<代码>人[n];< /C> >在C++标准(VLA)中没有提供。只有一些C++编译器提供了非标准扩展名。<代码> >名称>代码>代码>编号>代码>是结构体未初始化的指针成员。在尝试复制数据之前,必须为每个用户分配存储空间,并且由于它们都已经指针,所以在使用<代码> SCANF…是的,在初始化时需要一个malloc或calloc,大小为,如果你想使用动态内存,这个结构的初始化很糟糕,如果是arrayyea,我需要分配内存,一切都很好。谢谢