与文件

时间:2016-11-30 16:57:51

标签: c string

我试图制作一个程序,逐行扫描包含单词的文件,并删除拼写相同的单词,如果你向后阅读它们(回文)

这是program.c文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"

int main(int argc, char **argv)
{
if(argc != 3)
{
   printf("Wrong parameters");
   return 0;
}
FILE *data;
FILE *result;
char *StringFromFile = (char*)malloc(255);
char *word = (char*)malloc(255);

const char *dat = argv[1];
const char *res = argv[2];

data = fopen(dat, "r");
result =fopen(res, "w");

while(fgets(StringFromFile, 255, data))
{
    function1(StringFromFile, word);
    fputs(StringFromFile, result);
}
free(StringFromFile);
free (word);
fclose(data);
fclose(result);
return 0;
}

这是header.h文件:

#ifndef HEADER_H_INCLUDEC
#define HEADER_H_INCLUDED

void function1(char *StringFromFile, char *word);
void moving(char *StringFromFile, int *index, int StringLength, int WordLength);

#endif

这是函数文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"

void function1(char *StringFromFile, char *word)
{
int StringLength = strlen(StringFromFile);
int WordLength;
int i;
int p;
int k;
int t;
int m;
int match;
for(i = 0; i < StringLength; i++)
{   k=0;
    t=0;
    m=i;
if (StringFromFile[i] != ' ')
{   while (StringFromFile[i] != ' ')
    {
        word[k]=StringFromFile[i];
        k=k+1;
        i=i+1;
    }
//printf("%s\n", word);
WordLength = strlen(word)-1;
p = WordLength-1;
match=0;
while (t <= p)
{
    if (word[t] == word[p])
        {
            match=match+1;
        }
    t=t+1;
    p=p-1;
}
if ((match*2) >= (WordLength))
{
    moving(StringFromFile, &m, StringLength, WordLength);
}
}
}

}

void moving(char *StringFromFile, int *index, int StringLength, int WordLength)
{   int i;
    int q=WordLength-1;
    for(i = *index; i < StringLength; i++)
{
    StringFromFile[i-1] = StringFromFile[i+q];
}
*(index) = *(index)-1;
}

但是,它并没有正确读取每个单词。

这是数据文件:

abcba rttt plllp
aaaaaaaaaaaa
ababa
abbbba
kede

这些是程序读取的单独词语:

abcba
rttta
plllp
aaaaaaaaaaaa
ababa
abbbba
kede

这是结果文件:

abcba rtttp



kede

如果一行中只有一个单词,它可以正常工作,但是当有多个单词时它会混乱。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:0)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"

# define MAX 255

int Find_Number_Words_in_Line( char str[MAX] )
{
   char *ptr;
   int count = 0;
   int j;

   /* advance character pointer ptr until end of str[MAX] */
   /* everytime you see the space character, increase count */
   /* might not always work, you'll need to handle multiple space characters before/between/after words */

   ptr = str;
   for ( j = 0; j < MAX; j++ )
   {
      if ( *ptr == ' ' )
         count++;
      else if (( *ptr == '\0' ) || ( *ptr == '\n' ))
         break;

      ptr++;
   }

   return count;
}

void Extract_Word_From_Line_Based_on_Position( char line[MAX], char word[MAX], const int position )
{
   char *ptr;

   /* move pointer down line[], counting past the number of spaces specified by position */
   /* then copy the next word from line[] into word[] */
}


int Is_Palindrome ( char str[MAX] )
{
   /* check if str[] is a palindrome, if so return 1, else return 0 */
}


int main(int argc, char **argv)
{
   FILE *data_file;
   FILE *result_file;
   char *line_from_data_file = (char*)malloc(MAX);
   char *word = (char*)malloc(MAX);
   const char *dat = argv[1];
   const char *res = argv[2];
   int j, n;

   if (argc != 3)
   {
      printf("Wrong parameters");
      return 0;
   }

   data_file = fopen(dat, "r");
   result_file = fopen(res, "w");

   fgets( line_from_data_file, MAX, data_file );
   while ( ! feof( data_file ) )
   {
       /*
          fgets returns everything up to newline character from data_file,
          function1 in original context would only run once for each line read
          from data_file, so you would only get the first word

             function1( line_from_data_file, word );
             fputs( word, result_file );
             fgets( line_from_data_file, MAX, data_file );

          instead try below, you will need to write the code for these new functions
          don't be afraid to name functions in basic English for what they are meant to do
          make your code more easily readable
       */

      n = Find_Number_Words_in_Line( line_from_data_file );
      for ( j = 0; j < n; j++ )
      {
         Extract_Word_From_Line_Based_on_Position( line_from_data_file, word, n );
         if ( Is_Palindrome( word ) )
            fputs( word, result_file );  /* this will put one palindrome per line in result file */
      }

      fgets( line_from_data_file, MAX, data_file );
   }
   free( line_from_data_file );
   free( word );

   fclose( data_file );
   fclose( result_file );

   return 0;
}

答案 1 :(得分:0)

要对评论进行跟进,您可能会过度思考问题。要检查文件每行中的每个单词是否为回文,您有2个问题。 (1)阅读每一行(fgets没问题),以及(2)将每一行分成单个单词(标记),以便测试每个标记是否为回文。

当使用fgets读取每一行时,以fgets的返回为条件的简单while循环将会起作用。例如,如果缓冲区buf具有足够大小(MAXC字符),并且FILE *fp可供阅读,则可以执行以下操作:

while (fgets (buf, MAXC, fp)) { /* read each line */
    ...                         /* process line */
}

(你可以测试读入buf的行的长度是否小于MAXC个字符,以确保你读完整行,如果没有,任何未读的字符将放在buf在下一个循环迭代中。这个检查,以及你想如何处理它,留给你。)

读完行后,您可以使用一对简单的指针(开始和结束指针)来完成buf的工作,也可以使用strtok让它返回根据传递给它的分隔符集指向行中每个单词的开头。例如,要将一行划分为单词,您可能希望使用" \t\n.,:;!?"之类的分隔符来确保单独使用单词而不是带有标点符号的单词(例如,在"sit here."行中,您需要"sit" }和"here",而不是"here."

使用strtok很简单。在第一次调用时,传递包含要标记的字符串的缓冲区的名称和指向包含分隔符的字符串的指针(例如上面的strtok (buf, delims)),然后为每个后续调用(直到行的结尾是达到了)你使用NULL作为缓冲区的名称(例如strtok (NULL, delims))你可以调用它一次然后循环直到返回NULL,或者你可以使用一个for {1}}循环,for允许将初始条件设置为语句的一部分,例如,使用单独的调用:

char  *delims = " \t\n.,:;";    /* delimiters */
char *p = strtok (buf, delims); /* first call to strtok */

while ((p = strtok (NULL, delims))) {  /* all subsequent calls */
    ... /* check for palindrome */
}

或者您可以在for循环中进行初始调用和所有后续调用:

/* same thing in a single 'for' statement */
for (p = strtok (buf, delims); p; p = strtok (NULL, delims)) {
    ... /* check for palindrome */
}

现在,您需要检查回文。这是一个相当简单的过程。找到令牌的长度,然后使用字符串索引,或者只是使用指向第一个和最后一个字符的指针,从每个令牌的末尾到中间工作,确保字符匹配。在第一次不匹配时,您知道令牌不是回文。我发现开始和结束指针就像操纵刺痛索引一样简单,例如使用s中的令牌:

char *ispalindrome (char *s)    /* function to check palindrome */
{
    char *p = s,                   /* start pointer */
        *ep = s + strlen (s) - 1;  /* end pointer  */

    for ( ; p < ep; p++, ep--)  /* work from end to middle */
        if (*p != *ep)          /* if chars !=, not palindrome */
            return NULL;

    return s;
}

如果将所有部分放在一起,您可以执行以下操作:

#include <stdio.h>
#include <string.h>

enum { MAXC = 256 };    /* max chars for line buffer */

char *ispalindrome (char *s);

int main (int argc, char **argv) {

    char buf[MAXC] = "",        /* line buffer */
         *delims = " \t\n.,:;"; /* delimiters */
    unsigned ndx = 0;           /* line index */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    while (fgets (buf, MAXC, fp)) { /* read each line */
        char *p = buf;   /* pointer to pass to strtok */
        printf ("\n line[%2u]:  %s\n tokens:\n", ndx++, buf);
        for (p = strtok (buf, delims); p; p = strtok (NULL, delims))
            if (ispalindrome (p))
                printf ("  %-16s  - palindrome\n", p);
            else
                printf ("  %-16s  - not palindrome\n", p);
    }
    if (fp != stdin) fclose (fp);

    return 0;
}

char *ispalindrome (char *s)    /* function to check palindrome */
{
    char *p = s, *ep = s + strlen (s) - 1;  /* ptr & end-ptr */

    for ( ; p < ep; p++, ep--)  /* work from end to middle */
        if (*p != *ep)          /* if chars !=, not palindrome */
            return NULL;

    return s;
}

示例输入

$ cat dat/palins.txt
abcba rttt plllp
aaaaaaaaaaaa
ababa
abbbba
kede

示例使用/输出

$ ./bin/palindrome <dat/palins.txt

 line[ 0]:  abcba rttt plllp

 tokens:
  abcba             - palindrome
  rttt              - not palindrome
  plllp             - palindrome

 line[ 1]:  aaaaaaaaaaaa

 tokens:
  aaaaaaaaaaaa      - palindrome

 line[ 2]:  ababa

 tokens:
  ababa             - palindrome

 line[ 3]:  abbbba

 tokens:
  abbbba            - palindrome

 line[ 4]:  kede

 tokens:
  kede              - not palindrome

仔细研究并思考它发生了什么。如上所述,确保您已使用fgets在每次通话中阅读完整的一行,应该进行验证,由您自行决定。 (但是有了这个输入文件 - 当然会有)如果您有任何问题,请告诉我,我会很乐意为您提供进一步的帮助。