编写一个小型C程序,打印文件每行中的第一个单词

时间:2012-10-25 03:45:30

标签: c

这是我到目前为止所拥有的,

#include<stdio.h>
#include<stdlib.h>

void main(int argc, char *argv[]){

  FILE *fp;
  char word[30];
  int k;
  for (k=1 ; k < argc ; k++)
    {
      fp = fopen(argv[k],"r");
      if (fp == NULL)
        fprintf(stdout,"Error with file: %s\n",argv[k]);
      else{
        while( !feof(fp) ){
           fscanf(fp,%s%*[^\n]",word);
           printf("word: %s\n",word);
           memset(word,0,sizeof(word));                       
        }
      }
    fclose(fp);
    }
}

我不确定我的内容是否正确,我也不确定我应该在while循环中打印出文件中每一行的每个第一个单词。非常感谢帮助,提前感谢您的任何帮助/提示!

2 个答案:

答案 0 :(得分:1)

首先,您可以替换:

int k = 1;
for (k; k < argc; k++)

更“标准”:

int k;
for (k = 1; k < argc; k++)

然后,在else部分内,一个简单的循环和状态机,它只输出第一个单词中的字符。基于字符的状态机的优点是线路的长度无关紧要,并且没有缓冲区溢出的可能性。

使用30个字符的缓冲区,如果您对包含(例如)60个字符的文件尝试逐行处理,则可能会遇到问题。

以下伪代码可能有所帮助:

state = before_word
get character from input stream (see fgetc)
while character is not end-of-file:
    if character is newline:
        echo character (see putchar)
        state = before_word
    else
        if state is before_word:
            if character is not white space (see isblank/isspace):
                echo character
                state = in_word
            endif
        else
            if state is in_word:
                if character is white space:
                    state = past_word
                else
                    echo character
                endif
            endif
        endif
    endif
    get character from input stream (see fgetc)
endwhile

它的工作原理是维持一个状态(你的状态取决于通过输入流进入的东西)。

初始状态为before_word,因为它紧接在文件第一行之前的假想换行之后。在该状态下,所有空白字符都被丢弃,第一个非空格字符会在回显该字符后使状态更改为in_word

状态为in_word时,输出每个字符。到达该状态的第一个空格字符不会输出,并导致状态转换为past_word

past_word状态下,所有字符都被丢弃。

在任何状态下(此if语句为第一个),换行符会强制状态变为before_word

将伪代码转换为C代码将是一个很好的练习,特别是如果这是作业。


如果不是作业,则下面是一个解决方案。因为SO是一个公共网站而要警惕将其作为自己的工作,并且我确信教育工作者会检查这些网站是否存在抄袭。对echoAndChange的简单Google搜索几乎肯定会让您失败。

所以,假设它不是家庭作业,或者你只是想要一些东西来检查你自己的解决方案,我们走了:

#include <stdio.h>
#include <ctype.h>

// States and utility function for echo and change state.

typedef enum {ST_PRE, ST_IN, ST_POST} tState;

tState echoAndChange (int chr, tState newState) {
    if (chr != EOF) putchar (chr);
    return newState;
}

int main (int argc, char *argv[]) {
    FILE *fp;
    int k, chr;
    tState state;

    // Process each file.

    for (k = 1; k < argc; k++) {
        fp = fopen (argv[1], "r");
        if (fp == NULL) {
            printf ("Error with file: %s\n", argv[1]);
        } else {
            // Initial state pre-word, then process every character.

            state = ST_PRE;
            while (1) {
                chr = fgetc (fp); if (chr == EOF) break;

                // Newline: output it and change to pre-word.

                if (chr == '\n') {
                    state = echoAndChange (chr, ST_PRE);
                    continue;
                }

                // Pre-word and nonspace: echo and change to in-word.

                if (state == ST_PRE) {
                    if (!isblank (chr))
                        state = echoAndChange (chr, ST_IN);
                    continue;
                }

                // In-word: change to post word if space, otherwise echo.

                if (state == ST_IN)
                    if (isblank (chr))
                        state = echoAndChange (EOF, ST_POST);
                    else
                        state = echoAndChange (chr, ST_IN);
            }
            fclose (fp);
        }
    }
    return 0;
}

在着名的“Lorem ipsum”文本上运行该程序时:

Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.

你可以看到它的实际效果:

Lorem
sed
aliqua.
ullamco
Duis
esse
occaecat
deserunt

如果你想要一个更短的程序,你可以将一些状态机吸收到你的语句执行的 order 中(而不用担心前导空格)像:

#include <stdio.h>
#include <ctype.h>

int main (int argc, char *argv[]) {
    FILE *fp;
    int echo, chr;

    if (argc < 2) {
        puts ("Usage: firstword <input-file>");
        return -1;
    }

    fp = fopen (argv[1], "r");
    if (fp == NULL) {
        printf ("Error with file: %s\n", argv[1]);
        return -1;
    }

    echo = 1;
    chr = fgetc (fp);
    while (chr != EOF) {
        if (chr == '\n') echo = 1;
        if (isblank (chr)) echo = 0;
        if (echo ) putchar (chr);
        chr = fgetc (fp);
    }
    fclose (fp);
    return 0;
}

这里的基本规则是:

  • 初始状态是回声。
  • 然后,对于每个角色:
    • Newline强制回显(换行符向下两行)。
    • 任何空白都会回响。
    • 如果回显,则回显字符。

答案 1 :(得分:1)

有几种方法可以做到这一点。一种方法是使用getline()逐行读取文件,然后将字符打印到第一个空格字符:

#include <ctype.h>

char *line = NULL;
size_t siz = 0;
int i = 0;

while(-1 != getline(&line, &siz, fp)){
    for(i = 0; i < siz && !isspace(line[i]); i++){
        printf("%c", line[i]);
    }
}

这仍然会留下一些边缘情况(空白行等),但它应该让你开始。