如何使用多个重复键和csv在一个程序中执行上述操作。输入数据文件?
答案 0 :(得分:0)
编辑:假设为KEY "," DATA "\n"
(为简洁起见没有空格)并在末尾附加一个简短的草图,以便OP有一个开始。
我无法修复它,因为我不知道输入,但我可以指出你做的一些错误。请参阅代码中的注释
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNAMELENTH 64
#define MAXDATALENTH 1465
typedef struct node {
char name[MAXNAMELENTH];
char data[MAXDATALENTH];
struct node *left;
struct node *right;
} node;
node *root;
node *search(node ** tree, char *key, int count, FILE * fp_out);
node *insertion(node * r, char *key, char *value);
void deltree(node * tree);
char *strtok_r(char *str, const char *delim, char **nextp);
int main(int argc, char *argv[])
{
node *root;
node *tmp;
FILE *fp;
FILE *outputfile;
FILE *keyfile;
FILE *fp_key;
int i;
int counter = 0;
int bufsize = MAXDATALENTH + MAXNAMELENTH;
int keyfilelen = MAXNAMELENTH;
char *keyread;
char *buffer, *saveptr;
char *line = NULL;
char *keyin = NULL;
char *valuein = NULL;
char inputkey[MAXNAMELENTH];
char *target_key = NULL;
char *keyline = NULL;
root = NULL;
/* Inserting nodes into tree */
buffer = (char *) malloc(bufsize * sizeof(char));
if (buffer == NULL) {
// use the proper macros, please
exit(EXIT_FAILURE);
}
// Check outputs! Always check outputs!
// I just assume that it has not been done here for simplicity
// and fear of posting-size limits (limit is 30k IIRC, that's a lot of code)
fp = fopen(argv[1], "r");
outputfile = fopen("outputfile.txt", "a");
// this is an infinite loop. How do you break out?
while (1) {
// fgets() returns NULL in case of EOF and error
// (yes, both, so check, e.g.: with ferror())
fgets(line, bufsize, fp);
buffer = line;
// I'm not fully sure, but I think you wanted a "=" instead of a ","
// Please switch on warnings for your compiler
keyin, strtok_r(buffer, ",", &saveptr);
// NUL delimited? Really? Are you sure strtok_r() can handle it?
valuein = strtok_r(NULL, "\0", &saveptr);
// insertion() returns a node
insertion(root, keyin, valuein);
}
/* Search node into tree */
// Wrong type: keyfile is a filepointer (FILE *), not a string (char *)
if (scanf("%s", keyfile) != EOF) {
// hu? Please switch on warnings for your compiler
keyfile = fopen(argv[4], "r");
// where's keyfile? Gone?
while ((fgets(keyline, keyfilelen, fp_key))) {
keyread = strtok_r(keyline, "\n", &saveptr);
search((&root), keyread, counter, outputfile);
}
// Please use braces, even here, thank you
if (keyline) {
free(keyline);
}
fclose(keyfile);
}
// This reads keys given as arguments at programstart,
// that's not what the teacher wanted
for (i = 3; argv[i] != NULL; i++) {
target_key = argv[i];
search((&root), target_key, counter, outputfile);
}
// This program does not read from stdin.
// Hint: stdin is also nothing more (although slightly less) than a file
// but it is already open and you don't close it
// (but it may not exist at all, so check first)
/* Deleting all nodes of tree */
deltree(root);
fclose(fp);
fclose(outputfile);
return 0;
}
node *insertion(node * r, char *key, char *value)
{
if (r == NULL) // BST is not created created
{
r = (node *) malloc(sizeof(node)); // create a new node
// insert data to new node
strcpy(r->name, key);
strcpy(r->data, value);
// make left and right childs empty
r->left = NULL;
r->right = NULL;
}
// if the data is less than node value then we must put this in left sub-tree
else if (strcmp(key, r->name) < 0) {
r->left = insertion(r->left, key, value);
}
// else this will be in the right subtree
else if (strcmp(key, r->name) > 0) {
r->right = insertion(r->right, key, value);
} else {
if (strcmp(value, r->data) > 0) {
r->left = insertion(r->left, key, value);
} else if (strcmp(value, r->data) < 0) {
r->right = insertion(r->right, key, value);
}
// what if both, name and data are equal?
}
// if you don't want to do anything with the returned
// node than don't return it. Just an int indicating error
// or something in the line
return r;
}
void deltree(node * tree)
{
if (tree) {
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}
// searching does not compare the same way as inserting
node *search(node ** tree, char *key, int count, FILE * fp_out)
{
if (!(*tree)) {
return NULL;
}
if (strcmp(key, (*tree)->name) < 0) {
search(&((*tree)->left), key, count, fp_out);
count++;
} else if (strcmp(key, (*tree)->name) > 0) {
search(&((*tree)->right), key, count, fp_out);
count++;
} else if (strcmp(key, (*tree)->name) == 0) {
// won't print anything, because you return before the printing
return *tree;
fprintf(fp_out, "%s --> %s\n", key, (*tree)->data);
} else {
fprintf(fp_out, "%s --> NOTFOUND", key);
}
printf("%s --> %s\n", key, count);
// nothing to return here?
}
// Thank you for the proper reference!
// Seems to grow less and less usual these times.
/*
* public domain strtok_r() by Charlie Gordon
*
* from comp.lang.c 9/14/2007
*
* http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684
*
* (Declaration that it's public domain):
* http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c
*/
char *strtok_r(char *str, const char *delim, char **nextp)
{
char *ret;
if (str == NULL) {
str = *nextp;
}
str += strspn(str, delim);
if (*str == '\0') {
return NULL;
}
ret = str;
str += strcspn(str, delim);
if (*str) {
*str++ = '\0';
}
*nextp = str;
return ret;
}
编辑:草图。请注意,我没有做所有你的作业,我为学生留下了一点#34;正如俗话所说。
/*
*
* - Construct a binary search tree to store the information contained in the file specified
* in the command line argument. Each record should be stored in a separate Node.
*
* - Search the binary search tree for records, based on their keys. The keys are read in
* from stdin, i.e. from the screen.
*
* For testing, it is often convenient to create a file of keys to be searched, one per line, and redirect the input from this file.
*
* Use the UNIX operator < for redirecting input from a file.
*
* - Examples of use:
* ./yelp1 datafile outputfile then type in keys;
* or
* ./yelp1 datafile outputfile < keyfile
*
* - Your program will look up each key and output the information (the data found) to the output
* file specified by the second command line parameter.
*
* If the key is not found in the tree,you must output the word NOTFOUND.
*
* The number of key comparisons performed during both successful and unsuccessful lookups
* have to be written to stdout.
*
* - Remember that the entries in the file do not necessarily have unique keys.
* Your search must locate all keys matching the search key, and output all the data found.
*/
/*
* Tested with datafile produced by the following shellcode
*
* # KEY "," DATA
* counter=1;
* while [ $counter -le 100 ];
* do counter=$((counter + 1));
* echo $(pwgen 10 1)","$(pwgen 10 1) >> testtree.db
* done;
*
* # ten random KEY
* shuf -n10 testtree.db | sed -e 's/,[a-z]\+//g' > testtree10keys
*
* # ten random DATA
* shuf -n10 testtree.db | sed -e 's/[a-z]\+,//g' > testtree10datas
*
* Please insert doublettes manually
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// data produced has only 10 characters each (plus NUL)
#define MAXNAMELENTH 11
#define MAXDATALENTH 11
typedef struct node {
char name[MAXNAMELENTH];
char data[MAXDATALENTH];
struct node *left;
struct node *right;
} node;
node *root;
node *search(node ** tree, char *key, int *count, FILE * fp_out);
int insertion(node ** r, char *key, char *value);
void deltree(node * tree);
//char *strtok_r(char *str, const char *delim, char **nextp);
void bt_print(node * leaf);
int main(int argc, char *argv[])
{
node *root;
// node *tmp;
FILE *fp;
FILE *outputfile;
// FILE *keyfile;
// FILE *fp_key;
// int i;
int counter = 0;
int bufsize = MAXDATALENTH + MAXNAMELENTH + 2;
// int keyfilelen = MAXNAMELENTH;
// char *keyread;
char *buffer;
// char *saveptr;
// char *line = NULL;
char *keyin = NULL;
char *valuein = NULL;
// char inputkey[MAXNAMELENTH];
// char *target_key = NULL;
// char *keyline = NULL;
char *e;
int res;
char *comma;
root = NULL;
// must have at least one argument
if (argc < 2) {
fprintf(stderr, "Usage: %s datafile [< key-list]\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Inserting nodes into tree */
buffer = malloc(bufsize);
if (buffer == NULL) {
fprintf(stderr, "Malloc failed\n");
exit(EXIT_FAILURE);
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "Opening \"%s\" for reading failed\n", argv[1]);
exit(EXIT_FAILURE);
}
outputfile = fopen("outputfile.txt", "a");
if (fp == NULL) {
fprintf(stderr, "Opening \"outputfile.txt\" for appending failed\n");
exit(EXIT_FAILURE);
}
while ((e = fgets(buffer, bufsize, fp))) {
if (e == NULL) {
if (ferror(fp)) {
// TODO: check errno for the exact kind of error
fprintf(stderr, "An eror occured during reading \"%s\"\n", argv[1]);
exit(EXIT_FAILURE);
} else if (feof(fp)) {
break;
}
}
// assuming strict KEY","DATA"\n" and without whitespace
// otherwise you need to check every step here!
// valuein points to the comma before DATA
valuein = strchr(buffer, ',');
// valuein points to DATA
valuein++;
// DATA is 10 characters large
valuein[10] = '\0';
// comma points to the comma before DATA
comma = strchr(buffer, ',');
// make *comma NUL
*comma = '\0';
keyin = buffer;
// ignoring return for now
//printf("%s,%s\n",keyin, valuein);
(void) insertion(&root, keyin, valuein);
}
bt_print(root);
// search-keys come from either stdin or get typed in.
// things typed in are also stdin
while ((res = scanf("%10s", buffer)) == 1) {
//printf("%s\n",buffer);
search(&root, buffer, &counter, outputfile);
printf("Misses for KEY \"%s\" = %d\n", buffer, counter);
counter = 0;
}
/* Deleting all nodes of tree */
deltree(root);
fclose(fp);
fclose(outputfile);
return 0;
}
void bt_print(node * leaf)
{
if (leaf) {
printf("%s,%s\n", leaf->name, leaf->data);
bt_print(leaf->left);
bt_print(leaf->right);
}
}
int insertion(node ** r, char *key, char *value)
{
if (*r == NULL) {
*r = malloc(sizeof(node));
if (r == NULL) {
return 0;
}
strcpy((*r)->name, key);
strcpy((*r)->data, value);
(*r)->left = NULL;
(*r)->right = NULL;
}
// Checks for returns omitted for clarity
else if (strcmp(key, (*r)->name) < 0) {
insertion(&(*r)->left, key, value);
}
// else this will be in the right subtree
else if (strcmp(key, (*r)->name) > 0) {
insertion(&(*r)->right, key, value);
} else {
if (strcmp(value, (*r)->data) > 0) {
insertion(&(*r)->left, key, value);
} else if (strcmp(value, (*r)->data) < 0) {
insertion(&(*r)->right, key, value);
}
// what if both, name *and* data are equal?
return 0;
}
return 1;
}
void deltree(node * tree)
{
if (tree) {
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}
// search still cannot find multiple occurences of KEY
// Can you repair it?
node *search(node ** tree, char *key, int *count, FILE * fp_out)
{
node *tmp;
if (!(*tree)) {
printf("%s --> NOTFOUND\n", key);
fprintf(fp_out, "%s --> NOTFOUND", key);
return NULL;
} else {
if (strcmp(key, (*tree)->name) < 0) {
tmp = search(&((*tree)->left), key, count, fp_out);
(*count)++;
return tmp;
} else if (strcmp(key, (*tree)->name) > 0) {
tmp = search(&((*tree)->right), key, count, fp_out);
(*count)++;
return tmp;
} else {
// HINT 1: check (*tree)->left->name and (*tree)->right->name
// (recursively) and print it as long as key==name
// HINT 2: you don't need recursion, you can do it in a loop
printf("FOUND KEY %s --> DATA %s\n", key, (*tree)->data);
fprintf(fp_out, "%s --> %s\n", key, (*tree)->data);
return *tree;
}
}
}