【问题标题】:How to read a file until a character in C如何读取文件直到C中的一个字符
【发布时间】:2023-03-10 11:42:02
【问题描述】:

所以我有这个输入文件:

1 2 3 4 5 6 7
3 2 4 1 6 5 7
***
1 1 2
1 1 2
***end of input***

我想扫描前两行整数,然后对它们进行一些处理,然后跳过* 并扫描下一行整数,并对它们执行一些操作(就像一个循环,直到它读取* )。

我怎么能这样做?这是我的代码:

int main(){
int i = 0, j ;
int temp[100];
char c, buf[20];
FILE *fp;
fp = fopen("input.txt", "r");
    if (fp != NULL){

            while (1 == fscanf(fp, "%d ", &temp[i])){
                i++;
            }   
                            // do something with the integers
    }
    else{
        printf("Cannot open File!\n");   
    }

return 0;
}

所以问题是,我只能扫描前两行整数。我也想扫描*之后的整数。

【问题讨论】:

  • 结尾字符是什么?
  • 您遇到的具体问题是什么?
  • 听起来您需要(a)在“做某事”行之后添加代码以处理包含星号的行(例如使用fgets() 阅读),然后围绕@ 包裹另一个循环987654327@,'做某事'和'munch stars'代码重复直到EOF。理想情况下,您应该在遇到 EOF 后关闭该文件。删除格式字符串中%d 之后的空格也可能是明智的——原因很复杂,但尾随空格尤其会给交互式程序带来讨厌的行为。
  • 问题是,我只能扫描前两行整数。我也想扫描 * 之后的下一个整数。 @JonathanLeffler 可以帮助我并为此提供代码吗?一段时间循环
  • 是什么阻止了您在当前的 while 循环周围添加外部 while 循环并“做某事”代码来重复操作? “能帮我提供一个代码吗?” -- 那真的不是 SO 的意义所在。

标签: c file-io io fgets scanf


【解决方案1】:

评论:

听起来您需要 (a) 在“做某事”行之后添加代码以处理包含星号的行(例如使用 fgets() 阅读它),然后在 while 周围环绕另一个循环,“做某事” ' 和 'munch stars' 代码重复直到 EOF。理想情况下,您应该在遇到 EOF 后关闭该文件。删除格式字符串中%d 之后的空格也可能是明智的——原因很复杂,但尾随的空格尤其会给交互式程序带来讨厌的行为。

大纲:

if (fp != NULL)
{
    int c;
    do
    {
        i = 0;
        while (fscanf(fp, "%d", &temp[i]) == 1)
            i++;
        if (i > 0)  
            do_something(i, temp);
        while ((c = getc(fp)) != EOF && c != '\n')
            ;
    } while (c != EOF);
    fclose(fp);
}

我不经常使用 do ... while 循环,但它在这里工作正常,因为内部循环的主体没有做任何愚蠢的事情(就像假设有有效输入时没有' t)。如果有几行连续的星号,代码将正常工作,在它们之间什么都不做(因为i 每次都为零)。

请注意,我没有使用fgets() 来读取星号线,但可以这样做:

if (fp != NULL)
{
    char line[4096];
    do
    {
        i = 0;
        while (fscanf(fp, "%d", &temp[i]) == 1)
            i++;
        if (i > 0)  
            do_something(i, temp);
    } while (fgets(line, sizeof(line), fp) != 0);
    fclose(fp);
}

示例代码

无论使用上述两种解决方案中的哪一种,代码都以相同的方式处理示例数据:

#include <stdio.h>

static void do_something(int n, int *arr)
{
    printf("data (%d items):", n);
    for (int i = 0; i < n; i++)
        printf(" %d", arr[i]);
    putchar('\n');
}

int main(void)
{
    int i = 0;
    int temp[100];
    FILE *fp = fopen("input.txt", "r");
    if (fp != NULL)
    {
    char line[4096];
    do
    {
        i = 0;
        while (fscanf(fp, "%d", &temp[i]) == 1)
            i++;
        if (i > 0)  
            do_something(i, temp);
    } while (fgets(line, sizeof(line), fp) != 0);
    fclose(fp);
    }
    /*
    {
        int c;
        do
        {
            i = 0;
            while (fscanf(fp, "%d", &temp[i]) == 1)
                i++;
            if (i > 0)  
                do_something(i, temp);
            while ((c = getc(fp)) != EOF && c != '\n')
                ;
        } while (c != EOF);
        fclose(fp);
    }
    */
    else
    {
        printf("Cannot open File!\n");   
    }

    return 0;
}

输出

data (14 items): 1 2 3 4 5 6 7 3 2 4 1 6 5 7
data (6 items): 1 1 2 1 1 2

【讨论】:

  • 我尝试使用您的代码。它打印了我想要的结果,但它也打印了额外的输出编号。 IDK到底是从哪里来的。预期输出:3 2 4 7 5 6 1 2 1 1 输出:3 2 4 7 5 6 1 2 1 1 0 0 0 0 -67 blah blah
  • 在代码部分 where: if (i > 0) do_something(i, temp);而 ((c = getc(fp)) != EOF && c != '\n') ;我必须在 while 循环中放一些东西吗?
  • 否;空语句; 在该循环的主体中就足够了。分号单独一行以强调它是一个空语句;在与while 相同的行中包含分号是合法的,但很容易被忽略。你可以用(void)0;continue; 修饰分号,但是在一行上的分号适当缩进是编写代码的传统方式。
  • 错过了“最后一条评论被删”评论的更新。我不确定您为什么会从问题中引用的输入数据(以1 2 3 4 5 6 7 3 2 4 1 6 5 7 开头)中期望3 2 4 7 5 6 1 2 1 1。如果您想使用您拥有的替代示例输入文件以及您期望的输出来更新您的问题,那么我可以看到为什么我的程序会产生它的作用。
【解决方案2】:

也许你可以做这样的事情(需要 ctype.h):

int ch;
/* read file char by char til its end */
while ((ch = fgetc(file)) != EOF)
{
  if (isdigit(ch))
  {
    /* char is a digit */
    /* do s.th. with it */
    printf("digit=%d\n", (char)ch);
  }
  else if (ch == '\n')
  {
    /* new line */
    /* count lines or do s.th. else */
  }
}

我不太确定,你的问题是什么。也许这对你有点帮助。

编辑:您还可以使用简单的 if(-else) 语句检查每个字符是否为 '*'。

【讨论】:

    【解决方案3】:

    您做得很好,但唯一的问题是您没有阅读整个文件。你可以通过做一个简单的修改来实现这一点,比如......

    int main(){
    
        int i = 0, j;
    
        int temp[100];
    
        char c, buf[20];
    
        FILE *fp;
    
        fp = fopen("input.txt", "r");
    
        while ((c=getc(fp))!=EOF){  //here you are reading the whole file
    
            while (1 == fscanf(fp, "%d ", &temp[i])){
                i++;
            }   
            // do something with the integers
        }
    
        return 0;
    }
    

    【讨论】:

    • 欢迎来到 Stack Overflow。请尽快阅读About 页面。请注意,getc() 的返回值是 int,因此 c 应该是 int。像这样使用getc() 意味着将跳过第一个数字,我认为这不是一个好主意。
    猜你喜欢
    • 2011-02-08
    • 2020-03-19
    • 2017-04-27
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    • 2015-03-08
    • 2016-07-31
    • 1970-01-01
    相关资源
    最近更新 更多