Linux下采用C语言实现文本单词计数(word count)并统计运行时间

Linux下采用C语言实现文本单词计数(word count)并统计运行时间

由于WHUT的云计算课程实验要求,采用C lang实现word count功能。不得不说,用C语言处理字符串,真有一种想砸了电脑的冲动。。。

下面是源码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>


int* findn(int A[], int N);

int main() {

	FILE* fp;

	char fileName[256] = "/usr/local/data.dat";

	// scanf("%s", &fileName);

	fp = fopen(fileName, "r");  /* 以只读方式读取文件 */
        
	clock_t start, stop;

	start = clock();

	int word_count = 0;	 // 记录单词总数

	char store[60][15] = { '\0' };

	char key[15] = { '\0' };

	char temp[15] = { '\0' };

	int weight[60] = {0};

	int value = 0;
	
	int key_length = 0;

	while ((value = fgetc(fp)) != EOF) {    /* 当文件未到末尾时,统计各对应字符的权值 (即频数) */

		if (value != ' ') {

			if (value != '.' && value != ',' && value != '!' && value != '?' && value != ':' && value != '#') {

				key[key_length++] = value;	// 获得单词key

			}

		}
		
		if (value == ' ' || value == '#' || value == '\n') {

			key[key_length] = '\0';

			if (word_count == 0) {	// 第一次

				for (int m = 0; m <= key_length; m++) {	// 将每个单词以行的形式存储在二维数组store中

					store[0][m] = key[m];

				}

				weight[word_count]++;

				word_count++;

			} else {

				int flag = 0;

				for (int i = 0; i < word_count; i++) {
					
					int k;

					for (k = 0; store[i][k] != '\0'; k++) {	// 将每个单词以行的形式存储在二维数组store中

						temp[k] = store[i][k];

					}

					temp[k] = '\0';

					int isOkay = -1;

					if (abs(temp[0] - key[0]) == 32 && strlen(temp) == strlen(key)) {	// 相差32 & 长度相同

						char dest1[15] = { '\0' };

						char dest2[15] = { '\0' };

						int sub_length = strlen(temp) - 1;

						strncpy(dest1, temp + 1, sub_length);
						strncpy(dest2, key + 1, sub_length);

						isOkay = strcmp(dest1, dest2);

						if (isOkay == 0) {	// 相同单词, 首字母大小写不同

							weight[i]++;

							flag = 1;

							break;

						}

					}
					else {

						isOkay = strcmp(key, temp);	// 0相同, 1不同

						if (isOkay == 0) {	// 相同单词

							weight[i]++;

							flag = 1;

							break;

						}

					}

				}

				if (flag == 0) {	// 全新单词

					for (int j = 0; j < key_length; j++) { 

						store[word_count][j] = key[j];

					}

					weight[word_count]++;

					word_count++;

				}

			}

			key_length = 0;

		}

	}


	//for (int i = 0; i < word_count; i++) {	// 调试用

	//	for (int j = 0; store[i][j] != '\0'; j++) {

	//		printf("%c", store[i][j]);

	//	}

	//	printf("%4d\n", weight[i]);

	//}


	int* index = findn(weight, word_count);

	for (int i = 0; i < 3; i++) {

		int order = *(index + i);

		for (int j = 0; store[order][j] != '\0'; j++) {

			printf("%c", store[order][j]);

		}

		printf("%4d\n", weight[order]);

	}

	stop = clock();

	double duration = (double)(stop - start) / CLOCKS_PER_SEC;
	
	printf("word_count time: %fs\n",  duration);
        
        return 0;

}


int* findn(int A[], int N) {	// 冒泡排序

	int value[3] = { 0 };

	int max = 0;

	static int index[3] = { 0 };	// 此处必须加static,否则报错!

	for (int j = 0; j < 3; j++) {

		for (int i = 0; i < N; i++) {

			if (A[i] > max) {

				max = i;
				value[j] = A[i];

			}

		}

		index[j] = max;

		A[max] = 0;

		max = 0;

	}

	for (int j = 0; j < 3; j++) {

		A[index[j]] = value[j];

	}

	return index;

}


几点说明

  1. 没有完全考虑到英文中的所有标点符号,不过可以自己在程序中 获得单词key 的位置修改!

  2. 该程序以 # 作为结尾标识。

  3. 该程序在Linux下的GCC编译器运行通过。(注意输入的文件路径中不能包含 中文 (血的教训!!),否则会出现段错误(核心转储))
    如下图所示:
    在这里插入图片描述

  4. findn函数只实现了找到单词数量 前3 的单词,没有实现返回前n个单词的下标序列。而且需要注意的是findn函数中返回的数组在声明时,必须加 static

  5. 在linux下GNU的GCC编译器中,对头文件 <string.h><time.h> 的实现与windows下的Visual Studio的C lang编译器实现有差异。
    此处不一 一列举,只说明在本程序中的差异:

    1. 在Visual Studio的C lang编译器中,strcpy() 为可用于截取字符串,而在linux下,这一功能改用strncpy() 实现。
    2. 在Visual Studio的C lang编译器中,CLK_TCK 为一个时钟周期,而在linux下,这一功能改用CLOCKS_PER_SEC 实现。

最后还是不得不说,C lang处理字符串真的好垃圾! 不得不感叹,Java String的伟大!!

发布了69 篇原创文章 · 获赞 11 · 访问量 8440

猜你喜欢

转载自blog.csdn.net/qq_40994260/article/details/105091051