给定管道的确切位置,使管道分隔子串

时间:2015-10-14 03:55:33

标签: c substring text-files c-strings

我搜索过,并没有得到一个非常有效的答案。虽然我知道那里仍然有很多答案。老实说,我找不到它,因为我是C / C ++的初学者。

我的问题是我有一个文本文件,其中的数据由管道分隔(' |')。实际上是一个日志文件。在每个条目中,事物由管道分隔(' |'),每个条目由新行(' \ n')分隔,它真的很长。所以我想做的是当用户给出一个序列sequence=[2,5,7]时,该函数应该能够读取该数组并仅给出以该管道位置开头的东西。所以这里它应该给文本文件中的第2,第5和第7个内容。这里是我使用的代码。由于某些我无法找到的原因,它无法正常工作。它只会使用' \ n'打印出结果文本文件。并且没有更多。它也是文件中的条目。

minorSeparatorChar是指定为' |'

的字符

majorSeparatorChar是以' \ n'

命名的字符

inFile输入文字文件

outFile输出文本文件

minSepCount次要分隔符计数

majSepCount主要分隔符计数

sequence是一个全局const int数组

void getFormattedOutput(char * inFile, char * outFile, char minorSeparatorChar,char majorSeparatorChar){

FILE *readFile,*writeFile;
int charactor=0, minSepCount=0, i=0,majSepCount = 0;
int flagMin = 0;
char charactorBefore = NULL;
readFile = fopen(inFile,"r");       // opens the file for reading
writeFile = fopen(outFile,"w");     // opens the file for writing

if (readFile==NULL || writeFile == NULL){
    printf("\nFile creation is not a sucess, Exiting program..\n");
    exit(0);
    }


while(charactor!=EOF){

    charactorBefore = charactor;
    if (charactor==minorSeparatorChar)
        flagMin=1;
    charactor = fgetc(readFile);
    if(charactorBefore == minorSeparatorChar){
        flagMin = 0;
        if (minSepCount==sequence[i]){
            fputc(charactor,writeFile);

            continue;
            }
        i++;

        minSepCount++;
    }

    else if (charactorBefore == majorSeparatorChar){
        minSepCount=0;
        i=0;
        majSepCount++;
        fputc('\n',writeFile);
        }       

    else{
        if(flagMin==1)
            fputc(charactor,writeFile);
        continue;
    }

}       

fclose(readFile);
fclose(writeFile);

}

例如,如果输入文件有

33|333|67|787|7889|9876554|56
20151001|0|0|0|0||94|71
1|94|71|1|94|71|1

如果我给出序列[2,5,6]

它应该打印到文件

67  9876554 56
 0       94 71
71       71  1

1 个答案:

答案 0 :(得分:1)

我最终得出结论,你的代码中有太多的标志,控件和变量,而且我无法做出他们所做的事情的头或尾,并决定重写代码。例如,我无法在你的代码中看到你如何知道序列中有多少个字段。

我用C11(C99)编写,但在这个程序中,这只是意味着我在需要时声明变量,而不是在函数的顶部。如果这是一个问题(C89 / C90),请将声明移到函数顶部。

我还发现使用的名称太长,以至于它们模糊了变量的目的。你可能认为我在另一个方向走得太远;更重要的是,你的教授(老师)可能会这么认为。就这样吧;名称是可替代的,全球搜索和替换效果很好。

我也没看到你的代码应该如何在字段之间插入半任意数量的空格,所以我实际上已经解决了这个问题。此代码在适当的位置输出字段分隔符(minor_sep - 长度减少minorSeparatorChar)和记录分隔符(major_sep - 从majorSeparatorChar减少)。

我注意到字段编号从代码中的字段0开始。我不相信你的代码会从字段0输出数据,但考虑到重写,这有点相切。

我最终得到了:

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

static const int sequence[] = { 2, 5, 7 };
static const int seqlen = 3;

static
void getFormattedOutput(char *inFile, char *outFile, char minor_sep, char major_sep)
{
    FILE *ifp = fopen(inFile, "r");  // opens the file for reading
    FILE *ofp = fopen(outFile, "w"); // opens the file for writing

    if (ifp == NULL || ofp == NULL)
    {
        printf("\nFile creation is not a success, Exiting program..\n");
        exit(0);
    }

    int c;
    int seqnum = 0;
    int fieldnum = 0;
    while ((c = getc(ifp)) != EOF)
    {
        if (c == major_sep)
        {
            putc(major_sep, ofp);
            fieldnum = 0;
            seqnum = 0;
        }
        else if (c == minor_sep)
        {
            if (seqnum < seqlen && fieldnum == sequence[seqnum])
            {
                putc(minor_sep, ofp);
                seqnum++;
            }
            fieldnum++;
        }
        else if (fieldnum == sequence[seqnum])
            fputc(c, ofp);
    }

    fclose(ifp);
    fclose(ofp);
}

int main(void)
{
    getFormattedOutput("/dev/stdin", "/dev/stdout", '|', '\n');
    return 0;
}

当我运行它时(我称之为split,虽然它不是一个好选择,因为还有一个标准命令split),我得到:

$ echo "fld0|fld1|fld2|fld3|fld4|fld5|fld6|fld7|fld8|fld9" | ./split 
fld2|fld5|fld7|
$ echo "fld0|fld1|fld2|fld3|fld4|fld5|fld6" | ./split 
fld2|fld5|
$

唯一可能的反对意见是存在字段终止符而不是字段分隔符。如您所见,终结器并不难实现;使它成为一个分隔符(因此在行的最后一个字段之后没有管道,即使该行没有与序列中的元素一样多的字段 - 请参阅第二个示例输出)也比较棘手。当代码读取应在第一个字段之后打印的字段的第一个字符时,代码需要输出分隔符。此代码实现了:

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

static const int sequence[] = { 2, 5, 7 };
static const int seqlen = 3;

static
void getFormattedOutput(char *inFile, char *outFile, char minor_sep, char major_sep)
{
    FILE *ifp = fopen(inFile, "r");  // opens the file for reading
    FILE *ofp = fopen(outFile, "w"); // opens the file for writing

    if (ifp == NULL || ofp == NULL)
    {
        printf("\nFile creation is not a success, Exiting program..\n");
        exit(0);
    }

    int c;
    int seqnum = 0;
    int fieldnum = 0;
    int sep = 0;
    while ((c = getc(ifp)) != EOF)
    {
        if (c == major_sep)
        {
            putc(major_sep, ofp);
            fieldnum = 0;
            seqnum = 0;
            sep = 0;
        }
        else if (c == minor_sep)
        {
            if (seqnum < seqlen && fieldnum == sequence[seqnum])
                seqnum++;
            fieldnum++;
            sep = minor_sep;
        }
        else if (fieldnum == sequence[seqnum])
        {
            if (sep != 0)
            {
                putc(sep, ofp);
                sep = 0;
            }
            putc(c, ofp);
        }
    }

    fclose(ifp);
    fclose(ofp);
}

int main(void)
{
    getFormattedOutput("/dev/stdin", "/dev/stdout", '|', '\n');
    return 0;
}

示例运行:

$ {
> echo "Afld0|Afld1|Afld2|Afld3|Afld4|Afld5|Afld6|Afld7|Afld8|Afld9"
> echo "Bfld0|Bfld1|Bfld2|Bfld3|Bfld4|Bfld5|Bfld6|Bfld7|Bfld8|Bfld9"
> echo "Cfld0|Cfld1|Cfld2|Cfld3|Cfld4|Cfld5|Cfld6|Cfld7|Cfld8|Cfld9"
> echo "Dfld0|Dfld1|Dfld2|Dfld3|Dfld4|Dfld5|Dfld6|Dfld7|Dfld8|Dfld9"
> echo "Efld0|Efld1|Efld2|Efld3|Efld4|Efld5|Efld6|Efld7|Efld8|Efld9"
> } | ./split
|Afld2|Afld5|Afld7
|Bfld2|Bfld5|Bfld7
|Cfld2|Cfld5|Cfld7
|Dfld2|Dfld5|Dfld7
|Efld2|Efld5|Efld7
$