使用字符串的二维数组

7

我被一些未经过分数评定(仅用于练习)的作业困住了。

我需要创建一个名为find_name的函数,它接受两个参数。第一个参数是一个名字(字符串)的二维数组,第二个参数是用于在这个二维数组中查找名字的字符串,如果找到,函数必须返回1,否则返回0。

当我调用这个函数时(目前它是空的),我会得到这个警告:warning: passing argument 1 of 'find_name' from incompatible pointer type

以下是重要部分。

主函数

 char strNameList[][2] = { { "Luca","Daniel"} ,{"Vivan","Desmond"},{"Abdul","Justin"}, {"Nina","Marlene"},{"Donny","Kathlene"} };

char strFindName[] = "\0";
    printf("Please enter a name to look for: ");
    gets(strFindName);
    nSearch = find_name(strNameList, strFindName);

函数

int find_name(char strNameList[][2], char strLookUp[])

我是一名C语言的新手(我是一名学生),对于字符串(包括字符串数组等)感到完全困惑。


你想声明 char * strNameList[][2] 还是 char strNameList[][2] - alk
哎呀,我定义的是char strNameList,而不是char *strNameList。 - Luca
3个回答

12

我假设您想要一个char指针的二维数组。您在程序中strNameList的声明是错误的,无论是在哪个位置。您目前的声明为:

char strNameList[][2] = { { "Luca","Daniel"} ,{"Vivan","Desmond"},{"Abdul","Justin"}, {"Nina","Marlene"},{"Donny","Kathlene"} };

但是char[][N]声明的是一个二维数组,其元素类型为chars而不是char*。因此编译器会警告你正在将一系列指针值赋给char类型的项。

更改你的声明(变量和函数参数)为:

const char *strNameList[][2]

这声明了一个长度未知的数组,其元素是两个char*的数组,现在与您的初始化列表匹配。此外,添加了const是因为(a)我假设您不打算在函数内修改该名称列表,以及(b)通过初始化程序分配给char*的可写字符串文字声明在C中是未定义行为,在C++中正式废弃,因此无论如何都不应该使用它。同样,您的查找名称可能也没有被修改,因此也将其声明为const

const char * strNameList[][2] = { 
    {"Luca","Daniel"} ,
    {"Vivan","Desmond"},
    {"Abdul","Justin"}, 
    {"Nina","Marlene"},
    {"Donny","Kathlene"} 
};

并且在你的函数中:

int find_name(const char * strNameList[][2], const char strLookUp[])

最后但同样重要的是,除非你有一颗水晶球,否则你的 find_name() 函数无法根据所提供的信息知道正在传递的姓名列表中有多少个名字。我宁愿你现在看到这一点,而不是以后想知道发生了什么。你需要使用以下方法之一: (a)用一个find_name()已知的标记值终止列表,或者 (b)将姓名列表中的名称数量传递给find_name() 。 各自选择,但我更喜欢后者:

int find_name(const char * strNameList[][2], size_t nNameListSize, const char strLookUp[])

通过以下方式在调用方调用它:

find_name(strNameList, sizeof(strNameList)/sizeof(strNameList[0]), strFindName)

+1 对于我错过的 const ... - 因为如果使用最近的 gccstrcpy(strNameList[0][0], "alk"); 将会导致应用程序崩溃。 - alk
“可通过初始化程序分配给char**的可写字符串字面值声明是C语言中一个已弃用的特性”,这并不完全正确。在C++中,它已被弃用,但在C语言中仍然有效。C语言中的字符串字面值不是“const”,但修改它们的行为是未定义的:“[...]如果程序试图修改这样的数组,则行为是未定义的。”(C11 6.4.5/7,字符串字面值) - netcoder
@netcoder 我真的需要选择一种语言并坚持下去。每次我使用一种语言时,它都会在另一种语言中出现问题。前几天我在C++中声明了一个VLA,并盯着它看了10分钟,试图记住为什么它无法编译。谢谢,先生,我会更新答案。 - WhozCraig
如果数组以停止元素结尾,则不一定需要传递数组的大小。请参见我的修改答案。 - alk
@alk 这将是选项a,即“(a) 使用find_name()识别的令牌值终止列表”。 - WhozCraig
2
@alk sok. 盯着足够多的 Stack Overflow 帖子,最终它们都融合成一盘带有马里纳拉酱的意大利面。很容易错过一些东西。反正我经常会这样。 - WhozCraig

5

请按照以下方式进行:

#define STOPPER_NAMELIST NULL

char * strNameList[][2] = { 
  { "Luca","Daniel"},
  {"Vivan","Desmond"},
  {"Abdul","Justin"}, 
  {"Nina","Marlene"}, 
  {"Donny","Kathlene"} 
  {STOPPER_NAMELIST, STOPPER_NAMELIST}
};

size_t sizeNameList(const char * strNameList[][2])
{
  size_t size = 0;

  while ((strNameList[size][0] != STOPPER_NAMELIST) && 
         (strNameList[size][0] != STOPPER_NAMELIST))
    ++ size;

  return size;
}

int find_name(char * strNameList[][2], char strLookUp[])
{
   size_t size = sizeNameList(strNameList);

   ...
}

...

nSearch = find_name(strNameList, strFindName);

这种方法使用一个包含2个元素的char *数组的开放数组([])。


更新:

您可以向数组中添加一个停止符号元素来携带名称,那么就不需要在传递数组本身时还要传递数组大小,因为可以扫描数组成员直到找到停止符号为止来确定大小。


我现在明白了。警告:数组初始化程序中存在过多的元素| 警告:('strNameList [0]' 的初始化程序附近) - Luca
是的,我明白了,你也修改了find_name函数,我一直在看旧的代码。+1 - Omkant
要获取 Luca,只需执行 strNameList[0][0],而要获取 Vivan,请执行 strNameList[1][0]。@Omkant - alk
我没有按照“[][2]”所指示的方式将元素分组。既然所有错误都消失了,现在要构建find_name。 - Luca
我需要传递两个参数给find_name函数。 - Luca
显示剩余2条评论

2

您的函数find_name()正在查找一个2维字符数组,即:

char arr[][2] = { { 'a', 'b'}, ...

如果您想要将它们变成 字符串 ,您需要:

char *arr[][2] = { {"John", "Smith"}, ...

在函数的参数列表中需要:

void find_name(char *something[][2])
{
   printf("first name: %s, second name: %s\n", something[0][0], something[0][1]);

在你的main()函数中,只需调用它:
find_name(arr);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接