在C和通用数组中对齐文本

时间:2015-05-31 10:34:03

标签: c arrays

我试图从文件中完全证明(左右列对齐)输入,这就是我提出的。输入文件有嵌入的命令,所以从下面的伪输出开始我在company's行开始对齐并在telephone结束。正如你所看到的,它随机地连接了两条读出的行。有人可以告诉我它为什么要这样做吗?我的输入文件中肯定有换行符,因为我仔细检查了它们的输入。

另外,我如何执行以下操作:检查我的读取行是否适合我的输出数组(40个字符)?如果它不是我想要将溢出的字符串移动到下一行或字符串(如果它更容易)。这个问题不是我第一个问题所必需的,但我真的想让输出尽可能好,而且我不知道如何限制并将读取线溢出到下一个输出数组。 / p>

Since it began to escape from AT&T's Bell Laboratories in
the early 1970's, the success of the UNIX
operating system has led to many different
versions: recipients of the (at that time free) UNIX system
code all began developing their own different
versions in their own different ways for use and sale.
    Universities, research
institutes, government bodies and computer
companies  all began using the powerful 
UNIX      system to develop many of the 
technologies  which today are part of a 
UNIX     system. Computer aided design, 
manufacturing  control systems,laboratorysimulations,even   the Internet itself, 
all  began life with and because of UNIX 
Today,  without UNIX systems, the Internewould         come to a screeching halt.
Most telephone calls could not be made,
electronic commerce would grind to a halt and
there would have never been "Jurassic Park"! 

以下是我在另一个函数中使用fgets传递读取文件行的​​对齐函数。 printf行仅用于调试。

void justify(char strin[]){

int i = 0;  //strin iterator 
int j = 0;  //out iterator

int endSpaces = LINE + 1 - strlen(strin);
int voids = countwords(strin) - 1;

printf("Voids: %d\n", voids);
printf("Input: %s", strin);

//No words in line, exit
if (voids <= 0)
    return;

//How many to add between words
int addEvenly = endSpaces/voids;
int addUnevenly = endSpaces % voids;

printf("space to distribute: %d  evenly: %d unevenly: %d\n", endSpaces, addEvenly, addUnevenly);

//Copy space left of array to output
while (strin[i] == ' '){
    outLine[j++] = ' ';
    i++;
}

//One word at a time
while (endSpaces > 0 || addUnevenly > 0){

    //Copy letters into out
    while (strin[i] != ' '){
        outLine[j] = strin[i];
        i++;
        j++;
    }

    //Add the necessary spaces between words
    if (addEvenly > 0){
        for (int k = 0; k < addEvenly; k++){
            outLine[j++] = ' ';
        }
    }

    //Distribute to the left
    if (addUnevenly > 0){
        outLine[j++] = ' ';
        endSpaces--;
        addUnevenly--;
    }

    printf("Output: %s\n\n", outLine);
    endSpaces = endSpaces - addEvenly;

    //Finish copying rest of input to output when no more spaces to add
    if (endSpaces == 0 && addUnevenly == 0){
        while (strin[i] != '\0')
            outLine[j++] = strin[i++];

        printf("Output 2: %s\n", outLine);
    }
}
fprintf(out, "%s", outLine);
}

3 个答案:

答案 0 :(得分:1)

你非常接近 - 但你忘记了一件事!

将一个单词复制到outLine后,您插入正确数量的其他空格,然后继续下一个单词&#39;。但是,此时输入指针i仍然位于先前复制的单词的末尾(因此它指向紧随其后的第一个空格)。然后测试while (strin[i] != ' ')立即失败,并再次在该点插入额外的空格。这种情况一直持续到你没有要添加的空格为止,最后你会添加未处理的内容,这是&#34;字符串的其余部分&#34;。

修复很简单:将单词复制到outLine后,也复制原始空间,以便更新i迭代器以指向下一个字。

//One word at a time
while (endSpaces > 0 || addUnevenly > 0)
{
    //Copy letters into out
    while (strin[i] != ' ')
    {
        outLine[j] = strin[i];
        i++;
        j++;
    }

    //Copy original spaces into out <-- FIX!
    while (strin[i] == ' ')
    {
        outLine[j] = strin[i];
        i++;
        j++;
    }

有了这个,您的代码完全按照您的意图运行。输出:

|Since    it    began    to    escape    from    AT&T's    Bell    Laboratories   in|
|the       early       1970's,       the       success       of       the       UNIX|
|operating        system        has        led        to        many       different|
|versions:    recipients    of    the    (at    that    time   free)   UNIX   system|
|code        all        began       developing       their       own       different|
|versions     in     their    own    different    ways    for    use    and    sale.|
|    Universities,                                                          research|
|institutes,            government           bodies           and           computer|
|companies           all          began          using         the         powerful |
|UNIX              system        to        develop        many        of        the |
|technologies          which        today        are        part        of        a |
|UNIX                system.            Computer            aided           design, |
|manufacturing   control  systems,laboratorysimulations,even   the Internet itself, |
|all        began       life       with       and       because       of       UNIX |
|Today,   without  UNIX systems, the Internewould         come to a screeching halt.|
|Most         telephone         calls        could        not        be        made,|
|electronic       commerce       would       grind      to      a      halt      and|
|there        would        have       never       been       "Jurassic       Park"! |

可能的改进

合理的行不应该开始与空格(你的Copy space left of array to output部分)。只需在那里增加指针:

//Copy space left of array to output
while (strin[i] == ' ')
{
//  outLine[j++] = ' ';
    i++;
    endSpaces++;
}

(并将How many to add between words的计算移到此下方,因为它会更改endSpaces。)

最后的空间也是如此。您可以在开始时调整endSpaces

int l = strlen(strin);
while (l > 0 && strin[l-1] == ' ')
{
    l--;
    endSpaces++;
}

并禁止将尾部空格复制到底部的outLn。 (这需要一些额外的修补,我第一次做不到。)

在输入字符串中忽略内部更为简洁,但需要更多代码。

实施这三项后,你会得到一个稍微整洁的输出:

|Since    it    began    to    escape    from    AT&T's    Bell    Laboratories   in|
|the       early       1970's,       the       success       of       the       UNIX|
|operating        system        has        led        to        many       different|
|versions:    recipients    of    the    (at    that    time   free)   UNIX   system|
|code        all        began       developing       their       own       different|
|versions     in     their    own    different    ways    for    use    and    sale.|
|Universities,                                                              research|
|institutes,            government           bodies           and           computer|
|companies          all          began          using          the          powerful|
|UNIX          system         to         develop         many         of         the|
|technologies         which         today         are        part        of        a|
|UNIX             system.             Computer             aided             design,|
|manufacturing   control  systems,laboratorysimulations,even  the  Internet  itself,|
|all        began        life       with       and       because       of       UNIX|
|Today,   without  UNIX  systems,  the  Internewould  come  to  a  screeching  halt.|
|Most         telephone         calls        could        not        be        made,|
|electronic       commerce       would       grind      to      a      halt      and|
|there        would        have        never       been       "Jurassic       Park"!|

这种一行一行方法的一个缺点是,在线路溢出之前,不能轻易地重写以收集输入。为此,您需要:

  1. 跳过所有空格并返回指向 next 字的指针的例程。
  2. 一个例行程序,它会读取字词,直到某行“过满”为止。 - 也就是说,空格的单词数加上(单词数 - 1)大于LINE值。这使用例程#1并输出恰好一条对齐线。
  3. 您需要将main中的字符串的位置和数量传递给这两个例程,并检查是否位于单个输入行或整个输入数组的末尾。

答案 1 :(得分:1)

星期天我创建了一个函数(justifyline()),能够证明并缩进你给它作为输入的一行。它输出一个包含对齐(格式化)文本和任何最终文本余数的缓冲区;这样的余数可以用作函数justifyline()的输入。

在此步骤之后,我使用下面的文件(text.txt)来测试这种功能的行为。该测试表明我需要在行之间使用自动换行。然后我写了函数formatLineByLine()。函数formatLineByLine()并不关心空行。

文本文件(text.txt):(我使用了问题中的文字试图纠正它,但并非所有我都纠正过,那么输入文件就会受到这种情况的影响!)

Since it began to escape from AT&T's
Bell Laboratories in the early 1970's,
the success of the UNIX operating system
has led to many different versions:
recipients of the (at that time free)
UNIX system code all began developing
their own different versions in their
own different ways for use and sale.

Universities, research institutes,
government bodies and computer companies
all began using the powerful UNIX system
to develop many of the technologies which
today are part of a UNIX system.

Computer aided design, manufacturing
control systems, laboratory simulations,
even the Internet itself, all began life
with and because of UNIX Today, without
UNIX systems, the Internet would come to a
screeching halt. Most telephone calls
could not be made, electronic commerce
would grind to a halt and there would
have never been "Jurassic Park"!

函数formatLineByLine()

的输出
ABCDE12345678901234567890123456789012345
     Since  it  began  to  escape   from
     AT&T's  Bell  Laboratories  in  the
     early  1970's,  the  success of the
     UNIX  operating  system  has led to
     many different versions: recipients
     of  the  (at  that  time free) UNIX
     system  code  all  began developing
     their  own  different  versions  in
     their  own  different  ways for use
     and  sale.  Universities,  research
     institutes,  government  bodies and
     computer companies all began  using
     the powerful UNIX system to develop
     many  of  the  technologies   which
     today are  part of  a UNIX  system.
     Computer       aided        design,
     manufacturing   control    systems,
     laboratory  simulations,  even  the
     Internet  itself,  all  began  life
     with  and  because  of  UNIX Today,
     without UNIX systems, the  Internet
     would  come  to  a screeching halt.
     Most telephone  calls could  not be
     made,  electronic  commerce   would
     grind  to  a  halt  and there would
     have never been "Jurassic Park"!   

另一个步骤是每个段落使用一个段落进行辩护。然后我写了函数justifyParagraph()。函数formatInParagraphs()读取文件text.txt并使用函数justifyParagraph()将其打印出来。

函数formatInParagraphs()

的输出
ABCDE12345678901234567890123456789012345
          Since it began to escape  from
     AT&T's  Bell  Laboratories  in  the
     early  1970's,  the  success of the
     UNIX  operating  system  has led to
     many different versions: recipients
     of  the  (at  that  time free) UNIX
     system  code  all  began developing
     their  own  different  versions  in
     their  own  different  ways for use
     and sale.                          

          Universities,         research
     institutes,  government  bodies and
     computer companies all began  using
     the powerful UNIX system to develop
     many  of  the  technologies   which
     today are part of a UNIX system.   

          Computer     aided     design,
     manufacturing   control    systems,
     laboratory  simulations,  even  the
     Internet  itself,  all  began  life
     with  and  because  of  UNIX Today,
     without UNIX systems, the  Internet
     would  come  to  a screeching halt.
     Most telephone  calls could  not be
     made,  electronic  commerce   would
     grind  to  a  halt  and there would
     have never been "Jurassic Park"!   

函数justifyline()能够使用缩进(参数size_t indent)创建对齐的缓冲区,并在单词之间使用单个空格(参数int nospacing作为1发送。) / p>

函数justifyParagraph()能够创建一个带有行缩进(参数:size_t indent)和第一行缩进(参数:size_t indentstart)的对齐缓冲区。当NULL输出缓冲区被发送到函数时(参数char **outbuf发送为NULL),可以直接打印格式化的输出。函数生成的最后一行可能是合理的(参数:int notFrmtLast发送为1)。

两个对齐函数,当参数char **outbuf指向NULL指针(* outbuf == NULL)时,使用malloc()分配内存。在这种情况下,您必须在使用后释放缓冲区。如果此参数作为NULL传递给函数justifyParagraph(),则该函数将打印详细的输出,如果将outbuf作为NULL传递给函数justifyline(),则该函数将返回错误。

代码如下。此代码的一个问题是,在某些情况下,应使用与strlen()不同的函数计算字符串的长度。要避免此问题,您可以将这些函数用于单词之间只有一个空格的行。这样的问题会影响函数justifyParagraph()formatLineByLine()

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

int justifyLine(char *inbuf, char **outbuf, size_t linelen, char ** endptr, size_t indent, int nospacing);
int justifyParagraph(char *inbuf,char **outbuf,size_t linelen,size_t indentstart,size_t indent,int notFmtLast);

int formatLineByLine(FILE *f, size_t linelen,size_t indent, int notFrmtLast);
int formatInParagraphs(FILE *f, size_t linelen,size_t indentstart,size_t indent, int notFrmtLast);

int justifyParagraph(char *inbuf,char **outbuf,size_t linelen,size_t indentstart,size_t indent,int notFmtLast)
{
    char *optr=NULL,*endp=NULL;
    size_t len,s;
    int retval,nf;

    for(;;) { //Error control loop
        if (inbuf==NULL) {
            retval=0x10;break;
        }

        if (indent+indentstart>linelen) {
            retval=0x20;break;
        }

        if (outbuf!=NULL) {
            if (*outbuf==NULL) {
                if ( (*outbuf=malloc(linelen+1))==NULL ){
                    retval=0x30;break;
                }
            }

            optr=*outbuf;
        }

        endp=inbuf;
        indent+=indentstart;
        len=linelen-indent;
        s=indentstart;nf=0;
        while( *endp!=0) {
            if (notFmtLast && strlen(endp)<linelen-indent)
                nf=1;
            if ( (retval=justifyLine(endp,&optr,linelen,&endp,
                                     indent,nf)) ) {
                retval|=0x40;break;
            }
            if (outbuf!=NULL) {
                optr+=strlen(optr);
                *optr++='\n';
                *optr=0;
            } else {
                puts(optr);
            }
            indent-=s;
            len+=s;
            s=0;
        }

        break;  //Close error ctrl loop!
    }

    if (outbuf==NULL && optr!=NULL)
        free(optr);

    return retval;
}

int justifyLine(char *inbuf,char **outbuf,size_t linelen, char ** endptr,size_t indent,int nospacing)
{
    size_t textlen,tmp;
    size_t spctoadd,spcodd,spcin;
    size_t timetoodd;
    size_t ibidx,obidx,k,wc;

    char * endp;
    char * outb=NULL;

    int retval=0;

    for(;;) { //Error control loop
        endp=inbuf;

        if (inbuf==NULL) {
            retval=1;break;
        }

        if (indent>linelen) {
            retval=2;break;
        }

        if (outbuf==NULL) {
            retval=3;break;
        }

        if (*outbuf==NULL) {
            if ( (*outbuf=malloc(linelen+1))==NULL ){
                retval=4;break;
            }
        }

        outb=*outbuf;

        //Leave right spaces
        while(*inbuf==' ')
            inbuf++;

        if (*inbuf==0) {
            endp=inbuf;
            *outb=0;
            break;  //exit from error loop without error!
        }

        linelen-=indent;

        //Count words and the minimum number of characters
        ibidx=0;
        wc=0;textlen=0;k=1;endp=NULL;
        while ( *(inbuf+ibidx)!=0 ) {
            if (*(inbuf+ibidx)==' ') {
                ibidx++;continue;
            }
            //There's a char!
            k=ibidx;    //last word start
            tmp=textlen;
            wc++;textlen++; //add the space after the words
            //textlen<linelen because textlen contains also the space after the word
//            while(textlen<=linelen && *(inbuf+ibidx)!=' ' && *(inbuf+ibidx) ) {
            while(*(inbuf+ibidx)!=' ' && *(inbuf+ibidx) ) {
                textlen++;ibidx++;
            }

            if (textlen>linelen+1) {                    
                endp=inbuf+k;
                textlen=tmp;
                wc--;
                break;
            }
        }

        textlen=textlen-wc;

        if (endp==NULL) {
            endp=inbuf+ibidx;
        }

        if (textlen<2) {
            *outb=0;
            break;  //exit from error loop without error!
        }

        //Prepare outbuf
        memset(outb,' ',linelen+indent);
        *(outb+linelen+indent)=0;

        ibidx=0;
        obidx=indent;
        if (wc>1) {
            if (!nospacing) {
                //The odds are max in number == wc-2
                spctoadd=linelen-textlen;
            } else {
                spctoadd=wc-1;
            }

            spcin=spctoadd/(wc-1);
            spcodd=spctoadd % (wc-1);
            if (spcodd)
                timetoodd=(wc-1)/spcodd;

            k=timetoodd;
            while(spctoadd) {
                while(*(inbuf+ibidx)!=' ') {
                    *(outb+obidx++)=*(inbuf+ibidx++);
                }
                obidx+=spcin;spctoadd-=spcin;
                if (spcodd && !(--k)) {
                    k=timetoodd;
                    spcodd--;
                    spctoadd--;
                    obidx++;
                }
                while(*(inbuf+ ++ibidx)==' ');
            }
        }

        while(*(outb+obidx) && *(inbuf+ibidx) && *(inbuf+ibidx)!=' ')
            *(outb+obidx++)=*(inbuf+ibidx++);

        //There're words longer then the line!!!
        if (*(inbuf+ibidx) && *(inbuf+ibidx)!=' ')
            endp=inbuf+ibidx;

        break;  //Terminate error ctrl loop.
    }

    if (endptr!=NULL)
        *endptr=endp;

    return retval;
}

int formatLineByLine(FILE *f, size_t linelen,size_t indent, int notFrmtLast)
{
    char text[250],*app;
    //justifyLine allocates memory for the line if the outbuf (optr) value is NULL
    char * optr=NULL;
    size_t j,k;

    //print a ruler
    for(j=0;j<indent;j++)
        printf("%c",'A'+(char)j);

    for(j=1;j<=linelen-indent;j++)
        printf("%c",'0'+(char)(j%10));
    printf("\n");

    //starts printing
    fseek(f,0,SEEK_SET);
    j=0;
    while(fgets(text+j,sizeof(text)-j,f)) {
        if ( (app=strrchr(text+j,'\n')) ) {
            *app=0;
        }

        k=strlen(text);
        if (strlen(text)<linelen-indent) {
            if (!*(text+k) && *(text+k-1)!=' ') {
                *(text+k++)=' ';
                *(text+k)=0;
            }
            j=k;
            continue;
        }

        app=text;
        do {
            //justifyLine allocates memory for the line if the outbuf (optr) value is NULL
            if ( justifyLine(app,&optr,linelen,&app,indent,0) ) {
                if (optr!=NULL)
                    free(optr);
                return 1;
            }
            printf("%s\n",optr);
            j=(*app!=0)?strlen(app):0;
        } while(j>linelen-indent);

        if (j) {
            strcpy(text,app);
            *(text+j++)=' ';
            *(text+j)=0;
        }
    }

    if (*text!=0 && j) {
        if ( justifyLine(text,&optr,linelen,NULL,indent,notFrmtLast) )
        {
            if (optr!=NULL)
                free(optr);
            return 2;
        }

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

    //justifyLine allocates memory for the line if the outbuf value is NULL
    if (optr!=NULL)
        free(optr);

    return 0;
}

int formatInParagraphs(FILE *f, size_t linelen,size_t indentstart,size_t indent, int notFrmtLast)
{
    char text[1024], *app;

    //To uncomment when you use the commented justifyParagraph line.
    //see below
    //char *outbuf=NULL;

    size_t j;

    //print a ruler
    for(j=0;j<indent;j++)
        printf("%c",'A'+(char)j);

    for(j=1;j<=linelen-indent;j++)
        printf("%c",'0'+(char)(j%10));
    printf("\n");

    //starts printing
    fseek(f,0,SEEK_SET);

    j=0;
    while(fgets(text+j,sizeof(text),f)) {
        if ( (app=strrchr(text+j,'\n')) ) {
            *app++=' ';*app=0;
        }

        if ( *(text+j)==' ' && !*(text+j+1) ) {
            //The following commented line allocates memory creating a paragraph buffer!
            //doesn't print the formatted line.
            //justifyParagraph(text,&outbuf,linelen,indentstart,indent,notFrmtLast);

            //This line directly print the buffer allocating and de-allocating
            //only a line buffer. It prints the formatted line.
            justifyParagraph(text,NULL,linelen,indentstart,indent,notFrmtLast);
            j=0;
            //To uncomment when you use the commented justifyParagraph line.
            // printf("%s\n\n",outbuf);
            puts("");
        } else {
            j+=strlen(text+j);
        }
    }

    return 0;
}

int main(void)
{
    FILE * file;

    file=fopen("text.txt","r");

    formatLineByLine(file,40,5,1);
    puts("");
    formatInParagraphs(file,40,5,5,1);

    fclose(file);

    return 0;
}

答案 2 :(得分:0)

我写了这个main,其中包含两个简单的方法来将文本居中排成一行。第一种方法只打印text变量而不修改它,第二种方法修改text变量然后打印它。 (这里的方法不是函数,代码包含两个可以在简单函数中轻松翻译的例子)

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

int main(void)
{
    char text[81],fmt[10];
    int linelen=80,tlen;
    int spacetocenter=0;

    printf("Insert text to center [max %lu char]:\n",sizeof(text)-1);
    if (scanf("%[^\n]",text)<1) {
        perror("scanf");
        return -1;
    }
    getchar();  //Leaves return from the buffer

    tlen=strlen(text);
    spacetocenter=(linelen-tlen)/2;
    if (spacetocenter<0) 
       spacetocenter=0;

    //Method one (this doesn't modify text)
    //This method directly prints the contents of text centered.
    //----------------------------------------------------------
    snprintf(fmt,sizeof(fmt),"%%%+ds\n",spacetocenter+tlen);
    //printf("%s\n",fmt); // prints the used format
    printf(fmt,text);

    //Method two (this modifies text)
    //This method modifies the contents of the variable text
    //----------------------------------------------------------
    memmove(text+spacetocenter,text,tlen+1);
    memset(text,' ',spacetocenter);
    printf("%s\n",text);

    return 0;
}

注意:

  • 应用第二种方法后tlen不再包含文本长度!
  • 该程序考虑80个字符的行,如果您需要更短/更长的行,则必须修改变量linelen的值。