c - 在 c 中创建多文件程序时出错
问题描述
我正在尝试用 C 语言创建一个大型的多文件程序,但出现错误。
该程序实际上是一个智能电话簿,可以执行多项任务,如列出、添加、搜索和删除姓名。
对于其中的每一项任务,我都创建了一个文件,其中包含执行任务所需的函数和变量。
这里是我完成编码的文件:
(1) us-names.txt
(存储名称的数据库):
Mohammed
Ali
Harry
Peter
Hussain
Mark
John
Yu
Mohammed
Christina
Mohammed
Fatima
(2) Request.c
文件(接收用户的请求并执行所需的任务):
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <stdint.h>
#include <string.h>
//node declaration:
typedef struct node
{
char name[20];
struct node* link;
}
node;
void import_names(void) ;
void add_name(string name) ;
void search_for(string name) ;
void delete_name(string name) ;
int main(int argc , string argv[])
{
//create the hashtable and import the names:
import_names() ;
//check if there is any mistake in the command:
if(argc != 3 || argc != 4)
{
printf("Could not recognize the command, please enter one of the three commands: \n ./phone add name \n ./phone search-for name \n ./phone delete name \n") ;
return 1 ;
}
//otherwise, preform the command:
if(strcmp(argv[1] , "add") == 0)
{
add_name(argv[2]) ;
return 0 ;
}
if(strcmp(argv[1] , "search-for") == 0)
{
search_for(argv[2]) ;
return 0 ;
}
if(strcmp(argv[1] , "delete") == 0)
{
delete_name(argv[2]) ;
return 0 ;
}
else
{
printf("Could not recognize the command, please enter one of the three commands: \n ./phone add name \n ./phone search-for name \n ./phone delete name \n") ;
return 1 ;
}
}
3- Import.c 文件(从文本文件中导入名称并将它们散列并存储在散列表中):
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <stdint.h>
#include <string.h>
//node declaration:
typedef struct node
{
char name[20];
struct node* link;
}
node;
unsigned int hash(char* buffer , unsigned int CAPACITY) ;
void import_names(void)
{
//declarations:
FILE* fp = fopen("us-names.txt" , "a+") ;
if(fp == NULL)
{
printf("CANNOT OPEN THE FILE !\n") ;
fclose(fp) ;
exit ;
}
char buffer[20] ;
unsigned int key = 0;
unsigned int CAPACITY = 100 ;
struct node* temp = NULL ;
struct node* hashtable[CAPACITY] ;
for(int i = 0 ; i < CAPACITY ;i++)
{
hashtable[i] = NULL ;
}
struct node* curr = NULL ;
int num_of_names = 0;
//use a loop to iterate over the FILE:
for(int i = 0 ; !feof(fp) ; i++)
{
//Import name from the FILE & store into buffer:
fgets(buffer , 20 , fp) ;
//pass the name into the hash_function and get the key:
key = hash(buffer , CAPACITY) ;
//put the name in a node then in it's right place in the hashtable using the key:
temp = malloc(sizeof(struct node)) ;
sprintf(temp->name , "%s" , buffer) ;
temp->link = NULL ;
//if the key place of the hashtable is already populated, preform the collision protocol!:
if(hashtable[key] != NULL)
{
for(curr = hashtable[key] ; curr->link != NULL ; curr = curr->link)
{
}
curr->link = temp ;
}
//else if it's unpopulated, just store the name in this place:
else
{
hashtable[key] = temp ;
}
num_of_names++ ;
}
//close the FILE :
fclose(fp) ;
}
4- Hash.c 文件(一个包含哈希函数的小文件):
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <stdint.h>
#include <string.h>
unsigned int hash(char* buffer , unsigned int CAPACITY)
{
unsigned int sum = 0 ;
for(int i = 0; buffer[i] != '\0' ;i++)
{
sum += buffer[i] ;
}
return sum % CAPACITY ;
}
5- Search.c 文件(包含一种用于搜索任何名称的二进制搜索功能):
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <stdint.h>
#include <string.h>
#include "phonehead.h"
//node declaration:
typedef struct node
{
char name[20];
struct node* link;
}
node;
unsigned int CAPACITY = 100 ;
struct node* hashtable[CAPACITY] ;
unsigned int hash(char* buffer , unsigned int CAPACITY) ;
void search_for(string name)
{
//hash the name to get the place in which the wanted name is stored in the hash function:
unsigned int place = hash(name,CAPACITY);
//go to the location in the hashtable in which the name is stored, and check if the name is in the first node of the chain.
if(strcmp(hashtable[place]->name , name) == 0)
{
printf("FOUND\n") ;
}
//else, go to the node pointed by the current node and check if it contain the wanted name, and repeat this step until reaching null.
else if(strcmp(hashtable[place]->name , name) != 0)
{
struct node* curr = NULL ;
for(curr = hashtable[place]->link ; curr != NULL ; curr = curr->link)
{
if(strcmp(curr->name , name) == 0)
{
printf("FOUND\n");
exit ;
}
}
printf("NOT FOUND!\n") ;
}
}
除了头文件:
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <stdint.h>
#include <string.h>
typedef struct node
{
char name[20];
struct node* link;
}
node;
unsigned int hash(char* buffer , unsigned int CAPACITY) ;
unsigned int CAPACITY = 100 ;
struct node* hashtable[CAPACITY] ;
void import_names(void) ;
void add_name(string name) ;
void search_for(string name) ;
void delete_name(string name) ;
但是,当尝试使用命令链接/编译文件时
gcc phonehead.h requist.c Import.c Hash.c Search.c -o phone
我收到这些错误:
phonehead.h:15:14: error: variably modified ‘hashtable’ at file scope
15 | struct node* hashtable[CAPACITY] ;
| ^~~~~~~~~
In file included from Search.c:6:
phonehead.h:15:14: error: variably modified ‘hashtable’ at file scope
15 | struct node* hashtable[CAPACITY] ;
| ^~~~~~~~~
Search.c:8:16: error: redefinition of ‘struct node’
8 | typedef struct node
| ^~~
解决方案
本声明
struct node* hashtable[CAPACITY] ;
在文件范围内声明一个可变长度数组。您不能在文件范围内声明可变长度数组。在文件范围内声明的对象具有静态存储持续时间,但可变长度数组可能只有自动存储持续时间,即允许在块范围内定义它们。
而不是声明CAPACITY
用作数组大小的变量导致声明可变长度数组
unsigned int CAPACITY = 100 ;
struct node* hashtable[CAPACITY] ;
您可以使用定义指令,例如
#define CAPACITY 100
struct node* hashtable[CAPACITY] ;
或一个数值常数,如
enum { CAPACITY = 100 };
struct node* hashtable[CAPACITY] ;
此外,您在文件范围内两次声明了这样的数组:在头文件phonehead.h
中和在Search.c
包含头文件的文件中。两次声明数组是没有意义的。您应该只声明一次。由于文件范围内的数组未显式初始化,因此此类声明引入了暂定定义。
你两次定义了结构节点
typedef struct node
{
char name[20];
struct node* link;
}
node;
在标头phonehead.h
和包含标头的模块中
推荐阅读
- javascript - 为什么这段代码没有在 p5.js 的画布上输出任何东西?
- numpy - numpy 中更高的(4+)维度/轴......它们是否实际用于计算?
- scheme - Guile 是否通过允许以数字开头的变量名来放松对变量名约定的限制?
- python - 查找第一个数据框给出的两个日期之间的第二个数据框的最小值和最大值
- angular - 角材料 *matNoDataRow 不起作用
- apache-kafka - 卡夫卡消费者测试总是失败
- c# - 在 C# 中按选择排序
- sparql - 在 Wikidata SPARQL 查询中使项目可选
- flutter - 尝试打印地图但在 Flutter 中无法打印
- python - 如何解决推荐系统中的长尾问题?