这是一个家庭作业,所以我有一个限制,我不能在我的函数标题/调用中使用任何方括号(仅指针)。在函数内部,我可以使用括号作为我心中的内容。
该作业是从与出生年份相对应的文件中读取婴儿名称。该文件的组织方式使得该年份中最常见的名称是第一个,第二个下一个,等等。该文件在其上显示每个{名称,性别,使用频率},如图所示: 玛丽,女,56009
现在,我只是尝试从文件中读取这些名称,并将它们放入一个字符串数组(也就是一个char数组数组)中,以便以后进行排序。不幸的是,我得到了非常奇怪的结果。到目前为止,我已经能够将其操纵为:
正确地增加num_names var但是当它工作时它会不断地替换列表开头的名称,而不是将它添加到下一个可用的char数组(正如我想要的那样)。
OR
将名称正确设置为正确的指针但是当这种情况有效时,我的num_name计数器将不会超过num_name = 1。
我不确定为什么这两个是这样的互动。我认为我误解了一些关于记忆的事情。我去过一个导师和我的导师,并试图实施他们的建议,但它总是让我回到同样的问题。我已经在下面发布了我到目前为止的所有代码。但是,我目前使用的唯一功能是(除了主要)
readAllFiles
READFILE
processName
的GetFile
和compareStrings。
我尝试将数组作为指针(*)传递,并作为指向指针(**)的指针,并以任何方式得到类似的结果。
我有很多用于调试的打印语句 - 这些都不是最终执行所必需的。
问题:我的指针/字符串数组错误地导致内存覆盖了什么?
更新:我现在可以在2-D数组中正确读取名称,并且我的num_names可以同时递增。我遇到的问题是我分配内存不正确或根本没有。我使用for循环来遍历我的2-D数组并分配行和列,这似乎有助于覆盖。但是,它现在只读取第一个文件并停在第二个文件的第一个通道。更新了以下代码。
更新2:这是所有不正确的内存分配。请参阅下面的最终代码它适用于我试图解决的问题。 代码:
/**********************************************************************************
* Most Popular Names -
* This program examines baby name data contained in text files from the
* years 1920, 1930, ..., 2010 (stored as name,sex,frequency) and
* generates an excel file containing all female names that were
* within the top 100 names for one of those years. The file will be organized
* as follows :
*
* NAME : | 1920 | 1930 | ... | 2010 |
* Ann | 5 | 4 | ... | 1 |
* Beth | 1 | 2 | ... | 5 | etc.
*
* *********************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX_NAME_LNGTH 16
#define MAX_NUM_NAMES 100
#define YEARS 10
#define FILE_1 "yob1920.txt"
#define FILE_2 "yob1930.txt"
#define FILE_3 "yob1940.txt"
#define FILE_4 "yob1950.txt"
#define FILE_5 "yob1960.txt"
#define FILE_6 "yob1970.txt"
#define FILE_7 "yob1980.txt"
#define FILE_8 "yob1990.txt"
#define FILE_9 "yob2000.txt"
#define FILE_10 "yob2010.txt"
#define OUTPUT_FILE "summary.txt"
/* FUNCTION PROTOTYPES: */
/************************/
int readAllFiles(char **, int *, int); // called in main().
FILE * getFile(const int); // called in readAllFiles().
int readFile(FILE *, char **, int *, int, int ); // called in readAllFiles().
int processName(char *, int, char **, int *, int, int); // called in readFile().
int compareStrings(char *, char *); // called in processName() and charQuickSort().
void quickSort(char ** , int *, int ); // called in main().
// called in quickSort(arg1, arg2) for recursion.
void charQuickSort(char * , int * , char * , char * , int * , int *, int );
void writeSummary(FILE *, char *, int *, int ); // called in main().
int main(void) {
printf("begin : \n");
int ** all_ranks;
int * rank_data;
int num_names = 0;
char * name_data;
char ** all_names;
name_data = malloc(MAX_NUM_NAMES * MAX_NAME_LNGTH * YEARS);
all_names = malloc(MAX_NUM_NAMES * YEARS * sizeof(*all_names));
rank_data = malloc(MAX_NUM_NAMES * YEARS);
all_ranks = malloc(MAX_NUM_NAMES * YEARS * sizeof(*all_ranks));
int i;
for(i = 0; i < MAX_NUM_NAMES * YEARS; i++) {
all_names[i] = &name_data[i * MAX_NAME_LNGTH];
all_ranks[i] = &rank_data[i * YEARS];
}
if (all_ranks != NULL && all_names != NULL) {
printf("in main\n");
printf("calling read all : \n\n");
num_names += readAllFiles(all_names, all_ranks, num_names);
// printf("in main\n");
// printf("calling quicksort : \n\n");
// quickSort(all_names, all_ranks, &num_names);
printf("in main\n");
// printf("opening file and calling write summ : \n\n");
// FILE * output = fopen(OUTPUT_FILE, "w");
// writeSummary(output, (char **) all_names, (int *) all_ranks, num_names);
// fclose(output);
}
free(rank_data);
free(all_ranks);
free(all_names);
free(name_data);
return 0;
}
/**********************************************************************
* Accepts a pointer for list of names and a pointer to
* the list of ranks to be used for the 2 - D arrays
* to hold the file(s) data.
*
* PARAMETERS :
* ************
*
* the_names - the pointer to the list of names.
*
* the_ranks - the pointer to the list of ranks parallel
* to the names.
*
* returns the size of the list when the files have all been
* processed.
*
**********************************************************************
*/
int readAllFiles(char ** the_names, int * the_ranks, int num_names) {
printf("in read all\n");
/* For indexing through the files. */
int file_num;
/*
* For each file in the array of file names process the file
* and add the names and ranks to the appropriate lists.
*/
for(file_num = 0; file_num < YEARS; file_num++) {
printf("in for loop in read all\n file number : ");
printf(" %d \n", file_num);
FILE * file = getFile(file_num);
if(file == NULL){
perror("cannot open file");
exit(EXIT_FAILURE);
} else {
printf("else : FILE OPENED.\n\n");
num_names = readFile(file, the_names, the_ranks, file_num, num_names);
printf("NUM_NAMES in read all : %d\n", num_names);
}
printf("file_num is : %d \n", file_num);
}
return num_names;
}
/*******************************************************
* Gets the appropriate file for analysis.
*
* PARAMETERS :
* ************
*
* file - the file pointer for opening.
*
* file_num - the number corresponding to the file
* in need of opening.
*******************************************************
*/
FILE * getFile(const int file_num) {
FILE * file;
printf("in get file. file num : \n");
switch (file_num) {
case 0 :
printf("1\n");
file = fopen(FILE_1, "r");
break;
case 1 :
printf("2\n");
file = fopen(FILE_2, "r");
break;
case 2 :
printf("3\n");
file = fopen(FILE_3, "r");
break;
case 3 :
printf("4\n");
file = fopen(FILE_4, "r");
break;
case 4 :
printf("5\n");
file = fopen(FILE_5, "r");
break;
case 5 :
printf("6\n");
file = fopen(FILE_6, "r");
break;
case 6 :
printf("7\n");
file = fopen(FILE_7, "r");
break;
case 7 :
printf("8\n");
file = fopen(FILE_8, "r");
break;
case 8 :
printf("9\n");
file = fopen(FILE_9, "r");
break;
case 9 :
printf("10\n");
file = fopen(FILE_10, "r");
break;
default :
printf("null\n");
file = NULL;
break;
}
return file;
}
/**********************************************************************
* Accepts a pointer to a file, a pointer to
* the list of names gathered so far, a pointer to
* the list of ranks, and the year (0-9) to which the file
* corresponds.
*
* PARAMETERS :
* ************
* this_file - the file containing the names and ranks.
*
* the_names - the list of names gathered so far.
*
* the_ranks - the list of ranks parallel to the names.
*
* the_year - the year for which the file was created.
*
* list_size - the amount of names so far contained in the list.
*
* returns the current number of names in the list.
*
**********************************************************************
*/
int readFile(FILE * this_file, char ** the_names, int * the_ranks, int year, int num_names) {
/*
* PARDON THE MESS... STILL DEBUGGING.
*/
printf("in read file \n");
/*
* For ranks 0 - 99 in the file
* get the names associated with
* the ranks and process them.
*/
int rank;
for(rank = 0; rank < MAX_NUM_NAMES; rank++) {
printf("in read file for loop \n");
char name_temp[MAX_NAME_LNGTH];
char read_line[MAX_NAME_LNGTH * 2];
int name_length = 0;
fgets(read_line, MAX_NAME_LNGTH * 2, this_file);
printf("LINE : %s\n", read_line);
while(read_line[name_length] != ',') {
name_temp[name_length] = read_line[name_length];
name_length++;
}
while(name_length < MAX_NAME_LNGTH){
name_temp[name_length] = '\0';
name_length++;
}
printf("NAME : %s\n", name_temp);
printf(" NUM NAMES : %d \n", num_names);
if (num_names) printf("BEGINNING OF NAMES (in read_file) : %s \n", the_names[0]);
// if the name was not already in the list, will increase the size variable.
num_names = processName(name_temp, rank + 1, the_names, the_ranks, year, num_names);
}
fclose(this_file);
return num_names;
}
/**********************************************************************
* Accepts a pointer to a single name, the rank
* at which this name was found, a pointer to
* the list of names gathered so far, a pointer to
* the list of ranks, and the year (0-9) in which the
* name was found (for proper indexing in the rank list).
*
* PARAMETERS :
* ************
*
* this_name - the name that must be processed.
*
* the_rank - the rank at which the name was found.
*
* name_list - the list of names gathered so far.
*
* rank_list - the list of ranks parallel to the names.
*
* year - the year in which the name was found at the
* given rank.
*
* list_size - the amount of names so far contained in the list.
*
* returns 0 if the name was already in the list and some num > 0
* if it was not in the list.
*
**********************************************************************
*/
int processName(char *this_name, int the_rank,char **the_names, int * rank_list, int year, int num_names) {
int i = 0;
printf("this name is %s\n", this_name);
while(this_name[i]) {
the_names[num_names][i] = this_name[i];
i++;
}
printf("attempt to assign this name to the end of the_names\n");
printf(" the names is now %s\n", the_names[num_names]);
num_names++;
return num_names;
}
/********************************************************************
* Sorts the names into alphabetical order by first calling
* a recursive version of this function using the values
* defined herein.
*
* PARAMETERS :
* *************
* the_names - the list of names to be sorted.
*
* the_ranks - the parallel (to the names) array of ranks.
*
* list_size - the size of the list being sorted.
********************************************************************
*/
void quickSort(char ** the_names, int * the_ranks, int list_size) {
char ** names_bck = &the_names[(MAX_NAME_LNGTH * list_size) - 1];
int ** ranks_bck = &the_ranks[(sizeof (int) * list_size) - 1];
charQuickSort(the_names, the_ranks, the_names, names_bck, the_ranks, ranks_bck, &list_size);
}
/********************************************************************
* Sorts the name array into alphabetical order using
* the quick sort method.
*
* PARAMETERS :
* *************
*
* names - the pointer to the 2 - D array of names.
*
* ranks - the pointer to the 2 - D array of ranks.
*
* name_frnt - the pointer to the front of the list of names.
*
* name_bck - the pointer to the back of the list of names.
*
* ranks_frnt - the pointer to the front of the list of ranks.
*
* ranks_bck - the pointer to the back of the list of ranks.
* ******************************************************************
*/
void charQuickSort(char * names, int * ranks, char * name_frnt, char * name_bck, int * ranks_frnt, int * ranks_bck, int size) {
// copy pointers to the back and front of the lists.
char ** tmpName_frnt = name_frnt;
char ** tmpName_bck = name_bck;
int ** tmpRank_front = ranks_frnt;
int ** tmpRank_back = ranks_bck;
// pointer variables for holding names during swaps.
char ** swap_char = NULL;
int ** swap_int = NULL;
// loop control variable.
char test;
// find a midpoint for testing
while(tmpName_frnt < tmpName_bck) {
name_frnt++;
name_bck--;
}
//loop control variable containing the value at the end of the list.
test = * name_bck;
// Set temporary pointers to traverse the list of names.
tmpName_frnt = name_frnt;
tmpName_bck = name_bck;
// Set temporary pointers to traverse the list of ranks.
tmpRank_front = ranks_frnt;
tmpRank_back = ranks_bck;
/*
* Do the following while the temporary pointer to the front
* of names list is less than the temporary pointer to the
* end of the names list.
*/
do {
/*
* While the temporary pointer to the front of the names list is less than or equal to
* the end of the names list and the value at the temporary pointer is less than the value
* at the middle of the names list increment the temporary names and ranks.
*/
while(tmpName_frnt <= names + (MAX_NUM_NAMES * MAX_NAME_LNGTH)
&& ** tmpName_frnt < test) {
tmpName_frnt += MAX_NAME_LNGTH, tmpRank_front++;
}
/*
* While the temporary pointer to the back of the names list is greater than or equal to
* the front of the names list and the value at the temporary pointer is greater than the value
* at the middle of the names list decrement the temporary names and ranks.
*/
while( tmpName_bck >= names && ** tmpName_bck > test) {
tmpName_bck -= MAX_NAME_LNGTH, tmpRank_back--;
}
/*
* If the first name is greater than the second
* (closer to Z or z), swap the pointers.
*/
if(compareStrings(*tmpName_frnt, *tmpName_bck) > 0) {
** swap_char = ** tmpName_frnt;
** swap_int = ** tmpRank_front;
** tmpName_frnt = ** tmpName_bck;
** tmpRank_front = ** tmpRank_back;
** tmpName_bck = ** swap_char;
** tmpRank_back = ** swap_int;
tmpName_frnt += MAX_NAME_LNGTH;
tmpRank_front++;
tmpName_bck -= MAX_NAME_LNGTH;
tmpRank_back--;
}
} while( tmpName_frnt <= tmpName_bck);
// Choose recursive call :
if(name_frnt < tmpName_bck) charQuickSort(names, ranks, name_frnt, tmpName_bck, ranks_frnt, tmpRank_back, size);
if(tmpName_frnt < name_bck) charQuickSort(names, ranks, tmpName_frnt, name_bck, tmpRank_front, ranks_bck, size);
}
/* ************************************************************************
* Compares two strings for equality. Returns a negative value if
* the first name is less than the second, 0 if they are equal, and
* a positive number if the first > second.
*
* PARAMETERS :
* *************
*
* name_1 - the first name for comparison.
*
* name_2 - the second name for comparison.
*
* RETURNS :
* **********
*
* a negative value if name_1 < name_2 (name_1 nearer to A or a), 0 if
* name_1 == name_2, and a positive value if name_1 > name_2
* (name_1 nearer to Z or z).
* *************************************************************************
*/
int compareStrings(char * name_1, char * name_2) {
while(* name_1 == * name_2 && * name_1 ) {
name_1++;
name_2++;
}
return (int) (* name_1 )- (int) (* name_2);
}
/******************************************************************
* Writes the summary data to a .csv file for output to excel.
*
* PARAMETERS :
* *************
*
*******************************************************************
*/
void writeSummary(FILE * the_file, char * the_names, int * the_ranks, int size) {
if(the_file == NULL) {
perror("in write summary");
perror("cannot open file");
exit(EXIT_FAILURE);
} else {
char barrier[1] = ",";
int ** rank = the_ranks;
int index, name_lngth, count;
for(index = 0; index < size; index++) {
char ** temp = the_names + (index * MAX_NAME_LNGTH);
while(** temp) {
name_lngth++;
}
rank = rank + index;
fwrite(temp, sizeof ** temp, name_lngth, the_file);
for(count = 0; count < 10; count++) {
fwrite(barrier, sizeof barrier, 1, the_file);
fwrite(rank, sizeof (int), 1, the_file);
}
}
}
}
答案 0 :(得分:0)
代码错误计算ranks_bck
。
指针算术再次出现。无需按sizeof (int)
进行缩放,因为指针算术会这样做。
void quickSort(char ** the_names, int * the_ranks, int list_size) {
char ** names_bck = &the_names[(MAX_NAME_LNGTH * list_size) - 1];
// int ** ranks_bck = &the_ranks[(sizeof (int) * list_size) - 1];
int ** ranks_bck = &the_ranks[list_size - 1];
...
}
OP有许多问题 - 这是一个问题。