给定管道的确切位置,获取由管道分隔的子字符串
Getting sub strings separated by pipes given the exact positions of the pipes
我进行了搜索,但没有得到有效的答案。尽管我知道那里仍然可能有很多答案。老实说,我找不到它,因为我是 C/C++ 的初学者。
我的问题是我有一个文本文件,其中包含用竖线 ('|') 分隔的数据。实际上是一个日志文件。在每个条目中,内容由竖线('|')分隔,每个条目由换行符('\n')分隔,这真的很长。所以我想做的是,当用户给出序列 sequence=[2,5,7]
时,该函数应该能够读取该数组并仅给出以该管道位置开头的内容。所以这里它应该将第 2、5 和 7 项内容放入文本文件中。下面是我使用的代码。由于某种我找不到的原因,它不起作用。它给出的结果文本文件仅使用 '\n' 打印出来,并且没有 more.Its 超过文件中的条目。
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
我最终得出结论,您的代码中有太多的标志、控件和变量,我无法弄清楚它们在做什么,因此决定重写代码。例如,我在您的代码中看不到您如何知道序列中有多少个字段。
我用 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
$
我进行了搜索,但没有得到有效的答案。尽管我知道那里仍然可能有很多答案。老实说,我找不到它,因为我是 C/C++ 的初学者。
我的问题是我有一个文本文件,其中包含用竖线 ('|') 分隔的数据。实际上是一个日志文件。在每个条目中,内容由竖线('|')分隔,每个条目由换行符('\n')分隔,这真的很长。所以我想做的是,当用户给出序列 sequence=[2,5,7]
时,该函数应该能够读取该数组并仅给出以该管道位置开头的内容。所以这里它应该将第 2、5 和 7 项内容放入文本文件中。下面是我使用的代码。由于某种我找不到的原因,它不起作用。它给出的结果文本文件仅使用 '\n' 打印出来,并且没有 more.Its 超过文件中的条目。
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
我最终得出结论,您的代码中有太多的标志、控件和变量,我无法弄清楚它们在做什么,因此决定重写代码。例如,我在您的代码中看不到您如何知道序列中有多少个字段。
我用 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
$