【问题标题】:C programming assignmnt help: read in and print formattedC 编程作业帮助:读入并打印格式化
【发布时间】:2013-02-06 17:26:27
【问题描述】:

这是一个 C 作业。我不是要求任何人为我做这件事,我只是碰壁了。明天就要交了,不知道怎么办。我是初学者,我的头开始受伤了

编写一个 ANSI C 程序,该程序对文本进行格式化,以便它很好地适合给定数量的列。文本格式化程序必须右对齐输入文本文件,以便右边距对齐在一条直线上,但有一个例外。最后一行没有正确对齐。此外,段落不会合并在一起。输出行之间的间距应均匀。

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

#define IN 1
#define OUT 0

/*
   This is the start of the main pgoram which originated from the K & R word  counter...
   we comment to understand each part...
 */
int main()
{
    /*
     * This is the pointer to the file object we will be readin in
     * from...
     */
    FILE           *ptr_file;
    char           *outputbuf;

    /*
     * This variable will hold the maximum width of the line we are to
     * output
     */
    int width;
    char eatspace;
    char  c;    /* We read each character invidually */

    int   state = OUT;

    int   nc = 0;   /* This is the total count of all words in the document */
    int   nl = 0;   /* This is the total count of newlines in the document  */
    int   nw = 0;  
    int   lw = 0;   /* Count the total whitespaces spaces per line */
    int   buff_offset = 0; /* Keep track of how many letters we are into the current output line */

    /* Opens a file stream for the .txt file to be read in */
    ptr_file = fopen("hollo_man.txt", "r");
    if ((fopen("hollo_man.txt", "r")) != NULL) {
        /*
         * This loop reads in one character at a time until the end
         * of file
         */

        /* Read the first line to get the width of the output */
        fscanf (ptr_file, "%i", &width); 
        outputbuf = (char*) malloc(width + 1);
        //fscanf(ptr_file, "%c", &eatspace);

        int prev_char_was_space = 0;

        while ((c = fgetc(ptr_file)) != EOF)
        {
            ++nc;
            if (c == '\n' || strlen(outputbuf) == width) 
            {
                outputbuf[buff_offset] = '\0';      
                ++nl;
                //              printf("Saw a newline, newline count is now: %i\n", nl);
                /* Our buffer needs to be ended since we saw a newline */

                for(int i = 0; i < (width - buff_offset); i++)
                {
                    printf(" ");

                }
                printf("%s\n", outputbuf);

                memset(outputbuf, width, '\0');

                buff_offset = 0; 
                prev_char_was_space = 0;

            }

            /* This more verbose check is to see if there is other whitespace */
            else if (isspace(c)) 
            {


                /* We only store one space between words in the output, this allows us to easily and evenly pad with white space later */
                if (!prev_char_was_space)
                {

                    outputbuf[buff_offset] = c;
                    outputbuf[buff_offset + 1] = '\0';                  
                    buff_offset++;                  

                    lw++;
                    prev_char_was_space = 1;
                }   
            }
            else /* This was not a whitespace character so store it in the current line buffer */
            {

                prev_char_was_space = 0; /* Keep track that we didnt have a whitespace for the next iteration */
                outputbuf[buff_offset] = c;
                buff_offset++;
                ++nw;


            }

        } /* End reading each character */

        /* This line should indeed print output to console for now */
        //fprintf(stderr, "ORIG LINE COUNT: %d\nORIG WORD COUNT: %d\nORIG CHAR COUNT: %d\n", nl, lw, nc);
        /* Close our file and clean up */
        fclose(ptr_file);
    }

    return 0;
}

它所做的只是打印出一个空白行。我想我需要另一个缓冲区,但我真的不知道。我将如何打印它,然后用填充空格均匀地间隔单词?我也不确定如何将每一行打印到指定的宽度。任何帮助将不胜感激!

【问题讨论】:

    标签: c


    【解决方案1】:

    双fopen的小问题,应该减少到一个。

    您的文件可能具有如下格式:

    15
    The quick
    brown
    

    问题是你的逻辑是这样的:

    /* Opens a file stream for the .txt file to be read in */
    ptr_file = fopen("hollo_man.txt", "r");
    if (/*the file was opened correctly */) {
    
            Read 'width' from the first word of the file;
            Create a buffer exactly 'width'+1 in size;
    
            while(get_a_character != EOF) {
                increment_total_character_count;
                if(character_is_newline)
                    increment_newline_count;
                    insert a '\0' in the output buffer;
                    reset the index we're inserting into the output buffer
                    prevCharacterIsSpace = false;
                if(character_is_space)
                    if(previous_character_NOT_a_space)
                        put_character_in_output_buffer;
                        increment_word_counter;
                        prevCharacterIsSpace = true;
                else
                    prevCharacterIsSpace = true;
                    put_character_in_output_buffer;
                    increment_nw (never used)
            }
    
    
            needed_spaces = (width - nc) % lw;
            printf(" %s", outputbuf);
    

    如果输入文件有上述格式,宽度出现在它自己的一行,你正在读取的字符流是这样的:

    '15' (read as a unit with the %i)
    '\n'
    'T'
    'h'
    ...
    'w'
    'n'
    '\n'
    

    您的字符阅读循环将换行符视为第一个字符。它将 null 插入输出缓冲区,将 prevCharacterIsSpace 设置为 false,然后继续。如果您的文件格式与我上面的格式匹配,您可能想通过在读入 'width' 后立即“吃掉”'\n' 来解决这个问题。

    请注意isspace 函数对换行返回 true,所以现在换行被放入输出缓冲区的下一个槽,并且字计数器递增(如果您取消注释程序底部的 printf,您应该看到这种效果)。修复可能只是将if (isspace(c)) 变成else if (isspace(c))

    另一个问题是您将文件中的每一行都复制到同一个缓冲区中。因此,除了输入的最后一行之外,您无法显示任何内容。您可能需要将打印代码放入 if (c == '\n') { 块中。这将允许您在阅读时打印每一行。

    这里的代码都没有处理打印右对齐文本,但一个简单的解决方案是一个小循环:

    for (i = 0; i < (width - buff_offset); i++)
        printf(" ");
    

    在打印输出之前直接插入。

    【讨论】:

    • 我接受了您的建议,并将我的更改包含在上面的代码中。输出右对齐,但打印不正确。我不确定如何描述输出,它几乎看起来“不完整”。
    【解决方案2】:

    首先不要两次调用fopen("hollo_man.txt", "r"),检查if中的指针。

    那么你应该逐字阅读文件:

    char words[1024];
    char * next_word = words;
    while(fscanf(ptr_file, "%s", next_word) {
    

    数一数他们的长度

    size_t word_length = strlen(next_word);
    next_word += word_length + 1;
    

    当你达到必要的宽度时打印它们:

    total_length +=  word_length;
    if (total_length > maxColumns) {
         size_t extra_spaces = total_length - word_length - 2;
    

    这有帮助吗?

    这是一个完整的解决方案:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    void justify(FILE* in, FILE * out, int columns) {
        char words[1024];
        char * next_word = words;
    
        ssize_t total_length = 0;
        size_t num_words = 0;
    
        while (fscanf(in, "%s", next_word) == 1) {
            size_t word_length = strlen(next_word);
            next_word += word_length + 1;
            num_words++;
            total_length += word_length;
    
            if (total_length + num_words > columns) {
    
                size_t spaces_needed = columns - (total_length - word_length);
    
                int minspoaces = 1;
                if (num_words > 2) // avoids nasty floating point exception if no two words fit on a line
                    minspoaces = spaces_needed / (num_words - 2);
    
    
                char * word_print = words;
    
                size_t chars_printed = fprintf(out, "%s",word_print);
                word_print += strlen(word_print) + 1;
                size_t spaces_printed = 0;
                ssize_t words_to_print = num_words - 2;
    
                fflush(out);
    
                while (words_to_print > 0) {
                    int spaces_to_print = minspoaces;
                    if (((spaces_needed - spaces_printed) % words_to_print) * 2 >= words_to_print) // spreads spaces out along the line
                        spaces_to_print++;
                    spaces_printed += spaces_to_print;
                    words_to_print--;
                    chars_printed += fprintf(out, "%*c%s", spaces_to_print, ' ', word_print);
                    word_print += strlen(word_print) + 1;
                    fflush(out);
                }
                fprintf(out, "\n");
    
                memmove(words, word_print, (total_length = strlen(word_print)) + 1);
                num_words = 1;
                next_word = words + total_length + 1;
            }
    
        }
    
        char * word_print = words;
        while (word_print != next_word) {
            word_print += fprintf(out, "%s ", word_print);
        }
    
        fprintf(out, "\n");
    }
    
    int main(int argc, char ** argv) {
    
        int columns = atoi(argv[1]);
    
        FILE * in = stdin;
    
        if (argc >= 3 && argv[2]) {
            in = fopen(argv[2], "r");
            if (!in) {
                perror("fopen");
                return -1;
            }
        }
    
        justify(in, stdout, columns);
    
    }
    

    【讨论】:

    • 当我尝试分配 total_length += word_length 得到以下 'error:program1.c:61:23: error: invalid '+=' at end of declaration; did you mean '='? size_t total_length += word_length;
    • += 仅在更改值时有效。这意味着total_length = total_length + word_length+= 在初始化程序中无效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多