c - 如何初始化一个不定长度的数组
问题描述
我下面的代码提供了 word 文件中出现“is”的次数。但是在这个程序中,我预先定义了文件的大小。帮我修改程序,以便我可以在字数未知的文件中获取单词“is”。数组文件的长度应该等于word文件的长度。
// Count of occurrence of word 'is' in file WordFile.
#include<stdio.h>
#include<conio.h>
#include<string.h>
//function to append
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
void main()
{
FILE *fp;
int i=0,count=0,j,k,space,times=0;
char ch,file[1000];
fp = fopen("../WordFile.txt","r");
while ((ch=fgetc(fp)) != EOF)
{
count++;
append(file,ch);
}
printf("Count of file is %d \n",count);
printf("%s \n",file);
for(i=0;i<(count-3);i++)
{
j = (file[i] == 'i' || file[i] == 'I');
k = (file[i+1] == 's' || file[i+1] == 'S');
space = (file[i+2] == ' ' || file[i+2] == ',' || file[i+2] == EOF);
if( (j && k && space ) == 1 )
times ++;
}
printf("the string IS appeared %d times in the griven file. \n", times);
getch();
}
解决方案
您可以使用stat()
, from获取文件的大小<sys/stat.h>
;例如,请参阅这个 SO 问题:How do you determine the size of a file in C? 一旦有了文件大小,就可以分配一个足够大的 char 数组来容纳它。
但是,您也可以在不先将其全部读入内存的情况下解析文件。您一次将几个字节读入一个小缓冲区并仅使用这些字节。下面是基于您的代码的该方法的快速n-dirty 实现。
请注意:有几种方法可以改进此代码。一方面,应该有更多的错误检查;另一方面,您可以使用strcmp()
//strncmp()
系列strnicmp()
函数更有效地检查输入缓冲区;另一方面,您可以使用命令行参数而不是硬编码值(我在下面这样做了;这是我可以提供一堆测试输入文件的唯一明智的方法);对于另一个,您可以使用 egbuf[indx++] = ch
作为速记(因为该后增量);等等
我对下面代码的主要观点是帮助您开始将文件处理视为流,而不是预先读取整个文件。其他人在您的问题中添加的评论也值得注意。希望这可以帮助!
// count of occurrences of word 'is' in input file
#include<stdio.h>
#include<string.h>
int main(int argc, char** argv) {
FILE *fp;
int count = 0;
int times = 0;
char ch = 0;
char buf[8]; // more than enough room to look for 'is' words
int indx = 0;
fp = fopen(argv[1], "r");
// fill the input buffer with nul bytes
memset(buf, 0, 8);
indx = 0;
// pretend that the input file starts with ' ', in order
// to detect 'is' at the start of the file
buf[indx] = ' ';
indx++;
while ((ch = fgetc(fp)) != EOF) {
count++;
buf[indx] = ch;
indx++;
// uncomment this to see the progression of 'buf' as
// the input file is being read
//printf("buf is : [%s]\n", buf);
// if the input buffer does not begin with a word
// boundary, start the input buffer over by resetting
// it and looping back to the top of the reading loop
if (buf[0] != ' ' && buf[0] != ',' && buf[0] != '\n') {
memset(buf, 0, 8);
indx = 0;
continue;
}
// if we have read 4 characters (indx 0 through indx 3),
// it's time to look to see if we have an 'is'
if (indx == 4) {
// if we have 'is' between word boundaries, count it
if ((buf[0] == ' ' || buf[0] == ',' || buf[0] == '\n') &&
(buf[1] == 'i' || buf[1] == 'I') &&
(buf[2] == 's' || buf[2] == 'S') &&
(buf[3] == ' ' || buf[3] == ',' || buf[3] == '\n')) {
times++;
}
// reset the input buffer
memset(buf, 0, 8);
indx = 0;
// if we ended with a word boundary, preserve it as the
// word boundary at the beginning of the next word
if (ch == ' ' || ch == ',' || ch == '\n') {
buf[indx] = ' ';
indx++;
}
}
}
// EOF is also a word boundary, so we do one final check to see
// if there is an 'is' at the end of the file
if ((buf[0] == ' ' || buf[0] == ',' || buf[0] == '\n') &&
(buf[1] == 'i' || buf[1] == 'I') &&
(buf[2] == 's' || buf[2] == 'S')) {
times++;
}
printf("input file is %d characters long\n", count);
printf("the string IS appeared %d times in the input file\n", times);
}
关于 argc 和 argv 的附加信息(re: comment question)
argc是命令行参数的数量; argv是一组指向这些命令行参数的指针。
argv[0]
总是指向命令本身(即执行程序的名称)。 argc
通常用于检查命令行参数的最小数量,作为循环命令行参数的限制,作为使用之前的测试argv[n]
等。有时,您会看到 argv 指定为char *argv[]
,其操作方式当然与char **argv
.
因此,该行fp = fopen(argv[1], "r");
使用第一个命令行参数作为输入文件的文件名。例如,在我的测试中,我将此代码编译为countis
并使用countis countis-input-test-001
. (我有一系列测试输入文件,并使用一个 shell 脚本来处理每个文件,以测试我对程序所做的每一次编辑。)
这里有几个地方可以阅读更多内容并查看使用 argc 和 argv 的代码示例:
https://www.tutorialspoint.com/cprogramming/c_command_line_arguments.htm http://www.teach.cs.toronto.edu/~ajr/209/notes/argv.html
您还可以通过 googlec programming argc argv
或类似网站搜索更多类似资源。
推荐阅读
- laravel - Laravel如何处理文件上传:无法保存图像文件名
- python - 在 Django 应用程序中读取 JSON 文件行时出错
- javascript - 如何使已排序的对象数组具有不同的值
- date - 在 Google 脚本和 Goggle Sheet 中添加未来日期
- python - scipy.stats.gamma 库中的参数 a 是什么
- gps - tcx - 如何计算两个轨迹点之间的距离
- windows-10 - 是否可以使用 VM 加速程序?
- vue.js - Vue初始化用户存储
- javascript - 将数组的字符串表示形式转换为 JSON
- python - 类型错误:setSubregion_id() 缺少 1 个必需的位置参数:'subregion_id'