循环崩溃在C

时间:2013-03-28 11:07:58

标签: c do-while

我是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;

}

请忽略糟糕的程序结构,正如我所提到的,我是新手!

由于

4 个答案:

答案 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);