在C中跳过特定行并存储变量特定变量

时间:2017-05-10 21:47:44

标签: c fgets lines fgetc

这是一个简单的问题,但我似乎无法弄明白。我需要一些帮助。我有一个名为programFile的文件,如下所示:

start mul val1
<--tab-->ldb #2
<--tab-->addr A B
<--tab-->float
loop lda #1
<--tab-->sta val2
<--tab-->j loop
val1 word 12
val2 word 0

我想只使用不以标签开头的行并对它们执行某些操作(现在我只想打印该行中的第一个单词),因此只有行start mul val1,{{ 1}},loop lda #1val1 word 12。输出应为:

val2 word 0

最后,我还想采用以标签开头的行并对它们做些不同的事情,但这是我尝试解决问题的不良尝试:

start
loop
val1
val2

这是我的输出:

while(ch = fgetc(programFile) != EOF){
    if(ch == '\t'){
        while(ch != '\n'){
            ch = fgetc(programFile);
        }
    }else{
        fscanf(programFile, "%s", symbol);
        printf("%s\n", symbol);
    }
}

3 个答案:

答案 0 :(得分:1)

继续评论,虽然使用面向字符的输入函数(例如fgetcgetc)没有任何问题,但需要处理& #34;行&#34; 数据,您可以更好地使用C库(fgets)或POSIX提供的面向行的输入函数( getline)然后解析每行所需的信息。

为什么呢?基本上,方便和效率。面向行的输入函数提供缓冲读取(每次读取多个字符),对于大型输入文件,可以真正帮助文件I / O.接下来,无论内容如何,​​您都将阅读整行(如果使用fgets时有足够的存储空间 - 否则您将读取多个块,直到读完整行; getline将自动分配(并重新分配)足够的存储来保存每一行)。

然后您拥有sscanfstrtokstrsepstrstrstrchr等工具,您可以解析所需的任何内容存储的行。 (你也可以总是使用简单的指针算术来解析任何带有指针或指针对的行,&#34; 走绳子 &#34;然后比较每个字符)存储字符串中每个字符的内存操作比同时对每个字符执行相同的操作快几个数量级。

当您担心每一行的开头字符时,您只需要将line[0](或简称*line)与您要查找的任何字符进行比较。

以下是一个简单的示例,它从作为第一个参数给出的输入文件名中读取(或者从stdin读取,默认情况下,如果没有给出文件名),然后测试每行的开始字符。如果该行以tab开头,则只会输出前面带有tab的行(在通过输出tab从文件中跳过line + 1之后)后跟{{ 1}}(你可以随意处理这些行,或者完全跳过它们),否则它将输出行本身后跟-- begins with tab。处理不同的前缀线完全取决于您。您可以构建一个包含每个不同类型行的指针数组,或者使用包含指针数组中的命令和选项卡式内容的结构来保留行关联(哪些命令与哪些选项卡一起使用),如果需要的话。

关于面向行的输入函数的另一个注意事项是它们读取直到并包括尾随-- no tab。您通常不希望存储'\n'悬挂在两端的字符串,因此您需要通过使用 nul-terminatedating字符覆盖尾随newlines来修剪newlines < / em>的。该示例通过使用'\n'获取每行的长度,然后使用strlen(相当于字符newline)覆盖0来完成此操作。我不想打字......

'\0'

输入文件

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

#define MAX 64

int main (int argc, char **argv) {

    char line[MAX] = "";
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    while (fgets (line, MAX, fp))   /* read each line in file  */
    {
        size_t len = strlen (line); /* get the length */

        if (line[len - 1] == '\n')  /* check for trailing '\n' */
            line[--len] = 0;        /* overwrite with nul-byte */

        if (*line == '\t') {        /* if first char is '\t'   */
            printf ("\t%s - begins with tab\n", line + 1);
            continue;
        }

        printf ("%s - no tab\n", line);     /* line has no tab */
    }

    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    return 0;
}

示例使用/输出

$ cat dat/tabfile.txt
start mul val1
        ldb #2
        addr A B
        float
loop lda #1
        sta val2
        j loop
val1 word 12
val2 word 0

正如评论中所指出的,如果您的意图是解析不是以$ ./bin/filehandletab <dat/tabfile.txt start mul val1 - no tab ldb #2 - begins with tab addr A B - begins with tab float - begins with tab loop lda #1 - no tab sta val2 - begins with tab j loop - begins with tab val1 word 12 - no tab val2 word 0 - no tab 开头的行中的第一个单词,那么您只需使用tab找到第一个单词{{1} },暂时终止strchr使用该命令的行,然后恢复space,以便在需要时可以再次解析该字符串,例如

space

或者,编写相同的行终止,删除space和重复的while (fgets (line, MAX, fp)) { char *p = NULL; size_t len = strlen (line); ... if (*line == '\t') { /* if first char is '\t' */ printf ("\t%s - begins with tab\n", line + 1); continue; } if ((p = strchr (line, ' '))) { /* find first ' ' */ *p = 0; /* terminate at p */ printf ("%s - no tab\n", line); /* output line */ *p = ' '; /* restore ' ' */ } else printf ("%s - no tab\n", line); /* s has no tab */ } ,您可以执行以下操作:更紧凑,但可读性更低的代码(完全取决于您) ):

if...else...

示例使用/输出

printf

仔细看看,如果您有任何其他问题,请告诉我。

答案 1 :(得分:0)

我想你可能会使用四个&#39; &#39;而不是&#39; \ t&#39;在ldb,addr,float,stat,j之前。以下可能有效。

$query = $this->createQueryBuilder('message')
    ->where('message.creator = :username or message.receiver = :username')
    ->leftJoin('message.replies', 'replies')
    ->andWhere('replies.user = :username')
    ->setParameter('username', $username);

if (some_condition) {
    $query->andWhere('some_property');
}

if (some_other_condition) {
    $query->andWhere('some_property');
}

return $query->getQuery()->getResults();

答案 2 :(得分:0)

要么读完整行并解析它们,要么读取字符来驱动有限状态机,如:

#include <stdio.h>
int main(void)
{
int ch, state;

for (state =0; ; ) {
        ch = getc(stdin) ;
        if (ch==EOF) break;
        switch(state) {
        case 0: /* initial */
                if (ch == '\t') {state = 2; continue; }
                if (ch == '\n') { continue; }   /* empty line */
                state = 1;
                break;        /* break will emit the character */
        case 1: /* first word on the line */
                if (ch== ' ') {ch = '\n'; state =2; break; }
                if (ch== '\n') {state =0; break; }
                break;
        case 2: /* ignore until EOL */
                if (ch== '\n') {state =0; continue; }
                continue;
                }
        putc(ch, stdout);
        }
return 0;
}