我是C的新手,我还在学习基础知识。我正在创建一个读取文本文件并单独分解单词的应用程序。我的目的是计算每个单词出现的次数。
无论如何,下面代码中的最后一个do-while循环执行正常,然后崩溃。此循环将内存地址输出到该字(指针),然后打印该字。它完成了这一点,然后在最后一次迭代时崩溃。我的目的是将这个内存地址压缩成一个单独链接的列表,尽管它已经停止崩溃了。
另外,请快速提一下下面的阵列尺寸;我还想出了如何设置保持单词字符数组等所需的正确大小,因为你必须在数组填充之前定义大小,我不知道如何做到这一点。因此我将它们设置为1024。
#include<stdio.h>
#include<string.h>
int main (int argc, char **argv) {
FILE * pFile;
int c;
int n = 0;
char *wp;
char wordArray[1024];
char delims[] = " "; // delims spaces in the word array.
char *result = NULL;
result = strtok(wordArray, delims);
char holder[1024];
pFile=fopen (argv[1],"r");
if (pFile == NULL) perror ("Error opening file");
else {
do {
c = fgetc (pFile);
wordArray[n] = c;
n++;
} while (c != EOF);
n = 0;
fclose (pFile);
do {
result = strtok(NULL, delims);
holder[n] = *result; // holder stores the value of 'result', which should be a word.
wp = &holder[n]; // wp points to the address of 'holder' which holds the 'result'.
n++;
printf("Pointer value = %d\n", wp); // Prints the address of holder.
printf("Result is \"%s\"\n", result); // Prints the 'result' which is a word from the array.
//sl_push_front(&wp); // Push address onto stack.
} while (result != NULL);
}
return 0;
}
请忽略糟糕的程序结构,正如我所提到的,我是新手!
由于
答案 0 :(得分:2)
正如其他人所指出的那样,你的第二个循环试图在之前取消引用result
,检查它是NULL
。按如下方式重构代码:
result = strtok( wordArray, delims ); // do this *after* you have read data into
// wordArray
while( result != NULL )
{
holder[n] = *result;
...
result = strtok( NULL, delims );
}
...虽然
您尝试将文件的全部内容读入内存,然后再将其分解为单词;这对于大于缓冲区大小的文件(目前为1K)不起作用。如果我可以提出建议,请更改您的代码,以便您随时阅读单个单词。这是一个将输入流分解为由空格(空格,换行符,制表符等)和标点符号(句点,逗号等)分隔的单词的示例:
#include <stdio.h>
#include <ctype.h>
int main(int argc, char **argv)
{
char buffer[1024];
int c;
size_t n = 0;
FILE *input = stdin;
if( argc > 1 )
{
input = fopen( argv[1], "r");
if (!input)
input = stdin;
}
while(( c = fgetc(input)) != EOF )
{
if (isspace(c) || ispunct(c))
{
if (n > 0)
{
buffer[n] = 0;
printf("read word %s\n", buffer);
n = 0;
}
}
else
{
buffer[n++] = c;
}
}
if (n > 0)
{
buffer[n] = 0;
printf("read word %s\n", buffer);
}
fclose(input);
return 0;
}
没有任何明示或暗示的保证(在上午7点之前敲定了这一点)。但它应该让你了解如何解析文件。如果不出意外,它可以避免使用strtok
,这是不是解析输入的最佳工具。您应该能够将此常规结构调整为您的代码。为了获得最佳结果,您应该将其抽象为自己的函数:
int getNextWord(FILE *stream, char *buf, size_t bufsize)
{
int c;
size_t n = 0;
while(( c = fgetc(input)) != EOF && n < bufsize)
{
if (isspace(c) || ispunct(c))
{
if (n > 0)
{
buf[n] = 0;
n = 0;
}
}
else
{
buffer[n++] = c;
}
}
if (n > 0)
{
buffer[n] = 0;
printf("read word %s\n", buffer);
}
if (n == 0)
return 0;
else
return 1;
}
你会称之为
void foo(void)
{
char word[SOME_SIZE];
...
while (getNextWord(inFile, word, sizeof word))
{
do_something_with(word);
}
...
}
答案 1 :(得分:1)
如果您希望在do...while
代码中,result
可能是null
(这是循环中断的条件),您如何看待此代码行:
holder[n] = *result;
必须工作吗?在我看来,这是你的程序崩溃的原因。
答案 2 :(得分:1)
将do while
循环更改为while
使用
while (condition)
{
}
而不是
do {
}while(condition)
它崩溃了,因为你试图在do while循环中derefrance一个NULL指针result
。
答案 3 :(得分:0)
我主要使用Objective-C工作,只是为了好玩而看你的问题,但我可能有一个解决方案。
在第一次do-while循环之后设置n=0;
之前,创建另一个名为totalWords
的变量并将其设置为n,可以在文件中的任何位置声明totalWords(除了其中一个之外) while循环),但可以在else块的顶部定义,因为它的生命周期很短:
totalWords = n;
然后你可以将n设置为零:
n = 0;
你最后的do-while循环的条件应该说:
...
} while (n <= ++totalWords);
应用程序背后的逻辑将说,计算文件中的单词(有n个单词,即文件中的totalWords)。当程序将结果打印到控制台时,它将运行第二个do-while循环,该循环将运行,直到n是totalWords值之后的一个结果(这可确保您打印最终单词)。
或者,对于其他程序员来说,使用一个半圈是更好的练习和清晰:
do {
result = strtok(NULL, delims);
holder[n] = *result;
wp = &holder[n];
printf("Pointer value = %d\n", wp);
printf("Result is \"%s\"\n", result);
//sl_push_front(&wp); // Push address onto stack.
if (n == totalWords) break; // This forces the program to exit the do-while after we have printed the last word
n++; // We only need to increment if we have not reached the last word
// if our logic is bad, we will enter an infinite loop, which will tell us while testing that our logic is bad.
} while (true);